diff options
-rw-r--r-- | README | 542 | ||||
-rw-r--r-- | man/vmware.man | 37 | ||||
-rw-r--r-- | src/bits2pixels.c | 1415 | ||||
-rw-r--r-- | src/bits2pixels.h | 25 | ||||
-rw-r--r-- | src/guest_os.h | 30 | ||||
-rw-r--r-- | src/includeCheck.h | 3 | ||||
-rw-r--r-- | src/offscreen_manager.c | 132 | ||||
-rw-r--r-- | src/offscreen_manager.h | 25 | ||||
-rw-r--r-- | src/svga_limits.h | 57 | ||||
-rw-r--r-- | src/svga_reg.h | 456 | ||||
-rw-r--r-- | src/svga_struct.h | 40 | ||||
-rw-r--r-- | src/vm_basic_types.h | 173 | ||||
-rw-r--r-- | src/vm_device_version.h | 64 | ||||
-rw-r--r-- | src/vmware.c | 1406 | ||||
-rw-r--r-- | src/vmware.h | 265 | ||||
-rw-r--r-- | src/vmwarecurs.c | 445 | ||||
-rw-r--r-- | src/vmwarexaa.c | 549 |
17 files changed, 5664 insertions, 0 deletions
@@ -0,0 +1,542 @@ + +Copyright (C) 1999-2002 VMware, Inc. +All Rights Reserved + +The code here may be used/distributed under the terms of the standard +XFree86 license. + + + VMware SVGA Device Interface and Programming Model + -------------------------------------------------- + + +Include Files +------------- + +svga_reg.h + SVGA register definitions, SVGA capabilities, and FIFO command definitions. + +svga_limits.h + Included by svga_reg.h, defines maximum frame buffer and memory region + sizes. + +guest_os.h + Values for the GUEST_ID register. + +vm_basic_types.h + Common type definitions. + +vm_device_version.h + PCI vendor ID's and related information. + + +Programming the VMware SVGA Device +---------------------------------- + +1. Reading/writing a register: + + The SVGA registers are addressed by an index/value pair of 32 bit + registers in the IO address space. + + The 0710 VMware SVGA chipset (PCI device ID PCI_DEVICE_ID_VMWARE_SVGA) has + its index and value ports hardcoded at: + + index: SVGA_LEGACY_BASE_PORT + 4 * SVGA_INDEX_PORT + value: SVGA_LEGACY_BASE_PORT + 4 * SVGA_VALUE_PORT + + The 0405 VMware SVGA chipset (PCI device ID PCI_DEVICE_ID_VMWARE_SVGA2) + determines its index and value ports as a function of the first base + address register in its PCI configuration space as: + + index: <Base Address Register 0> + SVGA_INDEX_PORT + value: <Base Address Register 0> + SVGA_VALUE_PORT + + To read a register: + Set the index port to the index of the register, using a dword OUT + Do a dword IN from the value port + + To write a register: + Set the index port to the index of the register, using a dword OUT + Do a dword OUT to the value port + + Example, setting the width to 1024: + + mov eax, SVGA_REG_WIDTH + mov edx, <SVGA Address Port> + out dx, eax + mov eax, 1024 + mov edx, <SVGA Value Port> + out dx, eax + +2. Initialization + Check the version number + loop: + Write into SVGA_REG_ID the maximum SVGA_ID_* the driver supports. + Read from SVGA_REG_ID. + Check if it is the value you wrote. + If yes, VMware SVGA device supports it + If no, decrement SVGA_ID_* and goto loop + This algorithm converges. + + Map the frame buffer and the command FIFO + Read SVGA_REG_FB_START, SVGA_REG_FB_SIZE, SVGA_REG_MEM_START, + SVGA_REG_MEM_SIZE. + Map the frame buffer (FB) and the FIFO memory (MEM) + + Get the device capabilities and frame buffer dimensions + Read SVGA_REG_CAPABILITIES, SVGA_REG_MAX_WIDTH, SVGA_REG_MAX_HEIGHT, + and SVGA_REG_HOST_BITS_PER_PIXEL / SVGA_REG_BITS_PER_PIXEL. + + Note: The capabilities can and do change without the PCI device ID + changing or the SVGA_REG_ID changing. A driver should always check + the capabilities register when loading before expecting any + capabilities-determined feature to be available. See below for a list + of capabilities as of this writing. + + Note: If SVGA_CAP_8BIT_EMULATION is not set, then it is possible that + SVGA_REG_HOST_BITS_PER_PIXEL does not exist and + SVGA_REG_BITS_PER_PIXEL should be read instead. + + Report the Guest Operating System + Write SVGA_REG_GUEST_ID with the appropriate value from <guest_os.h>. + While not required in any way, this is useful information for the + virtual machine to have available for reporting and sanity checking + purposes. + + SetMode + Set SVGA_REG_WIDTH, SVGA_REG_HEIGHT, SVGA_REG_BITS_PER_PIXEL + Read SVGA_REG_FB_OFFSET + (SVGA_REG_FB_OFFSET is the offset from SVGA_REG_FB_START of the + visible portion of the frame buffer) + Read SVGA_REG_BYTES_PER_LINE, SVGA_REG_DEPTH, SVGA_REG_PSEUDOCOLOR, + SVGA_REG_RED_MASK, SVGA_REG_GREEN_MASK, SVGA_REG_BLUE_MASK + + Note: SVGA_REG_BITS_PER_PIXEL is readonly if + SVGA_CAP_8BIT_EMULATION is not set in the capabilities register. Even + if it is set, values other than 8 and SVGA_REG_HOST_BITS_PER_PIXEL + will be ignored. + + Enable SVGA + Set SVGA_REG_ENABLE to 1 + (to disable SVGA, set SVGA_REG_ENABLE to 0. Setting SVGA_REG_ENABLE + to 0 also enables VGA.) + + Initialize the command FIFO + The FIFO is exclusively dword (32-bit) aligned. The first four + dwords define the portion of the MEM area that is used for the + command FIFO. These are values are all in byte offsets from the + start of the MEM area. + + A minimum sized FIFO would have these values: + mem[SVGA_FIFO_MIN] = 16; + mem[SVGA_FIFO_MAX] = 16 + (10 * 1024); + mem[SVGA_FIFO_NEXT_CMD] = 16; + mem[SVGA_FIFO_STOP] = 16; + + Set SVGA_REG_CONFIG_DONE to 1 after these values have been set. + + Note: Setting SVGA_REG_CONFIG_DONE to 0 will stop the device from + reading the FIFO until it is reinitialized and SVGA_REG_CONFIG_DONE is + set to 1 again. + +3. SVGA command FIFO protocol + The FIFO is empty when SVGA_FIFO_NEXT_CMD == SVGA_FIFO_STOP. The + driver writes commands to the FIFO starting at the offset specified + by SVGA_FIFO_NEXT_CMD, and then increments SVGA_FIFO_NEXT_CMD. + + The FIFO is full when SVGA_FIFO_NEXT_CMD is one word before SVGA_FIFO_STOP. + + When the FIFO becomes full, the FIFO should be sync'd + + To sync the FIFO + Write SVGA_REG_SYNC + Read SVGA_REG_BUSY + Wait for the value in SVGA_REG_BUSY to be 0 + + The FIFO should be sync'd before the driver touches the frame buffer, to + guarantee that any outstanding BLT's are completed. + +4. Cursor + When SVGA_CAP_CURSOR is set, hardware cursor support is available. In + practice, SVGA_CAP_CURSOR will only be set when SVGA_CAP_CURSOR_BYPASS is + also set and drivers supporting a hardware cursor should only worry about + SVGA_CAP_CURSOR_BYPASS and only use the FIFO to define the cursor. See + below for more information. + +5. Pseudocolor + When the read-only register SVGA_REG_PSEUDOCOLOR is 1, the device is in a + colormapped mode whose index width and color width are both SVGA_REG_DEPTH. + Thus far, 8 is the only depth at which pseudocolor is ever used. + + In pseudocolor, the colormap is programmed by writing to the SVGA palette + registers. These start at SVGA_PALETTE_BASE and are interpreted as + follows: + + SVGA_PALETTE_BASE + 3*n - The nth red component + SVGA_PALETTE_BASE + 3*n + 1 - The nth green component + SVGA_PALETTE_BASE + 3*n + 2 - The nth blue component + + And n ranges from 0 to ((1<<SVGA_REG_DEPTH) - 1). + + +Drawing to the Screen +--------------------- + +After initialization, the driver can write directly to the frame buffer. The +updated frame buffer is not displayed immediately, but only when an update +command is sent. The update command (SVGA_CMD_UPDATE) defines the rectangle +in the frame buffer that has been modified by the driver, and causes that +rectangle to be updated on the screen. + +A complete driver can be developed this way. For increased performance, +additional commands are available to accelerate common operations. The two +most useful are SVGA_CMD_RECT_FILL and SVGA_CMD_RECT_COPY. + +After issuing an accelerated command, the FIFO should be sync'd, as described +above, before writing to the frame buffer. + +Addendum on 7/11/2000 +--------------------- + +SVGA_REG_FB_OFFSET and SVGA_REG_BYTES_PER_LINE may change after SVGA_REG_WIDTH +or SVGA_REG_HEIGHT is set. Also the VGA registers must be written to after +setting SVGA_REG_ENABLE to 0 to change the display to a VGA mode. + +Addendum on 11/29/2001 +--------------------- + +Actually, after changing any of SVGA_REG_WIDTH, SVGA_REG_HEIGHT, and +SVGA_REG_BITS_PER_PIXEL, all of the registers listed in the 'SetMode' +initialization section above should be reread. Additionally, when changing +modes, it can be convenient to set SVGA_REG_ENABLE to 0, change +SVGA_REG_WIDTH, SVGA_REG_HEIGHT, and SVGA_REG_BITS_PER_PIXEL (if available), +and then set SVGA_REG_ENABLE to 1 again. + + +Capabilities +------------ + +The capabilities register (SVGA_REG_CAPABILITIES) is an array of bits that +indicates the capabilities of the SVGA emulation. A driver should check +SVGA_REG_CAPABILITIES every time it loads before relying on any feature that +is only optionally available. + +Some of the capabilities determine which FIFO commands are available. This +table shows which capability indicates support for which command. + + FIFO Command Capability + ------------ ---------- + + SVGA_CMD_RECT_FILL SVGA_CAP_RECT_FILL + SVGA_CMD_RECT_COPY SVGA_CAP_RECT_COPY + SVGA_CMD_DEFINE_BITMAP SVGA_CAP_OFFSCREEN + SVGA_CMD_DEFINE_BITMAP_SCANLINE SVGA_CAP_OFFSCREEN + SVGA_CMD_DEFINE_PIXMAP SVGA_CAP_OFFSCREEN + SVGA_CMD_DEFINE_PIXMAP_SCANLINE SVGA_CAP_OFFSCREEN + SVGA_CMD_RECT_BITMAP_FILL SVGA_CAP_RECT_PAT_FILL + SVGA_CMD_RECT_PIXMAP_FILL SVGA_CAP_RECT_PAT_FILL + SVGA_CMD_RECT_BITMAP_COPY SVGA_CAP_RECT_PAT_FILL + SVGA_CMD_RECT_PIXMAP_COPY SVGA_CAP_RECT_PAT_FILL + SVGA_CMD_FREE_OBJECT SVGA_CAP_OFFSCREEN + SVGA_CMD_RECT_ROP_FILL SVGA_CAP_RECT_FILL + + SVGA_CAP_RASTER_OP + SVGA_CMD_RECT_ROP_COPY SVGA_CAP_RECT_COPY + + SVGA_CAP_RASTER_OP + SVGA_CMD_RECT_ROP_BITMAP_FILL SVGA_CAP_RECT_PAT_FILL + + SVGA_CAP_RASTER_OP + SVGA_CMD_RECT_ROP_PIXMAP_FILL SVGA_CAP_RECT_PAT_FILL + + SVGA_CAP_RASTER_OP + SVGA_CMD_RECT_ROP_BITMAP_COPY SVGA_CAP_RECT_PAT_FILL + + SVGA_CAP_RASTER_OP + SVGA_CMD_RECT_ROP_PIXMAP_COPY SVGA_CAP_RECT_PAT_FILL + + SVGA_CAP_RASTER_OP + SVGA_CMD_DEFINE_CURSOR SVGA_CAP_CURSOR + SVGA_CMD_DISPLAY_CURSOR SVGA_CAP_CURSOR + SVGA_CMD_MOVE_CURSOR SVGA_CAP_CURSOR + SVGA_CMD_DEFINE_ALPHA_CURSOR SVGA_CAP_ALPHA_CURSOR + SVGA_CMD_DRAW_GLYPH SVGA_CAP_GLYPH + SVGA_CMD_DRAW_GLYPH_CLIPPED SVGA_CAP_GLYPH_CLIPPING + +Note: SVGA_CMD_DISPLAY_CURSOR and SVGA_CMD_MOVE_CURSOR should not be used. +Drivers wishing hardware cursor support should use cursor bypass (see below). + +Other capabilities indicate other functionality as described below: + + SVGA_CAP_CURSOR_BYPASS + The hardware cursor can be drawn via SVGA Registers (without requiring + the FIFO be synchronized and will be drawn potentially before any + outstanding unprocessed FIFO commands). + + Note: Without SVGA_CAP_CURSOR_BYPASS_2, cursors drawn this way still + appear in the guest's framebuffer and need to be turned off before any + save under / overlapping drawing and turned back on after. This can + cause very noticeable cursor flicker. + + SVGA_CAP_CURSOR_BYPASS_2 + Instead of turning the cursor off and back on around any overlapping + drawing, the driver can write SVGA_CURSOR_ON_REMOVE_FROM_FB and + SVGA_CURSOR_ON_RESTORE_TO_FB to SVGA_REG_CURSOR_ON. In almost all + cases these are NOPs and the cursor will be remain visible without + appearing in the guest framebuffer. In 'direct graphics' modes like + Linux host fullscreen local displays, however, the cursor will still + be drawn in the framebuffer, still flicker, and be drawn incorrectly + if a driver does not use SVGA_CURSOR_ON_REMOVE_FROM_FB / RESTORE_TO_FB. + + SVGA_CAP_8BIT_EMULATION + SVGA_REG_BITS_PER_PIXEL is writable and can be set to either 8 or + SVGA_REG_HOST_BITS_PER_PIXEL. Otherwise the only SVGA modes available + inside a virtual machine must match the host's bits per pixel. + + Note: Some versions which lack SVGA_CAP_8BIT_EMULATION also lack the + SVGA_REG_HOST_BITS_PER_PIXEL and a driver should assume + SVGA_REG_BITS_PER_PIXEL is both read-only and initialized to the only + available value if SVGA_CAP_8BIT_EMULATION is not set. + + SVGA_CAP_OFFSCREEN_1 + SVGA_CMD_RECT_FILL, SVGA_CMD_RECT_COPY, SVGA_CMD_RECT_ROP_FILL, + SVGA_CMD_RECT_ROP_COPY can operate with a source or destination (or + both) in offscreen memory. + + Usable offscreen memory is a rectangle located below the last scanline + of the visible memory: + x1 = 0 + y1 = (SVGA_REG_FB_SIZE + SVGA_REG_BYTES_PER_LINE - 1) / + SVGA_REG_BYTES_PER_LINE + x2 = SVGA_REG_BYTES_PER_LINE / SVGA_REG_DEPTH + y2 = SVGA_REG_VRAM_SIZE / SVGA_REG_BYTES_PER_LINE + + +Cursor Handling +--------------- + +Starting with GSX Server Beta 3 (after 11/15/2000), hardware cursor support +was added. Actually, both a hardware cursor via the FIFO (SVGA_CAP_CURSOR) +and a hardware cursor via the SVGA registers (SVGA_CAP_CURSOR_BYPASS) were +added. SVGA_CAP_CURSOR was never available without SVGA_CAP_CURSOR_BYPASS and +the FIFO hardware cursor should never be used and may be removed without +warning in the future. + +Cursor bypass is programmed using the two FIFO commands SVGA_CMD_DEFINE_CURSOR +and SVGA_CMD_DEFINE_ALPHA_CURSOR in conjunction with the SVGA registers +SVGA_REG_CURSOR_ID, SVGA_REG_CURSOR_X, SVGA_REG_CURSOR_Y, and +SVGA_REG_CURSOR_ON. + +A driver defines an AND/XOR hardware cursor using SVGA_CMD_DEFINE_CURSOR to +assign an ID and establish the AND and XOR masks with the hardware. A driver +uses SVGA_CMD_DEFINE_ALPHA_CURSOR to define a 32 bit mask whose top 8 bits are +used to blend the cursor image with the pixels it covers. Alpha cursor +support is only available when SVGA_CAP_ALPHA_CURSOR is set. + +Once a cursor is defined, a driver can draw it to the screen at any time by +writing the SVGA_REG_CURSOR_ID register with the ID used when the cursor was +defined, writing SVGA_REG_CURSOR_X and SVGA_REG_CURSOR_Y with the location of +the cursor, and SVGA_CURSOR_ON_SHOW to SVGA_REG_CURSOR_ON. The drawing occurs +when SVGA_REG_CURSOR_ON is written. + +Writing SVGA_CURSOR_ON_HIDE to SVGA_REG_CURSOR_ON will turn the cursor off and +make it vanish from the display and, if present, from the framebuffer. +SVGA_CURSOR_ON_REMOVE_FROM_FB will ensure the cursor is not in the +framebuffer, but will only turn it off if there's no other way to remove it. +SVGA_CURSOR_ON_RESTORE_TO_FB is the complement to +SVGA_CURSOR_ON_REMOVE_FROM_FB. Whenever possible, the device will not put the +cursor in the framebuffer and Remove From / Restore To will be NOPs. + +Note: The cursor must be out of the frame buffer before the driver (or any +agent in the virtual machine) touches an overlapping portion of the frame +buffer, because it is actually drawn into the frame buffer memory in the +case of direct graphics mode (e.g. full screen mode on Linux). The cursor +does not have to be touched before issuing an accelerated command via the +command FIFO, this case is handled by the SVGA device. + +Note: If SVGA_CAP_CURSOR_BYPASS2 is not present, the driver must use +SVGA_CURSOR_ON_HIDE and SVGA_CURSOR_ON_HIDE to be certain the cursor is out of +the framebuffer. + + +Driver Version Numbers +---------------------- + +The SVGA drivers use the following convention for their version numbers: + +Version 10.0 - The first version that uses the FIFO +Version 10.1 - The version that uses the hardware cursor emulation via the FIFO +Version 10.2 - The version that uses the cursor that bypasses the FIFO +Version 10.3 - The version that can also support the 0405 chipset +Version 10.4 - The version that knows about SVGA_CAP_CURSOR_BYPASS2 +Version 10.5 - [Never released or well defined] +Version 10.6 - The version that knows about SVGA_CAP_8BIT_EMULATION +Version 10.7 - The version that knows about SVGA_CAP_ALPHA_CURSOR +Version 10.8 - The version that knows about SVGA_CAP_GLYPH +Version 10.9 - The version that knows about SVGA_CAP_OFFSCREEN_1 + +Note that this is merely the convention used by SVGA drivers written and +maintained by VMware, Inc. and describes the capabilities of the driver, not +the virtual hardware. An SVGA driver can only use the intersection of the +functionality it supports and the functionality available in the virtual SVGA +hardware. + + +Frequently Asked Questions +-------------------------- + +1. My driver doesn't display anything, what's going on? + +First check if you are issuing an SVGA_CMD_UPDATE after drawing to +the screen. Another check you can do is to run your driver in full +screen mode on a Linux host. In this case you are drawing directly +on the frame buffer, so what you draw to the screen will be immediately +visible. If nothing is visible in this case, then most likely your +driver hasn't mapped the frame buffer correctly. + +A discrepancy between what you get in full screen mode and what you +get in window mode indicates that you have a missing or incorrect +update command. + + +2. What's the difference between bitmaps and pixmaps? + +Pixmaps have the same depth as the screen, while bitmaps have depth one. +When a bitmap is drawn, the command also takes two colors, foreground and +background. The set bits in the bitmap are replaced with the foreground +color, and the unset bits are replaced with the background color. + +Pixmaps, on the other hand, can be directly copied to the screen. + + +3. What's the significance of the ROP in the commands SVGA_CMD_RECT_ROP_FILL, +SVGA_CMD_RECT_ROP_BITMAP_COPY, etc. ? + +The ROP in the ...ROP... commands is a raster operation. It has the same +significance (and encoding) as it does in X. The ROP value SVGA_ROP_COPY +means the source is copied to the destination, which makes these commands the +same as their non-ROP counterparts. The most commonly used raster operation +other than copy is probably SVGA_ROP_XOR, which combines the source and +destination using exclusive-or. + + +4. Tell me more about bitmaps and pixmaps. For example, the macro +SVGA_CMD_DEFINE_BITMAP has a field <scanlines>. What should this be +set to? Likewise with SVGA_CMD_DEFINE_PIXMAP. And when should the +SCANLINE macros be used? + +OK, I'll use pixmaps as an example. First you have to define the pixmap: + +#define SVGA_CMD_DEFINE_PIXMAP 6 + /* FIFO layout: + Pixmap ID, Width, Height, Depth, <scanlines> */ + +The ID is something you choose, which you subsequently use to refer to +this pixmap. It must be an integer between 0 and SVGA_MAX_ID. + +The width and height and depth are the dimensions of the pixmap. For now, +the depth of the pixmap has to match the depth of the screen. + +The scanlines are the pixels that make up the pixmap, arranged one row +at a time. Each row is required to be 32-bit aligned. The macros +SVGA_PIXMAP_SCANLINE_SIZE and SVGA_PIXMAP_SIZE give the size of a +single scanline, and the size of the entire pixmap, respectively, in +32-bit words. + +The second step is to use it: + +#define SVGA_CMD_RECT_PIXMAP_FILL 9 + /* FIFO layout: + Pixmap ID, X, Y, Width, Height */ + +The ID here is the one you chose when defining the pixmap. X, Y, +Width, and Height define a rectangle on the screen that is to be filled +with the pixmap. The pixmap is screen aligned, which means that the +coordinates in the pixmap are defined by the screen coordinates modulo +the pixmap dimensions. + +If you want a different alignment between the screen and the pixmap, +then you can use this command, which allows the pixmap coordinates to +be defined: + +#define SVGA_CMD_RECT_PIXMAP_COPY 11 + /* FIFO layout: + Pixmap ID, Source X, Source Y, Dest X, Dest Y, Width, + Height */ + +The Source X and Source Y are pixmap coordinates, and the Dest X and +Dest Y are screen coordinates. + + +5. OK, now it works briefly, then stops displaying anything. Also, +my log file is filled with lines like: + Unknown Command 0xff in SVGA command FIFO +What's happening? + +The most common problem at this point is that the FIFO gets out +of sync. This can happen if the amount of data in the FIFO doesn't +match what the VMware SVGA device expects. To track this down, try +to isolate the particular command which causes the problem. + +Another way this can happen is if the wraparound in the FIFO isn't +done correctly. Here is some example code for writing to the FIFO +(mem is an array of 32-bit integers that points to the FIFO memory +region): + +while (TRUE) { + fifo_min = mem[SVGA_FIFO_MIN] / 4; + fifo_max = mem[SVGA_FIFO_MAX] / 4; + fifo_next = mem[SVGA_FIFO_NEXT_CMD] / 4; + fifo_stop = mem[SVGA_FIFO_STOP] / 4; + + tmp_next = fifo_next+1; + if (tmp_next == fifo_max) + tmp_next = fifo_min; // Wraparound + + if (tmp_next == fifo_stop) { + sync_fifo(); // FIFO full + continue; // retry + } + + mem[fifo_next] = item; + mem[SVGA_FIFO_NEXT_CMD] = tmp_next * 4; + break; +} + +This isn't the most efficient code, but it should work. It's important +to do the increment with wraparound before the FIFO full check, and to +check FIFO full before updating the next command pointer. + + +6. My driver tries to switch modes and either nothing happens or the +display becomes completely garbled. What's going on? + +When you change modes, make very sure you reread all of the registers listed +above under SetMode. Getting the pitch (SVGA_REG_BYTES_PER_LINE) incorrect +will cause a heavily garbled display. Also, if you change +SVGA_REG_BITS_PER_PIXEL, make certain that SVGA_CAP_8BIT_EMULATION is present +in the SVGA_REG_CAPABILITIES register. Also, even with 8 bit emulation, the +driver must still use either 8 bpp or SVGA_REG_HOST_BITS_PER_PIXEL bpp, +nothing else. + + +7. Why does my driver's hardware cursor work when my virtual machine is in +window mode, but draw/erase incorrectly or in garbled locations in fullscreen +mode? + +You need to make sure you use SVGA_CURSOR_ON_REMOVE_FROM_FB and +SVGA_CURSOR_ON_RESTORE_TO_FB _every_ time your driver or the virtual machine +touches a region of the framebuffer that overlaps the cursor. If you forget +to remove it then it can show up when doing save-under operations or get mixed +in with other drawing. If you forget to restore it then can disappear. You +also need to make sure SVGA_CAP_CURSOR_BYPASS2 is available, or else you will +have to use SVGA_CURSOR_ON_SHOW and SVGA_CURSOR_ON_HIDE (which will flicker, +even in window mode), or else a software cursor. Newer version of the virtual +SVGA hardware will never put the hardware cursor in the framebuffer while in +window mode, so everything will appear to work correctly there. + + +8. Why do my accelerated glyphs look funny? OR Why does the fifo complain +about invalid commands when I draw accelerated glyphs? + +The bitmap data passed to SVGA_CMD_DRAW_GLYPH_* must not have any per-scanline +alignment. If there are any remaining bits left in the last byte of a scanline, +the first bits of the next scanline should use them. + +The bitmap data as a whole must be 4 byte aligned. + +$XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/README,v 1.5 2002/10/16 22:12:53 alanh Exp $ diff --git a/man/vmware.man b/man/vmware.man new file mode 100644 index 0000000..e2d707f --- /dev/null +++ b/man/vmware.man @@ -0,0 +1,37 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/vmware.man,v 1.2 2001/04/06 17:44:58 dawes Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH VMWARE __drivermansuffix__ __vendorversion__ +.SH NAME +vmware \- VMware SVGA video driver +.SH SYNOPSIS +.nf +.B "Section \*qDevice\*q" +.BI " Identifier \*q" devname \*q +.B " Driver \*qvmware\*q" +\ \ ... +.B EndSection +.fi +.SH DESCRIPTION +.B vmware +is an XFree86 driver for VMware virtual video cards. +.SH CONFIGURATION DETAILS +Please refer to XF86Config(__filemansuffix__) for general configuration +details. This section only covers configuration details specific to this +driver. +.PP +The driver auto-detects the version of any virtual VMware SVGA adapter. +.PP +The following driver +.B Options +are supported: +.TP +.BI "Option \*qHWCursor\*q \*q" boolean \*q +Enable or disable the HW cursor. Default: off. +.TP +.BI "Option \*qNoAccel\*q \*q" boolean \*q +Disable or enable acceleration. Default: acceleration is enabled. +.SH "SEE ALSO" +XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__) +.SH AUTHORS +Copyright (c) 1999-2001 VMware, Inc. diff --git a/src/bits2pixels.c b/src/bits2pixels.c new file mode 100644 index 0000000..416a1a7 --- /dev/null +++ b/src/bits2pixels.c @@ -0,0 +1,1415 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/bits2pixels.c,v 1.2 2002/12/11 17:07:58 dawes Exp $ */ +/* ********************************************************** + * Copyright (C) 1999-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ +#ifdef VMX86_DEVEL +char rcsId_bits2pixels[] = "Id: bits2pixels.c,v 1.6 2001/01/26 23:32:15 yoel Exp $"; +#else +#define FILECODE "F(814)" +#endif + +/* + * bits2pixels.c -- + * + * Emulation routines to convert bitmaps to pixmaps + */ + +#include "vm_basic_types.h" +#include "bits2pixels.h" + + +/* + * Local functions + */ + +static void RasterBitsToPixels8(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg); + +static void RasterBitsToPixels16(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg); + +static void RasterBitsToPixels24(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg); + +static void RasterBitsToPixels32(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg); + + +/* + *---------------------------------------------------------------------- + * + * vmwareRaster_BitsToPixels -- + * + * Convert a bitmap to a pixmap, converting 1 bits to the foreground + * color (fg) and 0 bits to the background color (bg). + * + * Results: + * Pixmap filled with pixels + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +vmwareRaster_BitsToPixels(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, int bytes_per_pixel, + uint32 width, uint32 height, uint32 fg, uint32 bg) +{ + switch (bytes_per_pixel) { + case 1: + RasterBitsToPixels8(bits, bits_increment, pix, pix_increment, + width, height, fg, bg); + break; + + case 2: + RasterBitsToPixels16(bits, bits_increment, pix, pix_increment, + width, height, fg, bg); + break; + + case 3: + RasterBitsToPixels24(bits, bits_increment, pix, pix_increment, + width, height, fg, bg); + break; + + case 4: + RasterBitsToPixels32(bits, bits_increment, pix, pix_increment, + width, height, fg, bg); + break; + } +} + + +/* + *---------------------------------------------------------------------- + * + * RasterBitsToPixels8 -- + * + * Convert a bitmap to a pixmap, converting 1 bits to the foreground + * color (fg) and 0 bits to the background color (bg), for an 8-bit + * pixmap + * + * Results: + * Pixmap filled with pixels + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +RasterBitsToPixels8(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg) +{ + uint8 *lpix, *lbits; + int i, j; + uint32 expbits = 0; /* Bits to be expanded */ + + for (i=0; i<height; i++) { + lpix = pix; + lbits = bits; + for (j = width ; j > 0; j -= 4) { + expbits = (*lbits >> 4) & 0x0f; + + if (j < 4) + break; + + switch (expbits) { + case 0: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 1: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 2: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 3: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 4: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 5: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 6: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 7: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 8: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 9: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 10: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 11: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 12: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 13: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 14: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 15: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + } + + expbits = *lbits & 0x0f; + + j -= 4; + if (j < 4) { + break; + } + + switch (expbits) { + case 0: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 1: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 2: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 3: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 4: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 5: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 6: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 7: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 8: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 9: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 10: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 11: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 12: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 13: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 14: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 15: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + } + lbits++; + } + + if (j > 0) { + *lpix++ = (expbits & 0x08) ? fg : bg; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x04) ? fg : bg; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x02) ? fg : bg; + j--; + } + } + } + + pix += pix_increment; + bits += bits_increment; + } + return; +} + + +/* + *---------------------------------------------------------------------- + * + * RasterBitsToPixels16 -- + * + * Convert a bitmap to a pixmap, converting 1 bits to the foreground + * color (fg) and 0 bits to the background color (bg), for a 16-bit + * pixmap + * + * Results: + * Pixmap filled with pixels + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +RasterBitsToPixels16(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg) +{ + uint16 *lpix; + uint8 *lbits; + int i, j; + uint32 expbits = 0; /* Bits to be expanded */ + + for (i=0; i<height; i++) { + lpix = (uint16 *)pix; + lbits = bits; + for (j = width; j > 0; j -= 4) { + expbits = (*lbits >> 4) & 0x0f; + + if (j < 4) + break; + + switch (expbits) { + case 0: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 1: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 2: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 3: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 4: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 5: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 6: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 7: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 8: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 9: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 10: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 11: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 12: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 13: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 14: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 15: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + } + + expbits = *lbits & 0x0f; + + j -= 4; + if (j < 4) { + break; + } + + switch (expbits) { + case 0: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 1: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 2: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 3: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 4: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 5: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 6: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 7: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 8: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 9: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 10: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 11: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 12: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 13: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 14: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 15: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + } + lbits++; + } + + if (j > 0) { + *lpix++ = (expbits & 0x08) ? fg : bg; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x04) ? fg : bg; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x02) ? fg : bg; + j--; + } + } + } + + pix += pix_increment; + bits += bits_increment; + } + return; +} + + + +/* + *---------------------------------------------------------------------- + * + * RasterBitsToPixels24 -- + * + * Convert a bitmap to a pixmap, converting 1 bits to the foreground + * color (fg) and 0 bits to the background color (bg), for a 24-bit + * pixmap + * + * Results: + * Pixmap filled with pixels + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +RasterBitsToPixels24(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg) +{ + uint8 *lpix, *lbits; + uint32 fgColor1, fgColor2, fgColor3; + uint32 bgColor1, bgColor2, bgColor3; + + int i, j; + uint32 expbits = 0; /* Bits to be expanded */ + + fgColor1 = fg & 0x000000ff; + fgColor2 = (fg >> 8) & 0x000000ff; + fgColor3 = (fg >> 16) & 0x000000ff; + + bgColor1 = bg & 0x000000ff; + bgColor2 = (bg >> 8) & 0x000000ff; + bgColor3 = (bg >> 16) & 0x000000ff; + + for (i=0; i<height; i++) { + lpix = pix; + lbits = bits; + for (j = width; j > 0; j -= 4) { + expbits = (*lbits >> 4) & 0x0f; + + if (j < 4) + break; + + switch (expbits) { + case 0: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 1: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 2: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 3: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 4: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 5: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 6: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 7: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 8: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 9: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 10: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 11: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 12: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 13: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 14: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 15: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + } + + expbits = *lbits & 0x0f; + + j -= 4; + if (j < 4) { + break; + } + + switch (expbits) { + case 0: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 1: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 2: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 3: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 4: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 5: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 6: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 7: + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 8: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 9: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 10: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 11: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 12: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 13: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + case 14: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = bgColor1; + *lpix++ = bgColor2; + *lpix++ = bgColor3; + break; + case 15: + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + *lpix++ = fgColor1; + *lpix++ = fgColor2; + *lpix++ = fgColor3; + break; + } + lbits++; + } + + if (j > 0) { + *lpix++ = (expbits & 0x08) ? fgColor1 : bgColor1; + *lpix++ = (expbits & 0x08) ? fgColor2 : bgColor2; + *lpix++ = (expbits & 0x08) ? fgColor3 : bgColor3; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x04) ? fgColor1 : bgColor1; + *lpix++ = (expbits & 0x04) ? fgColor2 : bgColor2; + *lpix++ = (expbits & 0x04) ? fgColor3 : bgColor3; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x02) ? fgColor1 : bgColor1; + *lpix++ = (expbits & 0x02) ? fgColor2 : bgColor2; + *lpix++ = (expbits & 0x02) ? fgColor3 : bgColor3; + j--; + } + } + } + + pix += pix_increment; + bits += bits_increment; + } + return; +} + + + +/* + *---------------------------------------------------------------------- + * + * RasterBitsToPixels32 -- + * + * Convert a bitmap to a pixmap, converting 1 bits to the foreground + * color (fg) and 0 bits to the background color (bg), for a 32-bit + * pixmap + * + * Results: + * Pixmap filled with pixels + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +RasterBitsToPixels32(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, + uint32 width, uint32 height, uint32 fg, uint32 bg) +{ + uint32 *lpix; + uint8 *lbits; + int i, j; + uint32 expbits = 0; /* Bits to be expanded */ + + for (i=0; i<height; i++) { + lpix = (uint32 *)pix; + lbits = bits; + for (j = width; j > 0; j -= 4) { + expbits = (*lbits >> 4) & 0x0f; + + if (j < 4) + break; + + switch (expbits) { + case 0: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 1: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 2: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 3: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 4: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 5: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 6: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 7: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 8: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 9: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 10: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 11: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 12: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 13: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 14: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 15: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + } + + expbits = *lbits & 0x0f; + + j -= 4; + if (j < 4) { + break; + } + + switch (expbits) { + case 0: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 1: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 2: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 3: + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 4: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 5: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 6: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 7: + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 8: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 9: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 10: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 11: + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + *lpix++ = fg; + break; + case 12: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = bg; + break; + case 13: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + *lpix++ = fg; + break; + case 14: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = bg; + break; + case 15: + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + *lpix++ = fg; + break; + } + lbits++; + } + + if (j > 0) { + *lpix++ = (expbits & 0x08) ? fg : bg; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x04) ? fg : bg; + j--; + if (j > 0) { + *lpix++ = (expbits & 0x02) ? fg : bg; + j--; + } + } + } + + pix += pix_increment; + bits += bits_increment; + } + return; +} diff --git a/src/bits2pixels.h b/src/bits2pixels.h new file mode 100644 index 0000000..585f6fc --- /dev/null +++ b/src/bits2pixels.h @@ -0,0 +1,25 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/bits2pixels.h,v 1.2 2002/12/11 17:07:58 dawes Exp $ */ +/* ********************************************************** + * Copyright (C) 1999-2001 VMware, Inc. + * All Rights Reserved + * Id: bits2pixels.h,v 1.4 2001/01/26 23:32:15 yoel Exp $ + * **********************************************************/ + +/* + * bits2pixels.h -- + * + * Drawing emulation routines + */ + +#ifndef _BITS2PIXELS_H_ +#define _BITS2PIXELS_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#include "includeCheck.h" + +void +vmwareRaster_BitsToPixels(uint8 *bits, uint32 bits_increment, + uint8 *pix, uint32 pix_increment, int bytes_per_pixel, + uint32 width, uint32 height, uint32 fg, uint32 bg); + +#endif /* _BITS4PIXELS_H_ */ diff --git a/src/guest_os.h b/src/guest_os.h new file mode 100644 index 0000000..dedebe0 --- /dev/null +++ b/src/guest_os.h @@ -0,0 +1,30 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/guest_os.h,v 1.1 2001/04/05 19:29:44 dawes Exp $ */ +/* ********************************************************* + * Copyright (C) 1999-2001 VMware, Inc. + * All Rights Reserved + * Id: guest_os.h,v 1.5 2001/01/26 23:32:15 yoel Exp $ + * **********************************************************/ + +#ifndef _GUEST_OS_H_ +#define _GUEST_OS_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#include "includeCheck.h" + +#define GUEST_OS_BASE 0x5000 + +#define GUEST_OS_DOS (GUEST_OS_BASE+1) +#define GUEST_OS_WIN31 (GUEST_OS_BASE+2) +#define GUEST_OS_WINDOWS95 (GUEST_OS_BASE+3) +#define GUEST_OS_WINDOWS98 (GUEST_OS_BASE+4) +#define GUEST_OS_WINDOWSME (GUEST_OS_BASE+5) +#define GUEST_OS_NT (GUEST_OS_BASE+6) +#define GUEST_OS_WIN2000 (GUEST_OS_BASE+7) +#define GUEST_OS_LINUX (GUEST_OS_BASE+8) +#define GUEST_OS_OS2 (GUEST_OS_BASE+9) +#define GUEST_OS_OTHER (GUEST_OS_BASE+10) +#define GUEST_OS_FREEBSD (GUEST_OS_BASE+11) +#define GUEST_OS_WHISTLER (GUEST_OS_BASE+12) + + +#endif diff --git a/src/includeCheck.h b/src/includeCheck.h new file mode 100644 index 0000000..8df4666 --- /dev/null +++ b/src/includeCheck.h @@ -0,0 +1,3 @@ +/* This space intentionally left blank. */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/includeCheck.h,v 1.3 2002/10/16 22:12:53 alanh Exp $ */ + diff --git a/src/offscreen_manager.c b/src/offscreen_manager.c new file mode 100644 index 0000000..68c8632 --- /dev/null +++ b/src/offscreen_manager.c @@ -0,0 +1,132 @@ +/* ********************************************************** + * Copyright (C) 1998-2002 VMware, Inc. + * All Rights Reserved + * **********************************************************/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/offscreen_manager.c,v 1.2 2002/12/11 17:07:58 dawes Exp $ */ + +#include "vmware.h" + +struct _Heap { + CARD8* ptr; + CARD32 size; + CARD32 maxSlots; + CARD32 startOffset; + SVGASurface* frontBuffer; + SVGASurface* slotsStart; + Bool clear; +}; + +static SVGASurface* FillInSurface(Heap* heap, SVGASurface* surface, + CARD32 width, CARD32 height, + CARD32 bpp, CARD32 pitch, CARD32 size, + CARD32 sizeUsed); + +Heap* +vmwareHeap_Create(CARD8* ptr, CARD32 size, CARD32 maxSlots, CARD32 startOffset, + CARD32 sWidth, CARD32 sHeight, CARD32 sBPP, CARD32 sPitch, + CARD32 sFbOffset) +{ + Heap* newHeap = malloc(sizeof (Heap)); + + newHeap->ptr = ptr; + newHeap->size = size - sizeof(SVGASurface); /* leave room for frontbuffer */ + newHeap->maxSlots = maxSlots; + newHeap->startOffset = startOffset; + + newHeap->frontBuffer = FillInSurface(newHeap, + (SVGASurface*)(ptr + newHeap->size), + sWidth, sHeight, sBPP, sPitch, + sHeight * sPitch, 0); + newHeap->frontBuffer->dataOffset = sFbOffset; + newHeap->frontBuffer->numQueued = newHeap->frontBuffer->numDequeued = 0; + + newHeap->slotsStart = (SVGASurface*)(newHeap->ptr + newHeap->size) - + newHeap->maxSlots; + newHeap->clear = FALSE; + vmwareHeap_Clear(newHeap); + + return newHeap; +} + +void +vmwareHeap_Destroy(Heap* heap) +{ + free(heap); +} + +void +vmwareHeap_Clear(Heap* heap) +{ + if (!heap->clear) { + memset(heap->slotsStart, 0, heap->maxSlots * sizeof (SVGASurface)); + heap->clear = TRUE; + } +} + +static SVGASurface* +FillInSurface(Heap* heap, SVGASurface* surface, CARD32 width, CARD32 height, + CARD32 bpp, CARD32 pitch, CARD32 size, CARD32 offset) +{ + surface->size = sizeof (SVGASurface); + surface->version = SVGA_SURFACE_VERSION_1; + surface->bpp = bpp; + surface->width = width; + surface->height = height; + surface->pitch = pitch; + if (surface->userData == 0) { + /* + * We allocate exactly what we need the first time we use a slot, so + * all reuses of this slot will be equal or smaller. + */ + surface->userData = size; + } + surface->dataOffset = offset + heap->startOffset; + + return surface; +} + +SVGASurface* +vmwareHeap_GetFrontBuffer(Heap* heap) +{ + return heap->frontBuffer; +} + +SVGASurface* +vmwareHeap_AllocSurface(Heap* heap, CARD32 width, CARD32 height, + CARD32 pitch, CARD32 bpp) +{ + CARD32 size = pitch * height; + CARD32 sizeUsed = 0; + SVGASurface* surface = heap->slotsStart; + int i; + + /* + * NOTE: we use SVGASurface::userData to store the largest this slot's + * size has ever been, since we don't ever compact anything. + */ + + /* find a free slot that's big enough */ + for (i = 0; i < heap->maxSlots; i++) { + if (surface[i].userData == 0) { /* this surface has never been used */ + if ((CARD8*)heap->slotsStart - heap->ptr - sizeUsed < size) { + /* no room left for data*/ + return NULL; + } + + heap->clear = FALSE; + return FillInSurface(heap, surface + i, width, height, bpp, + pitch, size, sizeUsed); + } + + if (surface[i].numQueued == surface[i].numDequeued && + surface[i].userData >= size) { /* free and big enough, sweet! */ + heap->clear = FALSE; + return FillInSurface(heap, surface + i, width, height, bpp, + pitch, size, sizeUsed); + } + + sizeUsed += surface[i].userData; + } + + return NULL; +} diff --git a/src/offscreen_manager.h b/src/offscreen_manager.h new file mode 100644 index 0000000..e948da9 --- /dev/null +++ b/src/offscreen_manager.h @@ -0,0 +1,25 @@ +/* ********************************************************** + * Copyright (C) 1998-2002 VMware, Inc. + * All Rights Reserved + * **********************************************************/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/offscreen_manager.h,v 1.2 2002/12/11 17:07:58 dawes Exp $ */ + +#ifndef OFFSCREEN_MANAGER_H +#define OFFSCREEN_MANAGER_H + +struct _Heap; +typedef struct _Heap Heap; + +extern Heap* vmwareHeap_Create(CARD8* ptr, CARD32 size, CARD32 maxSlots, + CARD32 startOffset, CARD32 sWidth, CARD32 sHeight, + CARD32 sBPP, CARD32 sPitch, CARD32 sFbOffset); +extern void vmwareHeap_Destroy(Heap* heap); + +extern void vmwareHeap_Clear(Heap* heap); + +extern SVGASurface* vmwareHeap_GetFrontBuffer(Heap* heap); + +extern SVGASurface* vmwareHeap_AllocSurface(Heap* heap, CARD32 width, CARD32 height, + CARD32 pitch, CARD32 bpp); + +#endif diff --git a/src/svga_limits.h b/src/svga_limits.h new file mode 100644 index 0000000..016c2b8 --- /dev/null +++ b/src/svga_limits.h @@ -0,0 +1,57 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/svga_limits.h,v 1.2 2002/10/16 22:12:53 alanh Exp $ */ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * $Id$ + * **********************************************************/ + +/* + * svga_limits.h -- + * + * SVGA limits + */ + +#ifndef _SVGA_LIMITS_H_ +#define _SVGA_LIMITS_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#define INCLUDE_ALLOW_MONITOR +#include "includeCheck.h" + +/* + * Location and size of SVGA frame buffer and the FIFO. + */ +#define SVGA_VRAM_SIZE (16*1024*1024) +#define SVGA_MEM_SIZE (256*1024) + +/* + * SVGA_FB_START is the default starting address of the SVGA frame + * buffer in the guest's physical address space. + * SVGA_FB_START_BIGMEM is the starting address of the SVGA frame + * buffer for VMs that have a large amount of physical memory. + * + * The address of SVGA_FB_START is set to 2GB - (SVGA_FB_MAX_SIZE + SVGA_MEM_SIZE), + * thus the SVGA frame buffer sits at [SVGA_FB_START .. 2GB-1] in the + * physical address space. Our older SVGA drivers for NT treat the + * address of the frame buffer as a signed integer. For backwards + * compatibility, we keep the default location of the frame buffer + * at under 2GB in the address space. This restricts VMs to have "only" + * up to ~2031MB (i.e., up to SVGA_FB_START) of physical memory. + * + * For VMs that want more memory than the ~2031MB, we place the SVGA + * frame buffer at SVGA_FB_START_BIGMEM. This allows VMs to have up + * to 3584MB, at least as far as the SVGA frame buffer is concerned + * (note that there may be other issues that limit the VM memory + * size). PCI devices use high memory addresses, so we have to put + * SVGA_FB_START_BIGMEM low enough so that it doesn't overlap with any + * of these devices. Placing SVGA_FB_START_BIGMEM at 0xE0000000 + * should leave plenty of room for the PCI devices. + * + * NOTE: All of that is only true for the 0710 chipset. As of the 0405 + * chipset, the framebuffer start is determined solely based on the value + * the guest BIOS or OS programs into the PCI base address registers. + */ +#define SVGA_FB_LEGACY_START 0x7EFC0000 +#define SVGA_FB_LEGACY_START_BIGMEM 0xE0000000 + +#endif diff --git a/src/svga_reg.h b/src/svga_reg.h new file mode 100644 index 0000000..2d6800d --- /dev/null +++ b/src/svga_reg.h @@ -0,0 +1,456 @@ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * $Id$ + * **********************************************************/ + +/* + * svga_reg.h -- + * + * SVGA hardware definitions + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/svga_reg.h,v 1.8 2003/02/04 01:39:53 dawes Exp $ */ + +#ifndef _SVGA_REG_H_ +#define _SVGA_REG_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#define INCLUDE_ALLOW_MONITOR +#include "includeCheck.h" + +#include "svga_limits.h" + +/* + * Memory and port addresses and fundamental constants + */ + +/* + * Note-- MAX_WIDTH and MAX_HEIGHT are largely ignored by the code. This + * isn't such a bad thing for forward compatibility. --Jeremy. + */ +#define SVGA_MAX_WIDTH 2360 +#define SVGA_MAX_HEIGHT 1770 +#define SVGA_MAX_BITS_PER_PIXEL 32 + +#define PAGE_SHIFT 12 +#define SVGA_FB_MAX_SIZE \ + ((((SVGA_MAX_WIDTH * SVGA_MAX_HEIGHT * \ + SVGA_MAX_BITS_PER_PIXEL / 8) >> PAGE_SHIFT) + 1) << PAGE_SHIFT) + +#if SVGA_FB_MAX_SIZE > SVGA_VRAM_SIZE +#error "Bad SVGA maximum sizes" +#endif +#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8 +#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH) + +#define SVGA_MAGIC 0x900000 +#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver)) + +/* 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 SVGA_ID_ */ +#define SVGA_ID_INVALID 0xFFFFFFFF + +/* More backwards compatibility, old location of color map: */ +#define SVGA_OLD_PALETTE_BASE 17 + +/* Base and Offset gets us headed the right way for PCI Base Addr Registers */ +#define SVGA_LEGACY_BASE_PORT 0x4560 +#define SVGA_INDEX_PORT 0x0 +#define SVGA_VALUE_PORT 0x1 +#define SVGA_BIOS_PORT 0x2 +#define SVGA_NUM_PORTS 0x3 + +/* This port is deprecated, but retained because of old drivers. */ +#define SVGA_LEGACY_ACCEL_PORT 0x3 + +/* Legal values for the SVGA_REG_CURSOR_ON register in cursor bypass mode */ +#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 */ + +/* + * 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, + SVGA_REG_FB_OFFSET = 14, + SVGA_REG_VRAM_SIZE = 15, + SVGA_REG_FB_SIZE = 16, + + SVGA_REG_CAPABILITIES = 17, + SVGA_REG_MEM_START = 18, /* Memory for command FIFO and bitmaps */ + SVGA_REG_MEM_SIZE = 19, + SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */ + SVGA_REG_SYNC = 21, /* Write to force synchronization */ + SVGA_REG_BUSY = 22, /* Read to check if sync is done */ + SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */ + SVGA_REG_CURSOR_ID = 24, /* ID of cursor */ + SVGA_REG_CURSOR_X = 25, /* Set cursor X position */ + SVGA_REG_CURSOR_Y = 26, /* Set cursor Y position */ + SVGA_REG_CURSOR_ON = 27, /* Turn cursor on/off */ + SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* Current bpp in the host */ + + SVGA_REG_TOP = 30, /* Must be 1 greater than the last register */ + + SVGA_PALETTE_BASE = 1024 /* Base of SVGA color map */ +}; + + +/* + * Capabilities + */ + +#define SVGA_CAP_NONE 0x0000 +#define SVGA_CAP_RECT_FILL 0x0001 +#define SVGA_CAP_RECT_COPY 0x0002 +#define SVGA_CAP_RECT_PAT_FILL 0x0004 +#define SVGA_CAP_LEGACY_OFFSCREEN 0x0008 +#define SVGA_CAP_RASTER_OP 0x0010 +#define SVGA_CAP_CURSOR 0x0020 +#define SVGA_CAP_CURSOR_BYPASS 0x0040 +#define SVGA_CAP_CURSOR_BYPASS_2 0x0080 +#define SVGA_CAP_8BIT_EMULATION 0x0100 +#define SVGA_CAP_ALPHA_CURSOR 0x0200 +#define SVGA_CAP_GLYPH 0x0400 +#define SVGA_CAP_GLYPH_CLIPPING 0x0800 +#define SVGA_CAP_OFFSCREEN_1 0x1000 +#define SVGA_CAP_ALPHA_BLEND 0x2000 + + +/* + * Raster op codes (same encoding as X) used by FIFO drivers. + */ + +#define SVGA_ROP_CLEAR 0x00 /* 0 */ +#define SVGA_ROP_AND 0x01 /* src AND dst */ +#define SVGA_ROP_AND_REVERSE 0x02 /* src AND NOT dst */ +#define SVGA_ROP_COPY 0x03 /* src */ +#define SVGA_ROP_AND_INVERTED 0x04 /* NOT src AND dst */ +#define SVGA_ROP_NOOP 0x05 /* dst */ +#define SVGA_ROP_XOR 0x06 /* src XOR dst */ +#define SVGA_ROP_OR 0x07 /* src OR dst */ +#define SVGA_ROP_NOR 0x08 /* NOT src AND NOT dst */ +#define SVGA_ROP_EQUIV 0x09 /* NOT src XOR dst */ +#define SVGA_ROP_INVERT 0x0a /* NOT dst */ +#define SVGA_ROP_OR_REVERSE 0x0b /* src OR NOT dst */ +#define SVGA_ROP_COPY_INVERTED 0x0c /* NOT src */ +#define SVGA_ROP_OR_INVERTED 0x0d /* NOT src OR dst */ +#define SVGA_ROP_NAND 0x0e /* NOT src OR NOT dst */ +#define SVGA_ROP_SET 0x0f /* 1 */ +#define SVGA_ROP_UNSUPPORTED 0x10 + +#define SVGA_NUM_SUPPORTED_ROPS 16 +#define SVGA_ROP_ALL (MASK(SVGA_NUM_SUPPORTED_ROPS)) +#define SVGA_IS_VALID_ROP(rop) (rop >= 0 && rop < SVGA_NUM_SUPPORTED_ROPS) + +/* + * Ops + * For each pixel, the four channels of the image are computed with: + * + * C = Ca * Fa + Cb * Fb + * + * where C, Ca, Cb are the values of the respective channels and Fa + * and Fb come from the following table: + * + * BlendOp Fa Fb + * ------------------------------------------ + * Clear 0 0 + * Src 1 0 + * Dst 0 1 + * Over 1 1-Aa + * OverReverse 1-Ab 1 + * In Ab 0 + * InReverse 0 Aa + * Out 1-Ab 0 + * OutReverse 0 1-Aa + * Atop Ab 1-Aa + * AtopReverse 1-Ab Aa + * Xor 1-Ab 1-Aa + * Add 1 1 + * Saturate min(1,(1-Ab)/Aa) 1 + * + * Flags + * You can use the following flags to achieve additional affects: + * + * Flag Effect + * ------------------------------------------ + * ConstantSourceAlpha Ca = Ca * Param0 + * ConstantDestAlpha Cb = Cb * Param1 + * + * Flag effects resolve before the op. For example + * BlendOp == Add && Flags == ConstantSourceAlpha | + * ConstantDestAlpha results in: + * + * C = (Ca * Param0) + (Cb * Param1) + */ + +#define SVGA_BLENDOP_CLEAR 0 +#define SVGA_BLENDOP_SRC 1 +#define SVGA_BLENDOP_DST 2 +#define SVGA_BLENDOP_OVER 3 +#define SVGA_BLENDOP_OVER_REVERSE 4 +#define SVGA_BLENDOP_IN 5 +#define SVGA_BLENDOP_IN_REVERSE 6 +#define SVGA_BLENDOP_OUT 7 +#define SVGA_BLENDOP_OUT_REVERSE 8 +#define SVGA_BLENDOP_ATOP 9 +#define SVGA_BLENDOP_ATOP_REVERSE 10 +#define SVGA_BLENDOP_XOR 11 +#define SVGA_BLENDOP_ADD 12 +#define SVGA_BLENDOP_SATURATE 13 + +#define SVGA_NUM_BLENDOPS 14 +#define SVGA_IS_VALID_BLENDOP(op) (op >= 0 && op < SVGA_NUM_BLENDOPS) + +#define SVGA_BLENDFLAG_CONSTANT_SOURCE_ALPHA 0x01 +#define SVGA_BLENDFLAG_CONSTANT_DEST_ALPHA 0x02 +#define SVGA_NUM_BLENDFLAGS 2 +#define SVGA_BLENDFLAG_ALL (MASK(SVGA_NUM_BLENDFLAGS)) +#define SVGA_IS_VALID_BLENDFLAG(flag) ((flag & ~SVGA_BLENDFLAG_ALL) == 0) + +/* + * Memory area offsets (viewed as an array of 32-bit words) + */ + +/* + * The distance from MIN to MAX must be at least 10K + */ + +#define SVGA_FIFO_MIN 0 +#define SVGA_FIFO_MAX 1 +#define SVGA_FIFO_NEXT_CMD 2 +#define SVGA_FIFO_STOP 3 + +#define SVGA_FIFO_USER_DEFINED 4 + +/* + * Drawing object ID's, in the range 0 to SVGA_MAX_ID + */ + +#define SVGA_MAX_ID 499 + +/* + * Macros to compute variable length items (sizes in 32-bit words, except + * for SVGA_GLYPH_SCANLINE_SIZE, which is in bytes). + */ + +#define SVGA_BITMAP_SIZE(w,h) ((((w)+31) >> 5) * (h)) +#define SVGA_BITMAP_SCANLINE_SIZE(w) (( (w)+31 ) >> 5) +#define SVGA_PIXMAP_SIZE(w,h,bpp) ((( ((w)*(bpp))+31 ) >> 5) * (h)) +#define SVGA_PIXMAP_SCANLINE_SIZE(w,bpp) (( ((w)*(bpp))+31 ) >> 5) +#define SVGA_GLYPH_SIZE(w,h) ((((((w) + 7) >> 3) * (h)) + 3) >> 2) +#define SVGA_GLYPH_SCANLINE_SIZE(w) (((w) + 7) >> 3) + +/* + * Get the width and height of VRAM in the current mode (for offscreen memory) + */ +#define SVGA_VRAM_WIDTH_HEIGHT(width /* out */, height /* out */) { \ + uint32 pitch = svga->reg[SVGA_REG_BYTES_PER_LINE]; \ + width = (pitch * 8) / ((svga->reg[SVGA_REG_BITS_PER_PIXEL] + 7) & ~7); \ + height = (svga->reg[SVGA_REG_VRAM_SIZE] - \ + svga->reg[SVGA_REG_FB_OFFSET]) / pitch; \ +} + +/* + * Increment from one scanline to the next of a bitmap or pixmap + */ +#define SVGA_BITMAP_INCREMENT(w) ((( (w)+31 ) >> 5) * sizeof (uint32)) +#define SVGA_PIXMAP_INCREMENT(w,bpp) ((( ((w)*(bpp))+31 ) >> 5) * sizeof (uint32)) + +/* + * Transparent color for DRAW_GLYPH_CLIPPED + */ +#define SVGA_COLOR_TRANSPARENT (~0) + +/* + * Commands in the command FIFO + */ + +#define SVGA_CMD_INVALID_CMD 0 + /* FIFO layout: + <nothing> (well, undefined) */ + +#define SVGA_CMD_UPDATE 1 + /* FIFO layout: + X, Y, Width, Height */ + +#define SVGA_CMD_RECT_FILL 2 + /* FIFO layout: + Color, X, Y, Width, Height */ + +#define SVGA_CMD_RECT_COPY 3 + /* FIFO layout: + Source X, Source Y, Dest X, Dest Y, Width, Height */ + +#define SVGA_CMD_DEFINE_BITMAP 4 + /* FIFO layout: + Pixmap ID, Width, Height, <scanlines> */ + +#define SVGA_CMD_DEFINE_BITMAP_SCANLINE 5 + /* FIFO layout: + Pixmap ID, Width, Height, Line #, scanline */ + +#define SVGA_CMD_DEFINE_PIXMAP 6 + /* FIFO layout: + Pixmap ID, Width, Height, Depth, <scanlines> */ + +#define SVGA_CMD_DEFINE_PIXMAP_SCANLINE 7 + /* FIFO layout: + Pixmap ID, Width, Height, Depth, Line #, scanline */ + +#define SVGA_CMD_RECT_BITMAP_FILL 8 + /* FIFO layout: + Bitmap ID, X, Y, Width, Height, Foreground, Background */ + +#define SVGA_CMD_RECT_PIXMAP_FILL 9 + /* FIFO layout: + Pixmap ID, X, Y, Width, Height */ + +#define SVGA_CMD_RECT_BITMAP_COPY 10 + /* FIFO layout: + Bitmap ID, Source X, Source Y, Dest X, Dest Y, + Width, Height, Foreground, Background */ + +#define SVGA_CMD_RECT_PIXMAP_COPY 11 + /* FIFO layout: + Pixmap ID, Source X, Source Y, Dest X, Dest Y, Width, Height */ + +#define SVGA_CMD_FREE_OBJECT 12 + /* FIFO layout: + Object (pixmap, bitmap, ...) ID */ + +#define SVGA_CMD_RECT_ROP_FILL 13 + /* FIFO layout: + Color, X, Y, Width, Height, ROP */ + +#define SVGA_CMD_RECT_ROP_COPY 14 + /* FIFO layout: + Source X, Source Y, Dest X, Dest Y, Width, Height, ROP */ + +#define SVGA_CMD_RECT_ROP_BITMAP_FILL 15 + /* FIFO layout: + ID, X, Y, Width, Height, Foreground, Background, ROP */ + +#define SVGA_CMD_RECT_ROP_PIXMAP_FILL 16 + /* FIFO layout: + ID, X, Y, Width, Height, ROP */ + +#define SVGA_CMD_RECT_ROP_BITMAP_COPY 17 + /* FIFO layout: + ID, Source X, Source Y, + Dest X, Dest Y, Width, Height, Foreground, Background, ROP */ + +#define SVGA_CMD_RECT_ROP_PIXMAP_COPY 18 + /* FIFO layout: + ID, Source X, Source Y, Dest X, Dest Y, Width, Height, ROP */ + +#define SVGA_CMD_DEFINE_CURSOR 19 + /* FIFO layout: + ID, Hotspot X, Hotspot Y, Width, Height, + Depth for AND mask, Depth for XOR mask, + <scanlines for AND mask>, <scanlines for XOR mask> */ + +#define SVGA_CMD_DISPLAY_CURSOR 20 + /* FIFO layout: + ID, On/Off (1 or 0) */ + +#define SVGA_CMD_MOVE_CURSOR 21 + /* FIFO layout: + X, Y */ + +#define SVGA_CMD_DEFINE_ALPHA_CURSOR 22 + /* FIFO layout: + ID, Hotspot X, Hotspot Y, Width, Height, + <scanlines> */ + +#define SVGA_CMD_DRAW_GLYPH 23 + /* FIFO layout: + X, Y, W, H, FGCOLOR, <stencil buffer> */ + +#define SVGA_CMD_DRAW_GLYPH_CLIPPED 24 + /* FIFO layout: + X, Y, W, H, FGCOLOR, BGCOLOR, <cliprect>, <stencil buffer> + Transparent color expands are done by setting BGCOLOR to ~0 */ + +#define SVGA_CMD_UPDATE_VERBOSE 25 + /* FIFO layout: + X, Y, Width, Height, Reason */ + +#define SVGA_CMD_SURFACE_FILL 26 + /* FIFO layout: + color, dstSurfaceOffset, x, y, w, h, rop */ + +#define SVGA_CMD_SURFACE_COPY 27 + /* FIFO layout: + srcSurfaceOffset, dstSurfaceOffset, srcX, srcY, + destX, destY, w, h, rop */ + +#define SVGA_CMD_SURFACE_ALPHA_BLEND 28 + /* FIFO layout: + srcSurfaceOffset, dstSurfaceOffset, srcX, srcY, + destX, destY, w, h, op (SVGA_BLENDOP*), flags (SVGA_BLENDFLAGS*), + param1, param2 */ + +#define SVGA_CMD_MAX 29 + +/* SURFACE_ALPHA_BLEND currently has the most (non-data) arguments: 12 */ +#define SVGA_CMD_MAX_ARGS 12 + + +/* + * A sync request is sent via a non-zero write to the SVGA_REG_SYNC + * register. In devel builds, the driver will write a specific value + * indicating exactly why the sync is necessary + */ +enum { + SVGA_SYNC_INVALIDREASON = 0, /* Don't ever write a zero */ + SVGA_SYNC_GENERIC = 1, /* Legacy drivers will always write a 1 */ + SVGA_SYNC_FIFOFULL = 2, /* Need to drain FIFO for next write */ + SVGA_SYNC_FB_WRITE = 3, /* About write to shadow frame buffer (generic) */ + SVGA_SYNC_FB_BITBLT = 4, /* Unaccelerated DrvBitBlt */ + SVGA_SYNC_FB_COPYBITS = 5, /* Unacclerated DrvCopyBits bits */ + SVGA_SYNC_FB_FILLPATH = 6, /* Unacclerated DrvFillPath */ + SVGA_SYNC_FB_LINETO = 7, /* Unacclerated DrvLineTo */ + SVGA_SYNC_FB_PAINT = 8, /* Unacclerated DrvPaint */ + SVGA_SYNC_FB_STRETCHBLT = 9, /* Unacclerated DrvStretchBlt */ + SVGA_SYNC_FB_STROKEFILL = 10, /* Unacclerated DrvStrokeAndFillPath */ + SVGA_SYNC_FB_STROKE = 11, /* Unacclerated DrvStrokePath */ + SVGA_SYNC_FB_TEXTOUT = 12, /* Unacclerated DrvTextOut */ + SVGA_SYNC_FB_ALPHABLEND = 13, /* Unacclerated DrvAlphaBlend */ + SVGA_SYNC_FB_GRADIENT = 14, /* Unacclerated DrvGradientFill */ + SVGA_SYNC_FB_PLGBLT = 15, /* Unacclerated DrvPlgBlt */ + SVGA_SYNC_FB_STRETCHROP = 16, /* Unacclerated DrvStretchBltROP */ + SVGA_SYNC_FB_TRANSPARENT = 17, /* Unacclerated DrvTransparentBlt */ + SVGA_SYNC_FB_NEWCURSOR = 18, /* Defined a new cursor */ + SVGA_SYNC_FB_SYNCSURFACE = 19, /* DrvSynchrnoizeSurface call */ + SVGA_SYNC_FB_NUM_REASONS /* Total number of reasons */ +}; + +#endif diff --git a/src/svga_struct.h b/src/svga_struct.h new file mode 100644 index 0000000..fe4f0bf --- /dev/null +++ b/src/svga_struct.h @@ -0,0 +1,40 @@ +/* ********************************************************** + * Copyright (C) 1998-2000 VMware, Inc. + * All Rights Reserved + * **********************************************************/ + +#ifndef _SVGA_STRUCT_H_ +#define _SVGA_STRUCT_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#define INCLUDE_ALLOW_MONITOR +#include "includeCheck.h" + + /* + * Offscreen memory surface structure + * + */ + +enum SVGASurfaceVersion { + SVGA_SURFACE_VERSION_1 = 1 /* Initial version... */ +}; + +typedef struct _SVGASurface { + uint32 size; /* Size of the structure */ + uint32 version; /* Version of this surface structure. */ + uint32 bpp; /* Format of the surface */ + uint32 width; /* Width of the surface */ + uint32 height; /* Height of the surface */ + uint32 pitch; /* Pitch of the surface */ + volatile uint32 numQueued; /* Number of times this bitmap has been queued */ + volatile uint32 numDequeued; /* Number of times this bitmap has been dequeued */ + uint32 userData; /* Driver defined data */ + uint32 dataOffset; /* Offset to the data */ +} SVGASurface; + +typedef struct SVGAPoint { + int16 x; + int16 y; +} SVGAPoint; + +#endif diff --git a/src/vm_basic_types.h b/src/vm_basic_types.h new file mode 100644 index 0000000..673522f --- /dev/null +++ b/src/vm_basic_types.h @@ -0,0 +1,173 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/vm_basic_types.h,v 1.5 2002/01/07 20:38:29 dawes Exp $ */ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * Id: vm_basic_types.h,v 1.9 2001/02/14 22:22:53 bennett Exp $ + * **********************************************************/ + +/* + * + * vm_basic_types.h -- + * + * basic data types. + */ + + +#ifndef _VM_BASIC_TYPES_H_ +#define _VM_BASIC_TYPES_H_ + +#define INCLUDE_ALLOW_USERLEVEL +#define INCLUDE_ALLOW_MONITOR +#define INCLUDE_ALLOW_MODULE +#define INCLUDE_ALLOW_VMKERNEL +#include "includeCheck.h" + +/* STRICT ANSI means the Xserver build and X defines Bool differently. */ +#if 0 +typedef char Bool; +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifdef _MSC_VER +typedef unsigned __int64 uint64; +typedef signed __int64 int64; + +#pragma warning (disable :4018) // signed/unsigned mismatch +#pragma warning (disable :4761) // integral size mismatch in argument; conversion supplied +#pragma warning (disable :4305) // truncation from 'const int' to 'short' +#pragma warning (disable :4244) // conversion from 'unsigned short' to 'unsigned char' +//#pragma warning (disable :4101) // unreferenced local variable +#pragma warning (disable :4133) // incompatible types - from 'struct VM *' to 'int *' +#pragma warning (disable :4047) // differs in levels of indirection +#pragma warning (disable :4146) // unary minus operator applied to unsigned type, result still unsigned +#pragma warning (disable :4142) // benign redefinition of type + +#elif defined(__GNUC__) +/* The Xserver source compiles with -ansi -pendantic */ +#ifndef __STRICT_ANSI__ +typedef unsigned long long uint64; +typedef long long int64; +#endif +#else +/* int64/uint64 aren't actually used in the vmware driver. */ +#if 0 +#error - Need compiler define for int64/uint64 +#endif +#endif + +typedef unsigned int uint32; +typedef unsigned short uint16; +typedef unsigned char uint8; + +typedef int int32; +typedef short int16; +typedef char int8; + + +/* + * Printf format for 64-bit number. Use it like this: + * printf("%"FMT64"d\n", big); + */ + +#ifdef _MSC_VER +#define FMT64 "I64" +#elif defined(__GNUC__) +#define FMT64 "L" +#else +/* FMT64 isn't actually used in the vmware driver. */ +#if 0 +#error - Need compiler define for FMT64 +#endif +#endif + +typedef uint32 VA; +typedef uint32 VPN; + +typedef uint32 PA; +typedef uint32 PPN; + +typedef uint32 MA; +typedef uint32 MPN; + +#define INVALID_MPN ((MPN)-1) + +#define EXTERN extern +/* + * Right now our use of CONST is broken enough that it only works + * with GCC. XXX Need to fix this. + */ +#ifdef __GNUC__ +#define CONST const +#else +#ifndef CONST +#define CONST +#endif +#endif + +#ifdef _MSC_VER +#ifndef INLINE +#define INLINE __inline +#endif +#else +#ifndef INLINE +#define INLINE inline +#endif +#endif + + +#if defined(WIN32) && !defined(VMX86_NO_THREADS) +#define THREADSPECIFIC _declspec(thread) +#else +#define THREADSPECIFIC +#endif + +/* + * Like "INLINE" but use this token to mark functions that are inline + * because they have only a single call site. In other words, if a second + * call site is introduced, the "INLINE_SINGLE_CALLER" token should be + * removed. + */ +#define INLINE_SINGLE_CALLER INLINE + +/* + * Attributes placed on function declarations to tell the compiler + * that the function never returns. + */ +#ifdef _MSC_VER +#define NORETURN_DECL(_fndecl) __declspec(noreturn) _fndecl +#elif defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 5 +#define NORETURN_DECL(_fndecl) _fndecl __attribute__((__noreturn__)) +#else +#define NORETURN_DECL(_fndecl) _fndecl +#endif + + +/* + * GCC's argument checking for printf-like functions + * This is conditional until we have replaced all `"%x", void *' + * with `"0x%08x", (uint32) void *'. Note that %p prints different things + * on different platforms. + * + * fmtPos is the position of the format string argument, beginning at 1 + * varPos is the position of the variable argument, beginning at 1 + */ +#if defined(__GNUC__) && defined(notdef) +# define PRINTF_DECL(fmtPos, varPos) __attribute__((__format__(__printf__, fmtPos, varPos))) +#else +# define PRINTF_DECL(fmtPos, varPos) +#endif + +/* + * Used to silence compiler warnings that get generated when the + * compiler thinks that a function returns when it is marked noreturn. + */ +#define INFINITE_LOOP() do { } while (1) + +#endif diff --git a/src/vm_device_version.h b/src/vm_device_version.h new file mode 100644 index 0000000..8f6dd3b --- /dev/null +++ b/src/vm_device_version.h @@ -0,0 +1,64 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/vm_device_version.h,v 1.1 2001/04/05 19:29:44 dawes Exp $ */ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * Id: vm_device_version.h,v 1.2 2001/01/26 21:53:27 yoel Exp $ + * **********************************************************/ + + +#ifndef VM_DEVICE_VERSION_H +#define VM_DEVICE_VERSION_H + +#define INCLUDE_ALLOW_USERLEVEL +#define INCLUDE_ALLOW_MONITOR +#define INCLUDE_ALLOW_MODULE +#define INCLUDE_ALLOW_VMKERNEL +#include "includeCheck.h" + +#define PCI_VENDOR_ID_VMWARE 0x15AD +#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405 +#define PCI_DEVICE_ID_VMWARE_SVGA 0x0710 +#define PCI_DEVICE_ID_VMWARE_NET 0x0720 +#define PCI_DEVICE_ID_VMWARE_SCSI 0x0730 +#define PCI_DEVICE_ID_VMWARE_IDE 0x1729 + +/* From linux/pci.h. We emulate an AMD ethernet controller */ +#define PCI_VENDOR_ID_AMD 0x1022 +#define PCI_DEVICE_ID_AMD_VLANCE 0x2000 +#define PCI_VENDOR_ID_BUSLOGIC 0x104B +#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140 +#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040 + +/* Intel Values for the chipset */ +#define PCI_VENDOR_ID_INTEL 0x8086 +#define PCI_DEVICE_ID_INTEL_82439TX 0x7100 +#define PCI_DEVICE_ID_INTEL_82371AB_0 0x7110 +#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113 +#define PCI_DEVICE_ID_INTEL_82371AB 0x7111 +#define PCI_DEVICE_ID_INTEL_82443BX 0x7192 + + +/************* Strings for IDE Identity Fields **************************/ +#define VIDE_ID_SERIAL_STR "00000000000000000001" /* Must be 20 Bytes */ +#define VIDE_ID_FIRMWARE_STR "00000001" /* Must be 8 Bytes */ + +/* No longer than 40 Bytes and must be an even length. */ +#define VIDE_ATA_MODEL_STR PRODUCT_GENERIC_NAME " Virtual IDE Hard Drive " +#define VIDE_ATAPI_MODEL_STR PRODUCT_GENERIC_NAME " Virtual IDE CDROM Drive " + +#define ATAPI_VENDOR_ID "NECVMWar" /* Must be 8 Bytes */ +#define ATAPI_PRODUCT_ID PRODUCT_GENERIC_NAME " IDE CDROM" /* Must be 16 Bytes */ +#define ATAPI_REV_LEVEL "1.00" /* Must be 4 Bytes */ + + +/************* Strings for SCSI Identity Fields **************************/ +#define SCSI_DISK_MODEL_STR PRODUCT_GENERIC_NAME " Virtual SCSI Hard Drive" +#define SCSI_CDROM_MODEL_STR PRODUCT_GENERIC_NAME " Virtual SCSI CDROM Drive" + +/************* Strings for the VESA BIOS Identity Fields *****************/ +#define VBE_OEM_STRING COMPANY_NAME " SVGA" +#define VBE_VENDOR_NAME COMPANY_NAME +#define VBE_PRODUCT_NAME PRODUCT_GENERIC_NAME + + +#endif /* VM_DEVICE_VERSION_H */ diff --git a/src/vmware.c b/src/vmware.c new file mode 100644 index 0000000..d21ebb7 --- /dev/null +++ b/src/vmware.c @@ -0,0 +1,1406 @@ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ +#ifdef VMX86_DEVEL +char rcsId_vmware[] = + "Id: vmware.c,v 1.11 2001/02/23 02:10:39 yoel Exp $"; +#endif +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/vmware.c,v 1.17 2003/02/18 19:10:36 alanh Exp $ */ + +/* + * TODO: support the vmware linux kernel fb driver (Option "UseFBDev"). + */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Resources.h" + +#include "compiler.h" /* inb/outb */ + +#include "xf86PciInfo.h" /* pci vendor id */ +#include "xf86Pci.h" /* pci */ + +#include "mipointer.h" /* sw cursor */ +#include "mibstore.h" /* backing store */ +#include "micmap.h" /* mi color map */ +#include "vgaHW.h" /* VGA hardware */ +#include "fb.h" +#include "shadowfb.h" /* ShadowFB wrappers */ + +#include "xf86cmap.h" /* xf86HandleColormaps */ + +#include "vmware.h" +#include "guest_os.h" +#include "vm_device_version.h" + +/* + * Sanity check that xf86PciInfo.h has the correct values (which come from + * the VMware source tree in vm_device_version.h. + */ +#if PCI_CHIP_VMWARE0405 != PCI_DEVICE_ID_VMWARE_SVGA2 +#error "PCI_CHIP_VMWARE0405 is wrong, update it from vm_device_version.h" +#endif +#if PCI_CHIP_VMWARE0710 != PCI_DEVICE_ID_VMWARE_SVGA +#error "PCI_CHIP_VMWARE0710 is wrong, update it from vm_device_version.h" +#endif +#if PCI_VENDOR_VMWARE != PCI_VENDOR_ID_VMWARE +#error "PCI_VENDOR_VMWARE is wrong, update it from vm_device_version.h" +#endif + +/* + * This is the only way I know to turn a #define of an integer constant into + * a constant string. + */ +#define VMW_INNERSTRINGIFY(s) #s +#define VMW_STRING(str) VMW_INNERSTRINGIFY(str) + +#define VMWARE_NAME "VMWARE" +#define VMWARE_DRIVER_NAME "vmware" +#define VMWARE_MAJOR_VERSION 10 +#define VMWARE_MINOR_VERSION 10 +#define VMWARE_PATCHLEVEL 2 +#define VERSION (VMWARE_MAJOR_VERSION * 65536 + VMWARE_MINOR_VERSION * 256 + VMWARE_PATCHLEVEL) + +static const char VMWAREBuildStr[] = "VMware Guest X Server " + VMW_STRING(VMWARE_MAJOR_VERSION) "." VMW_STRING(VMWARE_MINOR_VERSION) + "." VMW_STRING(VMWARE_PATCHLEVEL) " - build=$Name$\n"; + +static SymTabRec VMWAREChipsets[] = { + { PCI_CHIP_VMWARE0405, "vmware0405" }, + { PCI_CHIP_VMWARE0710, "vmware0710" }, + { -1, NULL } +}; + +static resRange vmwareLegacyRes[] = { + { ResExcIoBlock, SVGA_LEGACY_BASE_PORT, + SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)}, + _VGA_EXCLUSIVE, _END +}; + +/* + * Currently, even the PCI obedient 0405 chip still only obeys IOSE and + * MEMSE for the SVGA resources. Thus, RES_EXCLUSIVE_VGA is required. + * + * The 0710 chip also uses hardcoded IO ports that aren't disablable. + */ + +static PciChipsets VMWAREPciChipsets[] = { + { PCI_CHIP_VMWARE0405, PCI_CHIP_VMWARE0405, RES_EXCLUSIVE_VGA }, + { PCI_CHIP_VMWARE0710, PCI_CHIP_VMWARE0710, vmwareLegacyRes }, + { -1, -1, RES_UNDEFINED } +}; + +static const char *vgahwSymbols[] = { + "vgaHWGetHWRec", + "vgaHWGetIOBase", + "vgaHWGetIndex", + "vgaHWInit", + "vgaHWProtect", + "vgaHWRestore", + "vgaHWSave", + "vgaHWSaveScreen", + "vgaHWUnlock", + NULL +}; + +static const char *fbSymbols[] = { + "fbCreateDefColormap", + "fbPictureInit", + "fbScreenInit", + NULL +}; + +static const char *ramdacSymbols[] = { + "xf86CreateCursorInfoRec", + "xf86DestroyCursorInfoRec", + "xf86InitCursor", + NULL +}; + +static const char *shadowfbSymbols[] = { + "ShadowFBInit2", + NULL +}; + +#ifdef XFree86LOADER +static XF86ModuleVersionInfo vmwareVersRec = { + "vmware", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + VMWARE_MAJOR_VERSION, VMWARE_MINOR_VERSION, VMWARE_PATCHLEVEL, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + { 0, 0, 0, 0} +}; +#endif /* XFree86LOADER */ + +typedef enum { + OPTION_HW_CURSOR, + OPTION_NOACCEL +} VMWAREOpts; + +static const OptionInfoRec VMWAREOptions[] = { + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +static void VMWAREStopFIFO(ScrnInfoPtr pScrn); + +static Bool +VMWAREGetRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate != NULL) { + return TRUE; + } + pScrn->driverPrivate = xnfcalloc(sizeof(VMWARERec), 1); + /* FIXME: Initialize driverPrivate... */ + return TRUE; +} + +static void +VMWAREFreeRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate) { + xfree(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; + } +} + +CARD32 +vmwareReadReg(VMWAREPtr pVMWARE, int index) +{ + /* + * Block SIGIO for the duration, so we don't get interrupted after the + * outl but before the inl by a mouse move (which write to our registers). + */ + int oldsigio, ret; + oldsigio = xf86BlockSIGIO(); + outl(pVMWARE->indexReg, index); + ret = inl(pVMWARE->valueReg); + xf86UnblockSIGIO(oldsigio); + return ret; +} + +void +vmwareWriteReg(VMWAREPtr pVMWARE, int index, CARD32 value) +{ + /* + * Block SIGIO for the duration, so we don't get interrupted in between + * the outls by a mouse move (which write to our registers). + */ + int oldsigio; + oldsigio = xf86BlockSIGIO(); + outl(pVMWARE->indexReg, index); + outl(pVMWARE->valueReg, value); + xf86UnblockSIGIO(oldsigio); +} + +void +vmwareWriteWordToFIFO(VMWAREPtr pVMWARE, CARD32 value) +{ + CARD32* vmwareFIFO = pVMWARE->vmwareFIFO; + + /* Need to sync? */ + if ((vmwareFIFO[SVGA_FIFO_NEXT_CMD] + sizeof(CARD32) == vmwareFIFO[SVGA_FIFO_STOP]) + || (vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - sizeof(CARD32) && + vmwareFIFO[SVGA_FIFO_STOP] == vmwareFIFO[SVGA_FIFO_MIN])) { + VmwareLog(("Syncing because of full fifo\n")); + vmwareWaitForFB(pVMWARE); + } + + vmwareFIFO[vmwareFIFO[SVGA_FIFO_NEXT_CMD] / sizeof(CARD32)] = value; + if(vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - + sizeof(CARD32)) { + vmwareFIFO[SVGA_FIFO_NEXT_CMD] = vmwareFIFO[SVGA_FIFO_MIN]; + } else { + vmwareFIFO[SVGA_FIFO_NEXT_CMD] += sizeof(CARD32); + } +} + +void +vmwareWaitForFB(VMWAREPtr pVMWARE) +{ + vmwareWriteReg(pVMWARE, SVGA_REG_SYNC, 1); + while (vmwareReadReg(pVMWARE, SVGA_REG_BUSY)); +} + +void +vmwareSendSVGACmdUpdate(VMWAREPtr pVMWARE, BoxPtr pBB) +{ + vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_UPDATE); + vmwareWriteWordToFIFO(pVMWARE, pBB->x1); + vmwareWriteWordToFIFO(pVMWARE, pBB->y1); + vmwareWriteWordToFIFO(pVMWARE, pBB->x2 - pBB->x1); + vmwareWriteWordToFIFO(pVMWARE, pBB->y2 - pBB->y1); +} + +static void +vmwareSendSVGACmdUpdateFullScreen(VMWAREPtr pVMWARE) +{ + BoxRec BB; + + BB.x1 = 0; + BB.y1 = 0; + BB.x2 = pVMWARE->ModeReg.svga_reg_width; + BB.y2 = pVMWARE->ModeReg.svga_reg_height; + vmwareSendSVGACmdUpdate(pVMWARE, &BB); +} + +static CARD32 +vmwareCalculateWeight(CARD32 mask) +{ + CARD32 weight; + + for (weight = 0; mask; mask >>= 1) { + if (mask & 1) { + weight++; + } + } + return weight; +} + +/* + *----------------------------------------------------------------------------- + * + * VMXGetVMwareSvgaId -- + * + * Retrieve the SVGA_ID of the VMware SVGA adapter. + * This function should hide any backward compatibility mess. + * + * Results: + * The SVGA_ID_* of the present VMware adapter. + * + * Side effects: + * ins/outs + * + *----------------------------------------------------------------------------- + */ + +static uint32 +VMXGetVMwareSvgaId(VMWAREPtr pVMWARE) +{ + uint32 vmware_svga_id; + + /* Any version with any SVGA_ID_* support will initialize SVGA_REG_ID + * to SVGA_ID_0 to support versions of this driver with SVGA_ID_0. + * + * Versions of SVGA_ID_0 ignore writes to the SVGA_REG_ID register. + * + * Versions of SVGA_ID_1 will allow us to overwrite the content + * of the SVGA_REG_ID register only with the values SVGA_ID_0 or SVGA_ID_1. + * + * Versions of SVGA_ID_2 will allow us to overwrite the content + * of the SVGA_REG_ID register only with the values SVGA_ID_0 or SVGA_ID_1 + * or SVGA_ID_2. + */ + + vmwareWriteReg(pVMWARE, SVGA_REG_ID, SVGA_ID_2); + vmware_svga_id = vmwareReadReg(pVMWARE, SVGA_REG_ID); + if (vmware_svga_id == SVGA_ID_2) { + return SVGA_ID_2; + } + + vmwareWriteReg(pVMWARE, SVGA_REG_ID, SVGA_ID_1); + vmware_svga_id = vmwareReadReg(pVMWARE, SVGA_REG_ID); + if (vmware_svga_id == SVGA_ID_1) { + return SVGA_ID_1; + } + + if (vmware_svga_id == SVGA_ID_0) { + return SVGA_ID_0; + } + + /* No supported VMware SVGA devices found */ + return SVGA_ID_INVALID; +} + + +/* + *---------------------------------------------------------------------- + * + * RewriteTagString -- + * + * Rewrites the given string, removing the $Name$, and + * replacing it with the contents. The output string must + * have enough room, or else. + * + * Results: + * + * Output string updated. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +RewriteTagString(const char *istr, char *ostr, int osize) +{ + int chr; + Bool inTag = FALSE; + char *op = ostr; + + do { + chr = *istr++; + if (chr == '$') { + if (inTag) { + inTag = FALSE; + for (; op > ostr && op[-1] == ' '; op--) { + } + continue; + } + if (strncmp(istr, "Name:", 5) == 0) { + istr += 5; + istr += strspn(istr, " "); + inTag = TRUE; + continue; + } + } + *op++ = chr; + } while (chr); +} + +static void +VMWAREIdentify(int flags) +{ + xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets); +} + +static const OptionInfoRec * +VMWAREAvailableOptions(int chipid, int busid) +{ + return VMWAREOptions; +} + +static Bool +VMWAREPreInit(ScrnInfoPtr pScrn, int flags) +{ + MessageType from; + VMWAREPtr pVMWARE; + OptionInfoPtr options; + int bpp24flags; + uint32 id; + int i; + ClockRange* clockRanges; + IOADDRESS domainIOBase = 0; + +#ifndef BUILD_FOR_420 + domainIOBase = pScrn->domainIOBase; +#endif + + if (flags & PROBE_DETECT) { + return FALSE; + } + + if (pScrn->numEntities != 1) { + return FALSE; + } + + if (!VMWAREGetRec(pScrn)) { + return FALSE; + } + pVMWARE = VMWAREPTR(pScrn); + + pVMWARE->pvtSema = &pScrn->vtSema; + + pVMWARE->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if (pVMWARE->pEnt->location.type != BUS_PCI) { + return FALSE; + } + pVMWARE->PciInfo = xf86GetPciInfoForEntity(pVMWARE->pEnt->index); + if (pVMWARE->PciInfo == NULL) { + return FALSE; + } + + if (pVMWARE->PciInfo->chipType == PCI_CHIP_VMWARE0710) { + pVMWARE->indexReg = domainIOBase + + SVGA_LEGACY_BASE_PORT + SVGA_INDEX_PORT*sizeof(uint32); + pVMWARE->valueReg = domainIOBase + + SVGA_LEGACY_BASE_PORT + SVGA_VALUE_PORT*sizeof(uint32); + } else { + /* Note: This setting of valueReg causes unaligned I/O */ + pVMWARE->indexReg = domainIOBase + + pVMWARE->PciInfo->ioBase[0] + SVGA_INDEX_PORT; + pVMWARE->valueReg = domainIOBase + + pVMWARE->PciInfo->ioBase[0] + SVGA_VALUE_PORT; + } + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "VMware SVGA regs at (0x%04x, 0x%04x)\n", + pVMWARE->indexReg, pVMWARE->valueReg); + + id = VMXGetVMwareSvgaId(pVMWARE); + if (id == SVGA_ID_0 || id == SVGA_ID_INVALID) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No supported VMware SVGA found (read ID 0x%08x).\n", id); + return FALSE; + } + + if (!xf86LoadSubModule(pScrn, "vgahw")) { + return FALSE; + } + + xf86LoaderReqSymLists(vgahwSymbols, NULL); + + if (!vgaHWGetHWRec(pScrn)) { + return FALSE; + } + + pVMWARE->PciTag = pciTag(pVMWARE->PciInfo->bus, pVMWARE->PciInfo->device, + pVMWARE->PciInfo->func); + pVMWARE->Primary = xf86IsPrimaryPci(pVMWARE->PciInfo); + + pScrn->monitor = pScrn->confScreen->monitor; + +#ifdef ACCELERATE_OPS + pVMWARE->vmwareCapability = vmwareReadReg(pVMWARE, SVGA_REG_CAPABILITIES); +#else + pVMWARE->vmwareCapability = 0; +#endif + + if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { + pVMWARE->bitsPerPixel = + vmwareReadReg(pVMWARE, SVGA_REG_HOST_BITS_PER_PIXEL); + vmwareWriteReg(pVMWARE, + SVGA_REG_BITS_PER_PIXEL, pVMWARE->bitsPerPixel); + } else { + pVMWARE->bitsPerPixel = + vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL); + } + pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH); + pVMWARE->videoRam = vmwareReadReg(pVMWARE, SVGA_REG_VRAM_SIZE); + pVMWARE->memPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_FB_START); + pVMWARE->maxWidth = vmwareReadReg(pVMWARE, SVGA_REG_MAX_WIDTH); + pVMWARE->maxHeight = vmwareReadReg(pVMWARE, SVGA_REG_MAX_HEIGHT); + pVMWARE->cursorDefined = FALSE; + pVMWARE->cursorShouldBeHidden = FALSE; + + if (pVMWARE->vmwareCapability & SVGA_CAP_CURSOR_BYPASS_2) { + pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_REMOVE_FROM_FB; + pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_RESTORE_TO_FB; + } else { + pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_HIDE; + pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_SHOW; + } + + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "caps: 0x%08X\n", pVMWARE->vmwareCapability); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "depth: %d\n", pVMWARE->depth); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "bpp: %d\n", pVMWARE->bitsPerPixel); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "vram: %d\n", pVMWARE->videoRam); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "pbase: %p\n", pVMWARE->memPhysBase); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mwidt: %d\n", pVMWARE->maxWidth); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mheig: %d\n", pVMWARE->maxHeight); + + switch (pVMWARE->depth) { + case 16: + /* + * In certain cases, the Windows host appears to + * report 16 bpp and 16 depth but 555 weight. Just + * silently convert it to depth of 15. + */ + if (pVMWARE->bitsPerPixel == 16 && + pVMWARE->weight.green == 5) + pVMWARE->depth = 15; + case 8: + case 15: + bpp24flags = NoDepth24Support; + break; + + case 32: + /* + * There is no 32 bit depth, apparently it can get + * reported this way sometimes on the Windows host. + */ + if (pVMWARE->bitsPerPixel == 32) + pVMWARE->depth = 24; + case 24: + if (pVMWARE->bitsPerPixel == 24) + bpp24flags = Support24bppFb; + else + bpp24flags = Support32bppFb; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Adapter is using an unsupported depth (%d).\n", + pVMWARE->depth); + return FALSE; + } + + if (!xf86SetDepthBpp(pScrn, pVMWARE->depth, pVMWARE->bitsPerPixel, pVMWARE->bitsPerPixel, bpp24flags)) { + return FALSE; + } + + if (pScrn->bitsPerPixel != pVMWARE->bitsPerPixel) { + if (pScrn->bitsPerPixel == 8 && + pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) { + vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, 8); + pVMWARE->bitsPerPixel = + vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Currently unavailable depth/bpp of %d/%d requested.\n" + "\tThe guest X server must run at the same depth and bpp as the host\n" + "\t(which are currently %d/%d). This is automatically detected. Please\n" + "\tdo not specify a depth on the command line or via the config file.\n", + pScrn->depth, pScrn->bitsPerPixel, + pVMWARE->depth, pVMWARE->bitsPerPixel); + return FALSE; + } + } + + /* + * Reread depth and defer reading the colour registers until here + * in case we changed bpp above. + */ + + pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH); + pVMWARE->weight.red = + vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_RED_MASK)); + pVMWARE->weight.green = + vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_GREEN_MASK)); + pVMWARE->weight.blue = + vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_BLUE_MASK)); + pVMWARE->offset.blue = 0; + pVMWARE->offset.green = pVMWARE->weight.blue; + pVMWARE->offset.red = pVMWARE->weight.green + pVMWARE->offset.green; + pVMWARE->defaultVisual = vmwareReadReg(pVMWARE, SVGA_REG_PSEUDOCOLOR) ? + PseudoColor : TrueColor; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, + 2, "depth: %d\n", pVMWARE->depth); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, + 2, "bpp: %d\n", pVMWARE->bitsPerPixel); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, + 2, "w.red: %d\n", pVMWARE->weight.red); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, + 2, "w.grn: %d\n", pVMWARE->weight.green); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, + 2, "w.blu: %d\n", pVMWARE->weight.blue); + xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, + 2, "vis: %d\n", pVMWARE->defaultVisual); + + if (pScrn->depth != pVMWARE->depth) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Currently unavailable depth of %d requested.\n" + "\tThe guest X server must run at the same depth as the host (which\n" + "\tis currently %d). This is automatically detected. Please do not\n" + "\tspecify a depth on the command line or via the config file.\n", + pScrn->depth, pVMWARE->depth); + return FALSE; + } + xf86PrintDepthBpp(pScrn); + +#if 0 + if (pScrn->depth == 24 && pix24bpp == 0) { + pix24bpp = xf86GetBppFromDepth(pScrn, 24); + } +#endif + + if (pScrn->depth > 8) { + rgb zeros = { 0, 0, 0 }; + + if (!xf86SetWeight(pScrn, pVMWARE->weight, zeros)) { + return FALSE; + } + /* FIXME check returned weight */ + } + if (!xf86SetDefaultVisual(pScrn, pVMWARE->defaultVisual)) { + return FALSE; + } + if (pScrn->defaultVisual != pVMWARE->defaultVisual) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given visual (%d) is not supported by this driver (%d is required)\n", + pScrn->defaultVisual, pVMWARE->defaultVisual); + return FALSE; + } +#if 0 + bytesPerPixel = pScrn->bitsPerPixel / 8; +#endif + pScrn->progClock = TRUE; + +#if 0 /* MGA does not do this */ + if (pScrn->visual != 0) { /* FIXME */ + /* print error message */ + return FALSE; + } +#endif + + xf86CollectOptions(pScrn, NULL); + if (!(options = xalloc(sizeof(VMWAREOptions)))) + return FALSE; + memcpy(options, VMWAREOptions, sizeof(VMWAREOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + if (pScrn->depth <= 8) { + pScrn->rgbBits = 8; + } + + from = X_PROBED; + pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets, pVMWARE->PciInfo->chipType); + + if (!pScrn->chipset) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04 is not recognised\n", pVMWARE->PciInfo->chipType); + return FALSE; + } + + from = X_DEFAULT; + pVMWARE->hwCursor = TRUE; + if (xf86GetOptValBool(options, OPTION_HW_CURSOR, &pVMWARE->hwCursor)) { + from = X_CONFIG; + } + if (pVMWARE->hwCursor && !(pVMWARE->vmwareCapability & SVGA_CAP_CURSOR)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW cursor is not supported in this configuration\n"); + from = X_PROBED; + pVMWARE->hwCursor = FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", + pVMWARE->hwCursor ? "HW" : "SW"); + if (xf86IsOptionSet(options, OPTION_NOACCEL)) { + pVMWARE->noAccel = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); + } else { + pVMWARE->noAccel = FALSE; + } + pScrn->videoRam = pVMWARE->videoRam / 1024; + pScrn->memPhysBase = pVMWARE->memPhysBase; + xfree(options); + + { + Gamma zeros = { 0.0, 0.0, 0.0 }; + if (!xf86SetGamma(pScrn, zeros)) { + return FALSE; + } + } +#if 0 + if ((i = xf86GetPciInfoForScreen(pScrn->scrnIndex, &pciList, NULL)) != 1) { + /* print error message */ + VMWAREFreeRec(pScrn); + if (i > 0) { + xfree(pciList); + } + return FALSE; + } +#endif + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + clockRanges->minClock = 1; + clockRanges->maxClock = 400000000; + clockRanges->clockIndex = -1; + clockRanges->interlaceAllowed = FALSE; + clockRanges->doubleScanAllowed = FALSE; + clockRanges->ClockMulFactor = 1; + clockRanges->ClockDivFactor = 1; + + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, + clockRanges, NULL, 256, pVMWARE->maxWidth, 32 * 32, + 128, pVMWARE->maxHeight, + pScrn->display->virtualX, pScrn->display->virtualY, + pVMWARE->videoRam, + LOOKUP_BEST_REFRESH); + if (i == -1) { + VMWAREFreeRec(pScrn); + return FALSE; + } + xf86PruneDriverModes(pScrn); + if (i == 0 || pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + VMWAREFreeRec(pScrn); + return FALSE; + } + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); + pScrn->currentMode = pScrn->modes; + xf86PrintModes(pScrn); + xf86SetDpi(pScrn, 0, 0); + if (!xf86LoadSubModule(pScrn, "fb") || + !xf86LoadSubModule(pScrn, "shadowfb")) { + VMWAREFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(fbSymbols, shadowfbSymbols, NULL); + + /* Need ramdac for hwcursor */ + if (pVMWARE->hwCursor) { + if (!xf86LoadSubModule(pScrn, "ramdac")) { + VMWAREFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(ramdacSymbols, NULL); + } + + if (!pVMWARE->noAccel) { + if (!xf86LoadSubModule(pScrn, "xaa")) { + VMWAREFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(vmwareXaaSymbols, NULL); + } + + return TRUE; +} + +static Bool +VMWAREMapMem(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE; + + pVMWARE = VMWAREPTR(pScrn); + + pVMWARE->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, + pVMWARE->PciTag, + pVMWARE->memPhysBase, + pVMWARE->videoRam); + if (!pVMWARE->FbBase) + return FALSE; + + VmwareLog(("FB Mapped: %p/%u -> %p/%u\n", + pVMWARE->memPhysBase, pVMWARE->videoRam, + pVMWARE->FbBase, pVMWARE->videoRam)); + return TRUE; +} + +static Bool +VMWAREUnmapMem(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE; + + pVMWARE = VMWAREPTR(pScrn); + + VmwareLog(("Unmapped: %p/%u\n", pVMWARE->FbBase, pVMWARE->videoRam)); + + xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->FbBase, pVMWARE->videoRam); + pVMWARE->FbBase = NULL; + return TRUE; +} + +static void +VMWARESave(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg = &hwp->SavedReg; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VMWARERegPtr vmwareReg = &pVMWARE->SavedReg; + + vgaHWSave(pScrn, vgaReg, VGA_SR_ALL); + + vmwareReg->svga_reg_enable = vmwareReadReg(pVMWARE, SVGA_REG_ENABLE); + vmwareReg->svga_reg_width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH); + vmwareReg->svga_reg_height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT); + vmwareReg->svga_reg_bits_per_pixel = + vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL); + + /* XXX this should be based on the cap bit, not hwCursor... */ + if (pVMWARE->hwCursor) { + vmwareReg->svga_reg_cursor_on = + vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ON); + vmwareReg->svga_reg_cursor_x = + vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_X); + vmwareReg->svga_reg_cursor_y = + vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_Y); + vmwareReg->svga_reg_cursor_id = + vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ID); + } + + vmwareReg->svga_fifo_enabled = vmwareReadReg(pVMWARE, SVGA_REG_CONFIG_DONE); +} + +static void +VMWARERestoreRegs(ScrnInfoPtr pScrn, VMWARERegPtr vmwareReg) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VmwareLog(("VMWARERestoreRegs: W: %d, H: %d, BPP: %d, Enable: %d\n", + vmwareReg->svga_reg_width, vmwareReg->svga_reg_height, + vmwareReg->svga_reg_bits_per_pixel, vmwareReg->svga_reg_enable)); + if (vmwareReg->svga_reg_enable) { + vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width); + vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height); + vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, + vmwareReg->svga_reg_bits_per_pixel); + vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable); + vmwareWriteReg(pVMWARE, SVGA_REG_GUEST_ID, GUEST_OS_LINUX); + if (pVMWARE->hwCursor) { + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ID, + vmwareReg->svga_reg_cursor_id); + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_X, + vmwareReg->svga_reg_cursor_x); + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_Y, + vmwareReg->svga_reg_cursor_y); + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ON, + vmwareReg->svga_reg_cursor_on); + } + } else { + vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable); + } +} + +static void +VMWARERestore(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg = &hwp->SavedReg; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VMWARERegPtr vmwareReg = &pVMWARE->SavedReg; + + vmwareWaitForFB(pVMWARE); + if (!vmwareReg->svga_fifo_enabled) { + VMWAREStopFIFO(pScrn); + } + + vgaHWProtect(pScrn, TRUE); + VMWARERestoreRegs(pScrn, vmwareReg); + vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); + vgaHWProtect(pScrn, FALSE); +} + +static Bool +VMWAREModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaRegPtr vgaReg = &hwp->ModeReg; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + VMWARERegPtr vmwareReg = &pVMWARE->ModeReg; + + vgaHWUnlock(hwp); + if (!vgaHWInit(pScrn, mode)) + return FALSE; + pScrn->vtSema = TRUE; + + vmwareReg->svga_reg_enable = 1; + vmwareReg->svga_reg_width = max(mode->HDisplay, pScrn->virtualX); + vmwareReg->svga_reg_height = max(mode->VDisplay, pScrn->virtualY); + vmwareReg->svga_reg_bits_per_pixel = pVMWARE->bitsPerPixel; + + vgaHWProtect(pScrn, TRUE); + + vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); + VMWARERestoreRegs(pScrn, vmwareReg); + + if (pVMWARE->hwCursor) { + vmwareCursorModeInit(pScrn, mode); + } + + VmwareLog(("Required mode: %ux%u\n", mode->HDisplay, mode->VDisplay)); + VmwareLog(("Virtual: %ux%u\n", pScrn->virtualX, pScrn->virtualY)); + VmwareLog(("dispWidth: %u\n", pScrn->displayWidth)); + pVMWARE->fbOffset = vmwareReadReg(pVMWARE, SVGA_REG_FB_OFFSET); + pVMWARE->fbPitch = vmwareReadReg(pVMWARE, SVGA_REG_BYTES_PER_LINE); + pVMWARE->FbSize = vmwareReadReg(pVMWARE, SVGA_REG_FB_SIZE); + + pScrn->displayWidth = (pVMWARE->fbPitch * 8) / ((pScrn->bitsPerPixel + 7) & ~7); + VmwareLog(("fbOffset: %u\n", pVMWARE->fbOffset)); + VmwareLog(("fbPitch: %u\n", pVMWARE->fbPitch)); + VmwareLog(("fbSize: %u\n", pVMWARE->FbSize)); + VmwareLog(("New dispWidth: %u\n", pScrn->displayWidth)); + + vgaHWProtect(pScrn, FALSE); + + /* + * XXX -- If we want to check that we got the mode we asked for, this + * would be a good place. + */ + + /* + * Let XAA know about the mode change. + */ + if (!pVMWARE->noAccel) { + if (!vmwareXAAModeInit(pScrn, mode)) { + return FALSE; + } + } + + return TRUE; +} + +static void +VMWAREAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + /* FIXME */ +} + +static void +VMWAREInitFIFO(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + CARD32* vmwareFIFO; + + TRACEPOINT + + pVMWARE->mmioPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_MEM_START); + pVMWARE->mmioSize = vmwareReadReg(pVMWARE, SVGA_REG_MEM_SIZE) & ~3; + pVMWARE->mmioVirtBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, + pVMWARE->PciTag, + pVMWARE->mmioPhysBase, + pVMWARE->mmioSize); + vmwareFIFO = pVMWARE->vmwareFIFO = (CARD32*)pVMWARE->mmioVirtBase; + vmwareFIFO[SVGA_FIFO_MIN] = 4 * sizeof(CARD32); + vmwareFIFO[SVGA_FIFO_MAX] = pVMWARE->mmioSize; + vmwareFIFO[SVGA_FIFO_NEXT_CMD] = 4 * sizeof(CARD32); + vmwareFIFO[SVGA_FIFO_STOP] = 4 * sizeof(CARD32); + vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 1); +} + +static void +VMWAREStopFIFO(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + TRACEPOINT + + vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 0); + xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->mmioVirtBase, pVMWARE->mmioSize); +} + +static Bool +VMWARECloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + ScreenPtr save = &pVMWARE->ScrnFuncs; + + VmwareLog(("cursorSema: %d\n", pVMWARE->cursorSema)); + + if (*pVMWARE->pvtSema) { + if (pVMWARE->CursorInfoRec) { + vmwareCursorCloseScreen(pScreen); + } + + if (pVMWARE->xaaInfo) { + vmwareXAACloseScreen(pScreen); + } + + VMWARERestore(pScrn); + VMWAREUnmapMem(pScrn); + + pScrn->vtSema = FALSE; + } + + pScreen->CloseScreen = save->CloseScreen; + pScreen->SaveScreen = save->SaveScreen; + + return (*pScreen->CloseScreen)(scrnIndex, pScreen); +} + +static Bool +VMWARESaveScreen(ScreenPtr pScreen, int mode) +{ + VmwareLog(("VMWareSaveScreen() mode = %d\n", mode)); + + /* + * This thoroughly fails to do anything useful to svga mode. I doubt + * we care; who wants to idle-blank their VM's screen anyway? + */ + return vgaHWSaveScreen(pScreen, mode); +} + +/* disabled by default to reduce spew in DEBUG_LOGGING mode. */ +/*#define DEBUG_LOG_UPDATES*/ + +static void +VMWAREPreDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + +#ifdef DEBUG_LOG_UPDATES + { + int i; + for (i = 0; i < nboxes; i++) { + VmwareLog(("PreUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes - i, + boxPtr[i].x1, boxPtr[i].y1, + boxPtr[i].x2 - boxPtr[i].x1, + boxPtr[i].y2 - boxPtr[i].y1)); + } + } +#endif + + /* + * We only register this callback if we have a HW cursor. + */ + while (nboxes--) { + if (BOX_INTERSECT(*boxPtr, pVMWARE->hwcur.box)) { + PRE_OP_HIDE_CURSOR(); + pVMWARE->cursorExcludedForUpdate = TRUE; + break; + } + boxPtr++; + } +} + +static void +VMWAREPostDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + while (nboxes--) { +#ifdef DEBUG_LOG_UPDATES + VmwareLog(("PostUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes, + boxPtr->x1, boxPtr->y1, + boxPtr->x2 - boxPtr->x1, boxPtr->y2 - boxPtr->y1)); +#endif + + /* Clip off (y only) for offscreen memory */ + if (boxPtr->y2 >= pVMWARE->ModeReg.svga_reg_height) + boxPtr->y2 = pVMWARE->ModeReg.svga_reg_height; + if (boxPtr->y1 >= pVMWARE->ModeReg.svga_reg_height) + boxPtr->y1 = pVMWARE->ModeReg.svga_reg_height; + if (boxPtr->y1 == boxPtr->y2) { + boxPtr++; + continue; + } + + vmwareSendSVGACmdUpdate(pVMWARE, boxPtr++); + } + + if (pVMWARE->hwCursor && pVMWARE->cursorExcludedForUpdate) { + POST_OP_SHOW_CURSOR(); + pVMWARE->cursorExcludedForUpdate = FALSE; + } +} + +static void +VMWARELoadPalette(ScrnInfoPtr pScrn, int numColors, int* indices, + LOCO* colors, VisualPtr pVisual) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + int i; + + for (i = 0; i < numColors; i++) { + vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 0, colors[*indices].red); + vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 1, colors[*indices].green); + vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 2, colors[*indices].blue); + indices++; + } + VmwareLog(("Palette loading done\n")); +} + +static Bool +VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + ScrnInfoPtr pScrn; + vgaHWPtr hwp; + VMWAREPtr pVMWARE; + + /* Get the ScrnInfoRec */ + pScrn = xf86Screens[pScreen->myNum]; + pVMWARE = VMWAREPTR(pScrn); + + /* + * If using the vgahw module, its data structures and related + * things are typically initialised/mapped here. + */ + + hwp = VGAHWPTR(pScrn); + vgaHWGetIOBase(hwp); + + /* Save the current video state */ + VMWARESave(pScrn); + + VMWAREInitFIFO(pScrn); + + /* Initialise the first mode */ + VMWAREModeInit(pScrn, pScrn->currentMode); + + /* Set the viewport if supported */ + VMWAREAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + /* + * Setup the screen's visuals, and initialise the framebuffer + * code. + */ + VMWAREMapMem(pScrn); + + /* + * Clear the framebuffer (and any black-border mode areas). + */ + memset(pVMWARE->FbBase, 0, pVMWARE->FbSize); + vmwareSendSVGACmdUpdateFullScreen(pVMWARE); + + /* Reset the visual list */ + miClearVisualTypes(); + + /* + * Setup the visuals supported. This driver only supports + * TrueColor for bpp > 8, so the default set of visuals isn't + * acceptable. To deal with this, call miSetVisualTypes with + * the appropriate visual mask. + */ + + if (pScrn->bitsPerPixel > 8) { + if (!miSetVisualTypes(pScrn->depth, TrueColorMask, + pScrn->rgbBits, pScrn->defaultVisual)) { + return FALSE; + } + } else { + if (!miSetVisualTypes(pScrn->depth, + miGetDefaultVisualMask(pScrn->depth), + pScrn->rgbBits, pScrn->defaultVisual)) { + return FALSE; + } + } + + miSetPixmapDepths(); + + /* + * Initialise the framebuffer. + */ + if (!fbScreenInit(pScreen, pVMWARE->FbBase + pVMWARE->fbOffset, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth, + pScrn->bitsPerPixel)) { + return FALSE; + } + + /* Override the default mask/offset settings */ + if (pScrn->bitsPerPixel > 8) { + int i; + VisualPtr visual; + + for (i = 0, visual = pScreen->visuals; + i < pScreen->numVisuals; i++, visual++) { + if ((visual->class | DynamicClass) == DirectColor) { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } + + /* must be after RGB ordering fixed */ + fbPictureInit (pScreen, 0, 0); + + /* + * Save the old screen vector, then wrap CloseScreen and + * set SaveScreen. + */ + pVMWARE->ScrnFuncs = *pScreen; + pScreen->CloseScreen = VMWARECloseScreen; + pScreen->SaveScreen = VMWARESaveScreen; + + /* + * Set initial black & white colourmap indices. + */ + xf86SetBlackWhitePixels(pScreen); + + /* + * Initialize shadowfb to notify us of dirty rectangles. We only + * need preFB access callbacks if we're using the hw cursor. + */ + if (!ShadowFBInit2(pScreen, + pVMWARE->hwCursor ? VMWAREPreDirtyBBUpdate : NULL, + VMWAREPostDirtyBBUpdate)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ShadowFB initialization failed\n"); + return FALSE; + } + + /* + * If we have a hw cursor, we need to hook functions that might + * read from the framebuffer. + */ + if (pVMWARE->hwCursor) { + vmwareCursorHookWrappers(pScreen); + } + + /* + * Initialize acceleration. + */ + if (!pVMWARE->noAccel) { + if (!vmwareXAAScreenInit(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "XAA initialization failed -- running unaccelerated!\n"); + pVMWARE->noAccel = TRUE; + } + } + + /* + * If backing store is to be supported (as is usually the case), + * initialise it. + */ + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + xf86SetSilkenMouse(pScreen); + + /* + * Initialize software cursor. + */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + /* + * Initialize hardware cursor. + */ + if (pVMWARE->hwCursor) { + if (!vmwareCursorInit(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Hardware cursor initialization failed\n"); + pVMWARE->hwCursor = FALSE; + } + } + + /* + * Install colourmap functions. If using the vgahw module, + * vgaHandleColormaps would usually be called here. + */ + + if (!fbCreateDefColormap(pScreen)) + return FALSE; + + if (!xf86HandleColormaps(pScreen, 256, 8, + VMWARELoadPalette, NULL, + CMAP_PALETTED_TRUECOLOR | + CMAP_RELOAD_ON_MODE_SWITCH)) { + return FALSE; + } + + /* Report any unused options (only for the first generation) */ + if (serverGeneration == 1) { + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + } + + /* Done */ + return TRUE; +} + +static Bool +VMWARESwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + return VMWAREModeInit(xf86Screens[scrnIndex], mode); +} + +static Bool +VMWAREEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + if (!pVMWARE->SavedReg.svga_fifo_enabled) { + VMWAREInitFIFO(pScrn); + } + return VMWAREModeInit(pScrn, pScrn->currentMode); +} + +static void +VMWARELeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + VMWARERestore(pScrn); +} + +static void +VMWAREFreeScreen(int scrnIndex, int flags) +{ + /* + * If the vgahw module is used vgaHWFreeHWRec() would be called + * here. + */ + VMWAREFreeRec(xf86Screens[scrnIndex]); +} + +static Bool +VMWAREValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + return MODE_OK; +} + +static Bool +VMWAREProbe(DriverPtr drv, int flags) +{ + int numDevSections, numUsed; + GDevPtr *devSections; + int *usedChips; + int i; + Bool foundScreen = FALSE; + char buildString[sizeof(VMWAREBuildStr)]; + + RewriteTagString(VMWAREBuildStr, buildString, sizeof(VMWAREBuildStr)); + xf86MsgVerb(X_PROBED, 4, "%s", buildString); + + numDevSections = xf86MatchDevice(VMWARE_DRIVER_NAME, &devSections); + if (numDevSections <= 0) { +#ifdef DEBUG + xf86MsgVerb(X_ERROR, 0, "No vmware driver section\n"); +#endif + return FALSE; + } + if (xf86GetPciVideoInfo()) { + VmwareLog(("Some PCI Video Info Exists\n")); + numUsed = xf86MatchPciInstances(VMWARE_NAME, PCI_VENDOR_VMWARE, + VMWAREChipsets, VMWAREPciChipsets, devSections, + numDevSections, drv, &usedChips); + xfree(devSections); + if (numUsed <= 0) + return FALSE; + if (flags & PROBE_DETECT) + foundScreen = TRUE; + else + for (i = 0; i < numUsed; i++) { + ScrnInfoPtr pScrn = NULL; + + VmwareLog(("Even some VMware SVGA PCI instances exists\n")); + pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i], + VMWAREPciChipsets, NULL, NULL, NULL, + NULL, NULL); + if (pScrn) { + VmwareLog(("And even configuration suceeded\n")); + pScrn->driverVersion = VERSION; + pScrn->driverName = VMWARE_DRIVER_NAME; + pScrn->name = VMWARE_NAME; + pScrn->Probe = VMWAREProbe; + pScrn->PreInit = VMWAREPreInit; + pScrn->ScreenInit = VMWAREScreenInit; + pScrn->SwitchMode = VMWARESwitchMode; + pScrn->AdjustFrame = VMWAREAdjustFrame; + pScrn->EnterVT = VMWAREEnterVT; + pScrn->LeaveVT = VMWARELeaveVT; + pScrn->FreeScreen = VMWAREFreeScreen; + pScrn->ValidMode = VMWAREValidMode; + foundScreen = TRUE; + } + } + xfree(usedChips); + } + return foundScreen; +} + +DriverRec VMWARE = { + VERSION, + VMWARE_DRIVER_NAME, + VMWAREIdentify, + VMWAREProbe, + VMWAREAvailableOptions, + NULL, + 0 +}; + +#ifdef XFree86LOADER +static MODULESETUPPROTO(vmwareSetup); + +XF86ModuleData vmwareModuleData = { &vmwareVersRec, vmwareSetup, NULL }; + +static pointer +vmwareSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + if (!setupDone) { + setupDone = TRUE; + xf86AddDriver(&VMWARE, module, 0); + + LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols, + shadowfbSymbols, vmwareXaaSymbols, NULL); + + return (pointer)1; + } + if (errmaj) { + *errmaj = LDR_ONCEONLY; + } + return NULL; +} +#endif /* XFree86LOADER */ diff --git a/src/vmware.h b/src/vmware.h new file mode 100644 index 0000000..4059275 --- /dev/null +++ b/src/vmware.h @@ -0,0 +1,265 @@ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * Id: vmware.h,v 1.6 2001/01/30 18:13:47 bennett Exp $ + * **********************************************************/ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/vmware.h,v 1.10 2003/02/04 01:39:53 dawes Exp $ */ + +#ifndef VMWARE_H +#define VMWARE_H + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Resources.h" + +#include "compiler.h" /* inb/outb */ + +#include "xf86PciInfo.h" /* pci vendor id */ +#include "xf86Pci.h" /* pci */ +#include "xf86Cursor.h" /* hw cursor */ + +#include "vgaHW.h" /* VGA hardware */ +#include "fb.h" +#include "xaa.h" + +#include "xf86cmap.h" /* xf86HandleColormaps */ + +#include "vm_basic_types.h" +#include "svga_reg.h" +#include "svga_struct.h" + +#include "offscreen_manager.h" + +/* Arbitrarily choose max cursor dimensions. The emulation doesn't care. */ +#define MAX_CURS 32 + +typedef struct { + CARD32 svga_reg_enable; + CARD32 svga_reg_width; + CARD32 svga_reg_height; + CARD32 svga_reg_bits_per_pixel; + + CARD32 svga_reg_cursor_on; + CARD32 svga_reg_cursor_x; + CARD32 svga_reg_cursor_y; + CARD32 svga_reg_cursor_id; + + Bool svga_fifo_enabled; +} VMWARERegRec, *VMWARERegPtr; + +typedef struct { + EntityInfoPtr pEnt; + pciVideoPtr PciInfo; + PCITAG PciTag; + Bool Primary; + int depth; + int bitsPerPixel; + rgb weight; + rgb offset; + int defaultVisual; + int videoRam; + unsigned long memPhysBase; + unsigned long fbOffset; + unsigned long fbPitch; + unsigned long ioBase; + int maxWidth; + int maxHeight; + unsigned int vmwareCapability; + + unsigned char* FbBase; + unsigned long FbSize; + + VMWARERegRec SavedReg; + VMWARERegRec ModeReg; + + Bool* pvtSema; + + Bool noAccel; + Bool hwCursor; + Bool cursorDefined; + int cursorSema; + Bool cursorExcludedForUpdate; + Bool cursorShouldBeHidden; + + unsigned int cursorRemoveFromFB; + unsigned int cursorRestoreToFB; + +#ifdef RENDER + CompositeProcPtr Composite; +#endif /* RENDER */ + + unsigned long mmioPhysBase; + unsigned long mmioSize; + + unsigned char* mmioVirtBase; + CARD32* vmwareFIFO; + + xf86CursorInfoPtr CursorInfoRec; + struct { + int bg, fg, x, y; + BoxRec box; + + uint32 mask[SVGA_BITMAP_SIZE(MAX_CURS, MAX_CURS)]; + uint32 maskPixmap[SVGA_PIXMAP_SIZE(MAX_CURS, MAX_CURS, 32)]; + uint32 source[SVGA_BITMAP_SIZE(MAX_CURS, MAX_CURS)]; + uint32 sourcePixmap[SVGA_PIXMAP_SIZE(MAX_CURS, MAX_CURS, 32)]; + } hwcur; + + IOADDRESS indexReg, valueReg; + + ScreenRec ScrnFuncs; + + /* + * XAA info rec and misc storage + */ + XAAInfoRecPtr xaaInfo; + int xaaFGColor; + int xaaBGColor; + int xaaRop; + + unsigned char* xaaColorExpScanLine[1]; + unsigned int xaaColorExpSize; /* size of current scan line in DWords */ + + Heap* heap; + SVGASurface* frontBuffer; + + SVGASurface* curPict; + int op; + +} VMWARERec, *VMWAREPtr; + +#define VMWAREPTR(p) ((VMWAREPtr)((p)->driverPrivate)) + +static __inline ScrnInfoPtr infoFromScreen(ScreenPtr s) { + return xf86Screens[s->myNum]; +} + +#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define ABS(x) (((x) >= 0) ? (x) : -(x)) + +#define BOX_INTERSECT(a, b) \ + (ABS(((a).x1 + (a).x2) - ((b).x1 + (b).x2)) <= \ + ((a).x2 - (a).x1) + ((b).x2 - (b).x1) && \ + ABS(((a).y1 + (a).y2) - ((b).y1 + (b).y2)) <= \ + ((a).y2 - (a).y1) + ((b).y2 - (b).y1)) + +#define SVGA_GLYPH_SCANLINE_SIZE_DWORDS(w) (((w) + 31) >> 5) + +#define PRE_OP_HIDE_CURSOR() \ + if (pVMWARE->cursorDefined && *pVMWARE->pvtSema) { \ + pVMWARE->cursorSema++; \ + if (pVMWARE->cursorSema == 1) { \ + vmwareWriteCursorRegs(pVMWARE, FALSE, FALSE); \ + } \ + } +#define POST_OP_SHOW_CURSOR() \ + if (pVMWARE->cursorDefined && *pVMWARE->pvtSema) { \ + pVMWARE->cursorSema--; \ + if (!pVMWARE->cursorSema && !pVMWARE->cursorShouldBeHidden) { \ + vmwareWriteCursorRegs(pVMWARE, TRUE, FALSE); \ + } \ + } + +#define MOUSE_ID 1 + +extern const char *vmwareXaaSymbols[]; + +/*#define DEBUG_LOGGING*/ +#ifdef DEBUG_LOGGING +# define VmwareLog(args) ErrorF args +# define TRACEPOINT VmwareLog((__FUNCTION__ ":" __FILE__ "\n")); +#else +# define VmwareLog(args) +# define TRACEPOINT +#endif + +/* Undefine this to kill all acceleration */ +#define ACCELERATE_OPS + +void vmwareWriteReg( +#if NeedFunctionPrototypes + VMWAREPtr pVMWARE, int index, CARD32 value +#endif + ); + +CARD32 vmwareReadReg( +#if NeedFunctionPrototypes + VMWAREPtr pVMWARE, int index +#endif + ); + +void vmwareWriteWordToFIFO( +#if NeedFunctionPrototypes + VMWAREPtr pVMWARE, CARD32 value +#endif + ); + +void vmwareWaitForFB( +#ifdef NeedFunctionPrototypes + VMWAREPtr pVMWARE +#endif + ); + +void vmwareSendSVGACmdUpdate( +#if NeedFunctionPrototypes + VMWAREPtr pVMWARE, BoxPtr pBB +#endif + ); + +/* vmwarecurs.c */ +Bool vmwareCursorInit( +#if NeedFunctionPrototypes + ScreenPtr pScr +#endif + ); + +void vmwareCursorModeInit( +#if NeedFunctionPrototypes + ScrnInfoPtr pScrn, + DisplayModePtr mode +#endif + ); + +void vmwareCursorCloseScreen( +#if NeedFunctionPrototypes + ScreenPtr pScr +#endif + ); + +void vmwareWriteCursorRegs( +#if NeedFunctionPrototypes + VMWAREPtr pVMWARE, + Bool visible, + Bool force +#endif + ); + +void vmwareCursorHookWrappers( +#if NeedFunctionPrototypes + ScreenPtr pScreen +#endif + ); + + +/* vmwarexaa.c */ +Bool vmwareXAAScreenInit( +#if NeedFunctionPrototypes + ScreenPtr pScreen +#endif + ); + +Bool vmwareXAAModeInit( +#if NeedFunctionPrototypes + ScrnInfoPtr pScrn, DisplayModePtr mode +#endif + ); + +void vmwareXAACloseScreen( +#if NeedFunctionPrototypes + ScreenPtr pScreen +#endif + ); + +#endif diff --git a/src/vmwarecurs.c b/src/vmwarecurs.c new file mode 100644 index 0000000..1a7c6eb --- /dev/null +++ b/src/vmwarecurs.c @@ -0,0 +1,445 @@ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ +#ifdef VMX86_DEVEL +char rcsId_vmwarecurs[] = + "Id: vmwarecurs.c,v 1.5 2001/01/30 23:33:02 bennett Exp $"; +#endif +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/vmwarecurs.c,v 1.11 2003/02/05 12:47:42 dawes Exp $ */ + +#include "vmware.h" +#include "bits2pixels.h" + +static void VMWAREGetImage(DrawablePtr src, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, + char *pBinImage); +static void VMWARECopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr prgnSrc); + +#ifdef RENDER +static void VMWAREComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, + PicturePtr pDst, INT16 xSrc, INT16 ySrc, + INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, + CARD16 width, CARD16 height); +#endif /* RENDER */ + +static void +RedefineCursor(VMWAREPtr pVMWARE) +{ + int i; + + VmwareLog(("RedefineCursor\n")); + + pVMWARE->cursorDefined = FALSE; + + /* Define cursor */ + vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_DEFINE_CURSOR); + vmwareWriteWordToFIFO(pVMWARE, MOUSE_ID); + vmwareWriteWordToFIFO(pVMWARE, 0); /* HotX/HotY seem to be zero? */ + vmwareWriteWordToFIFO(pVMWARE, 0); /* HotX/HotY seem to be zero? */ + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->CursorInfoRec->MaxWidth); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->CursorInfoRec->MaxHeight); + vmwareWriteWordToFIFO(pVMWARE, 1); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->bitsPerPixel); + + /* + * Since we have AND and XOR masks rather than 'source' and 'mask', + * color expand 'mask' with all zero as its foreground and all one as + * its background. This makes 'image & 0 ^ 'source' = source. We + * arange for 'image' & 1 ^ 'source' = 'image' below when we clip + * 'source' below. + */ + vmwareRaster_BitsToPixels((uint8 *) pVMWARE->hwcur.mask, + SVGA_BITMAP_INCREMENT(pVMWARE->CursorInfoRec->MaxWidth), + (uint8 *) pVMWARE->hwcur.maskPixmap, + SVGA_PIXMAP_INCREMENT(pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->bitsPerPixel), + pVMWARE->bitsPerPixel / 8, + pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->CursorInfoRec->MaxHeight, 0, ~0); + for (i = 0; i < SVGA_BITMAP_SIZE(pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->CursorInfoRec->MaxHeight); i++) { + vmwareWriteWordToFIFO(pVMWARE, ~pVMWARE->hwcur.mask[i]); + } + + vmwareRaster_BitsToPixels((uint8 *) pVMWARE->hwcur.source, + SVGA_BITMAP_INCREMENT(pVMWARE->CursorInfoRec->MaxWidth), + (uint8 *) pVMWARE->hwcur.sourcePixmap, + SVGA_PIXMAP_INCREMENT(pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->bitsPerPixel), + pVMWARE->bitsPerPixel / 8, + pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->CursorInfoRec->MaxHeight, + pVMWARE->hwcur.fg, pVMWARE->hwcur.bg); + /* + * As pointed out above, we need to clip the expanded 'source' against + * the expanded 'mask' since we actually have AND and XOR masks in the + * virtual hardware. Effectively, 'source' becomes a three color fg/bg/0 + * pixmap that XORs appropriately. + */ + for (i = 0; i < SVGA_PIXMAP_SIZE(pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->CursorInfoRec->MaxHeight, + pVMWARE->bitsPerPixel); i++) { + pVMWARE->hwcur.sourcePixmap[i] &= ~pVMWARE->hwcur.maskPixmap[i]; + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->hwcur.sourcePixmap[i]); + } + + /* Sync the FIFO, so that the definition preceeds any use of the cursor */ + vmwareWaitForFB(pVMWARE); + pVMWARE->cursorDefined = TRUE; +} + +static void +vmwareSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + TRACEPOINT + + if (pVMWARE->hwcur.fg != fg || pVMWARE->hwcur.bg != bg) { + VmwareLog(("SetCursorColors(0x%08x, 0x%08x)\n", bg, fg)); + pVMWARE->hwcur.fg = fg; + pVMWARE->hwcur.bg = bg; + RedefineCursor(pVMWARE); + } +} + +static void +vmwareLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src ) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + const int imageSize = SVGA_BITMAP_SIZE(pVMWARE->CursorInfoRec->MaxWidth, + pVMWARE->CursorInfoRec->MaxHeight); + TRACEPOINT + + memcpy(pVMWARE->hwcur.source, src, imageSize * sizeof(uint32)); + memcpy(pVMWARE->hwcur.mask, + src + imageSize * sizeof(uint32), imageSize * sizeof(uint32)); + RedefineCursor(pVMWARE); +} + +#ifdef ARGB_CURSOR +#include "cursorstr.h" + +static Bool +vmwareUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs) +{ + ScrnInfoPtr pScrn = infoFromScreen(pScreen); + return pCurs->bits->height <= MAX_CURS && + pCurs->bits->width <= MAX_CURS && + pScrn->bitsPerPixel > 8; +} + +static void +vmwareLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + CARD32 width = pCurs->bits->width; + CARD32 height = pCurs->bits->height; + CARD32* image = pCurs->bits->argb; + CARD32* imageEnd = image + (width * height); + + pVMWARE->cursorDefined = FALSE; + + vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_DEFINE_ALPHA_CURSOR); + vmwareWriteWordToFIFO(pVMWARE, MOUSE_ID); + vmwareWriteWordToFIFO(pVMWARE, 0); + vmwareWriteWordToFIFO(pVMWARE, 0); + vmwareWriteWordToFIFO(pVMWARE, width); + vmwareWriteWordToFIFO(pVMWARE, height); + + while (image != imageEnd) { + vmwareWriteWordToFIFO(pVMWARE, *image++); + } + + vmwareWaitForFB(pVMWARE); + + pVMWARE->cursorDefined = TRUE; +} +#endif + +void +vmwareWriteCursorRegs(VMWAREPtr pVMWARE, Bool visible, Bool force) +{ + int enableVal; + + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ID, MOUSE_ID); + if (visible) { + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_X, pVMWARE->hwcur.x); + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_Y, pVMWARE->hwcur.y); + } + + if (force) { + enableVal = visible ? SVGA_CURSOR_ON_SHOW : SVGA_CURSOR_ON_HIDE; + } else { + enableVal = visible ? pVMWARE->cursorRestoreToFB : + pVMWARE->cursorRemoveFromFB; + } + vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ON, enableVal); +} + +/* disabled by default to reduce spew in DEBUG_LOGGING mode. */ +/* #define DEBUG_LOG_MOUSE_HIDE_SHOW */ + +static void +vmwareShowCursor(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); +#ifdef DEBUG_LOG_MOUSE_HIDE_SHOW + VmwareLog(("Show: %d %d %d\n", pVMWARE->cursorSema, pVMWARE->cursorDefined, + pVMWARE->cursorShouldBeHidden)); +#endif + pVMWARE->cursorShouldBeHidden = FALSE; + if (pVMWARE->cursorSema == 0 && pVMWARE->cursorDefined) { + vmwareWriteCursorRegs(pVMWARE, TRUE, TRUE); + } +} + +static void +vmwareHideCursor(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); +#ifdef DEBUG_LOG_MOUSE_HIDE_SHOW + VmwareLog(("Hide: %d %d %d\n", pVMWARE->cursorSema, pVMWARE->cursorDefined, + pVMWARE->cursorShouldBeHidden)); +#endif + if (pVMWARE->cursorDefined) { + vmwareWriteCursorRegs(pVMWARE, FALSE, TRUE); + } + pVMWARE->cursorShouldBeHidden = TRUE; +} + +/* disabled by default to reduce spew in DEBUG_LOGGING mode. */ +/* #define DEBUG_LOG_MOUSE_MOVE */ + +static void +vmwareSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); +#ifdef DEBUG_LOG_MOUSE_MOVE + VmwareLog(("Move: %d %d %d\n", pVMWARE->cursorSema, pVMWARE->cursorDefined, + pVMWARE->cursorShouldBeHidden)); +#endif + /* + * We're bad people. We have no concept of a frame (VMWAREAdjustFrame() + * is a NOP). The hwcursor code expects us to be frame aware though, so + * we have to do this. I'm open to suggestions. I tried not even + * hooking AdjustFrame and it didn't help. + */ + pVMWARE->hwcur.x = x + pScrn->frameX0; + pVMWARE->hwcur.y = y + pScrn->frameY0; + pVMWARE->hwcur.box.x1 = pVMWARE->hwcur.x; + pVMWARE->hwcur.box.x2 = pVMWARE->hwcur.x + pVMWARE->CursorInfoRec->MaxWidth; + pVMWARE->hwcur.box.y1 = pVMWARE->hwcur.y; + pVMWARE->hwcur.box.y2 = pVMWARE->hwcur.y + pVMWARE->CursorInfoRec->MaxHeight; + + vmwareShowCursor(pScrn); +} + +void +vmwareCursorModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + if (pVMWARE->cursorDefined) { + vmwareWriteCursorRegs(pVMWARE, !pVMWARE->cursorShouldBeHidden, TRUE); + } +} + +Bool +vmwareCursorInit(ScreenPtr pScreen) +{ + xf86CursorInfoPtr infoPtr; + VMWAREPtr pVMWARE = VMWAREPTR(infoFromScreen(pScreen)); + Bool ret; + + TRACEPOINT + + /* Require cursor bypass for hwcursor. Ignore deprecated FIFO hwcursor */ + if (!(pVMWARE->vmwareCapability & SVGA_CAP_CURSOR_BYPASS)) { + return FALSE; + } + + infoPtr = xf86CreateCursorInfoRec(); + if (!infoPtr) + return FALSE; + + pVMWARE->CursorInfoRec = infoPtr; + + infoPtr->MaxWidth = MAX_CURS; + infoPtr->MaxHeight = MAX_CURS; + infoPtr->Flags = HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | + HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED; + infoPtr->SetCursorColors = vmwareSetCursorColors; + infoPtr->SetCursorPosition = vmwareSetCursorPosition; + infoPtr->LoadCursorImage = vmwareLoadCursorImage; + infoPtr->HideCursor = vmwareHideCursor; + infoPtr->ShowCursor = vmwareShowCursor; + +#ifdef ARGB_CURSOR + if (pVMWARE->vmwareCapability & SVGA_CAP_ALPHA_CURSOR) { + infoPtr->UseHWCursorARGB = vmwareUseHWCursorARGB; + infoPtr->LoadCursorARGB = vmwareLoadCursorARGB; + } +#endif + + ret = xf86InitCursor(pScreen, infoPtr); + if (!ret) { + xf86DestroyCursorInfoRec(infoPtr); + pVMWARE->CursorInfoRec = NULL; + } + return ret; +} + +void +vmwareCursorCloseScreen(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = infoFromScreen(pScreen); + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); +#endif + + pScreen->GetImage = pVMWARE->ScrnFuncs.GetImage; + pScreen->CopyWindow = pVMWARE->ScrnFuncs.CopyWindow; +#ifdef RENDER + if (ps) { + ps->Composite = pVMWARE->Composite; + } +#endif /* RENDER */ + + vmwareHideCursor(pScrn); + xf86DestroyCursorInfoRec(pVMWARE->CursorInfoRec); +} + +/*** Wrap functions that read from the framebuffer ***/ + +void +vmwareCursorHookWrappers(ScreenPtr pScreen) +{ + VMWAREPtr pVMWARE = VMWAREPTR(infoFromScreen(pScreen)); +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); +#endif + + TRACEPOINT + + pVMWARE->ScrnFuncs.GetImage = pScreen->GetImage; + pVMWARE->ScrnFuncs.CopyWindow = pScreen->CopyWindow; + pScreen->GetImage = VMWAREGetImage; + pScreen->CopyWindow = VMWARECopyWindow; + +#ifdef RENDER + if (ps) { + pVMWARE->Composite = ps->Composite; + ps->Composite = VMWAREComposite; + } +#endif /* RENDER */ + +} + +static void +VMWAREGetImage(DrawablePtr src, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *pBinImage) +{ + ScreenPtr pScreen = src->pScreen; + VMWAREPtr pVMWARE = VMWAREPTR(infoFromScreen(src->pScreen)); + BoxRec box; + Bool hidden = FALSE; + + VmwareLog(("VMWAREGetImage(%p, %d, %d, %d, %d, %d, %d, %p)\n", + src, x, y, w, h, format, planeMask, pBinImage)); + + box.x1 = src->x + x; + box.y1 = src->y + y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + + if (BOX_INTERSECT(box, pVMWARE->hwcur.box)) { + PRE_OP_HIDE_CURSOR(); + hidden = TRUE; + } + + pScreen->GetImage = pVMWARE->ScrnFuncs.GetImage; + (*pScreen->GetImage)(src, x, y, w, h, format, planeMask, pBinImage); + pScreen->GetImage = VMWAREGetImage; + + if (hidden) { + POST_OP_SHOW_CURSOR(); + } +} + +static void +VMWARECopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + VMWAREPtr pVMWARE = VMWAREPTR(infoFromScreen(pWin->drawable.pScreen)); + BoxPtr pBB; + Bool hidden = FALSE; + + /* + * We only worry about the source region here, since shadowfb will + * take care of the destination region. + */ + pBB = REGION_EXTENTS(pWin->drawable.pScreen, prgnSrc); + + VmwareLog(("VMWARECopyWindow(%p, (%d, %d), (%d, %d - %d, %d)\n", + pWin, ptOldOrg.x, ptOldOrg.y, + pBB->x1, pBB->y1, pBB->x2, pBB->y2)); + + if (BOX_INTERSECT(*pBB, pVMWARE->hwcur.box)) { + PRE_OP_HIDE_CURSOR(); + hidden = TRUE; + } + + pScreen->CopyWindow = pVMWARE->ScrnFuncs.CopyWindow; + (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + pScreen->CopyWindow = VMWARECopyWindow; + + if (hidden) { + POST_OP_SHOW_CURSOR(); + } +} + +#ifdef RENDER +static void +VMWAREComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, + PicturePtr pDst, INT16 xSrc, INT16 ySrc, + INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, + CARD16 width, CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + VMWAREPtr pVMWARE = VMWAREPTR(infoFromScreen(pScreen)); + PictureScreenPtr ps = GetPictureScreen(pScreen); + BoxRec box; + Bool hidden = FALSE; + + VmwareLog(("VMWAREComposite op = %d, pSrc = %p, pMask = %p, pDst = %p," + " src = (%d, %d), mask = (%d, %d), dst = (%d, %d), w = %d," + " h = %d\n", op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height)); + + /* + * We only worry about the source region here, since shadowfb or XAA will + * take care of the destination region. + */ + box.x1 = pSrc->pDrawable->x + xSrc; + box.y1 = pSrc->pDrawable->y + ySrc; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + + if (BOX_INTERSECT(box, pVMWARE->hwcur.box)) { + PRE_OP_HIDE_CURSOR(); + hidden = TRUE; + } + + ps->Composite = pVMWARE->Composite; + (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc, + xMask, yMask, xDst, yDst, width, height); + ps->Composite = VMWAREComposite; + + if (hidden) { + POST_OP_SHOW_CURSOR(); + } +} +#endif /* RENDER */ diff --git a/src/vmwarexaa.c b/src/vmwarexaa.c new file mode 100644 index 0000000..b8e67cf --- /dev/null +++ b/src/vmwarexaa.c @@ -0,0 +1,549 @@ +/* ********************************************************** + * Copyright (C) 1998-2001 VMware, Inc. + * All Rights Reserved + * **********************************************************/ +#ifdef VMX86_DEVEL +char rcsId_vmwarexaa[] = + "Id: $"; +#endif +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/vmwarexaa.c,v 1.5 2003/02/04 01:39:53 dawes Exp $ */ + +#include "vmware.h" + +#define OFFSCREEN_SCRATCH_SIZE 1*1024*1024 +/* We'll assume we average about 32x32 alpha surfaces (4096 bytes) or larger */ +#define OFFSCREEN_SCRATCH_MAX_SLOTS OFFSCREEN_SCRATCH_SIZE / 4096 + +const char *vmwareXaaSymbols[] = { + "XAACreateInfoRec", + "XAADestroyInfoRec", + "XAAInit", + NULL +}; + +static void vmwareXAASync(ScrnInfoPtr pScrn); + +static void vmwareSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask); +static void vmwareSubsequentSolidFillRect(ScrnInfoPtr pScrn, + int x, int y, int w, int h); + +static void vmwareSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, + int trans_color); +static void vmwareSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int x1, int y1, + int x2, int y2, + int width, int height); + +static void vmwareSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask); +static void vmwareSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int x, int y, + int w, int h, + int skipleft ); +static void vmwareSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); + +#ifdef RENDER +static Bool vmwareSetupForCPUToScreenAlphaTexture(ScrnInfoPtr pScrn, int op, + CARD16 red, CARD16 green, + CARD16 blue, CARD16 alpha, + int alphaType, CARD8 *alphaPtr, + int alphaPitch, + int width, int height, + int flags); + +static Bool vmwareSetupForCPUToScreenTexture(ScrnInfoPtr pScrn, int op, + int texType, CARD8 *texPtr, + int texPitch, + int width, int height, + int flags); + +static void vmwareSubsequentCPUToScreenTexture(ScrnInfoPtr pScrn, + int dstx, int dsty, + int srcx, int srcy, + int width, int height); + +CARD32 vmwareAlphaTextureFormats[2] = {PICT_a8, 0}; +CARD32 vmwareTextureFormats[2] = {PICT_a8r8g8b8, 0}; + +#endif + +#define DESTROY_XAA_INFO(pVMWARE) \ + if (pVMWARE->xaaInfo) { XAADestroyInfoRec(pVMWARE->xaaInfo); \ + pVMWARE->xaaInfo = NULL; } + +Bool +vmwareXAAScreenInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + XAAInfoRecPtr xaaInfo; + + pVMWARE->xaaInfo = XAACreateInfoRec(); + if (!pVMWARE->xaaInfo) { + return FALSE; + } + + xaaInfo = pVMWARE->xaaInfo; + + xaaInfo->Sync = vmwareXAASync; + + if (pVMWARE->vmwareCapability & SVGA_CAP_RECT_FILL) { + xaaInfo->SetupForSolidFill = vmwareSetupForSolidFill; + xaaInfo->SubsequentSolidFillRect = vmwareSubsequentSolidFillRect; + + xaaInfo->SolidFillFlags = NO_PLANEMASK | + (pVMWARE->vmwareCapability & SVGA_CAP_RASTER_OP ? 0 : GXCOPY_ONLY); + } + + if (pVMWARE->vmwareCapability & SVGA_CAP_RECT_COPY) { + xaaInfo->SetupForScreenToScreenCopy = vmwareSetupForScreenToScreenCopy; + xaaInfo->SubsequentScreenToScreenCopy = + vmwareSubsequentScreenToScreenCopy; + + xaaInfo->ScreenToScreenCopyFlags = NO_TRANSPARENCY | NO_PLANEMASK | + (pVMWARE->vmwareCapability & SVGA_CAP_RASTER_OP ? 0 : GXCOPY_ONLY); + } + + /* + * We don't support SVGA_CAP_GLYPH without clipping, since we use clipping + * for normal glyphs. + */ + if (pVMWARE->vmwareCapability & SVGA_CAP_GLYPH_CLIPPING) { + xaaInfo->SetupForScanlineCPUToScreenColorExpandFill = + vmwareSetupForScanlineCPUToScreenColorExpandFill; + xaaInfo->SubsequentScanlineCPUToScreenColorExpandFill = + vmwareSubsequentScanlineCPUToScreenColorExpandFill; + xaaInfo->SubsequentColorExpandScanline = + vmwareSubsequentColorExpandScanline; + + xaaInfo->NumScanlineColorExpandBuffers = 1; + xaaInfo->ScanlineColorExpandBuffers = pVMWARE->xaaColorExpScanLine; + + xaaInfo->ScanlineCPUToScreenColorExpandFillFlags = GXCOPY_ONLY | + NO_PLANEMASK | BIT_ORDER_IN_BYTE_MSBFIRST | LEFT_EDGE_CLIPPING; + } + + if (pVMWARE->vmwareCapability & SVGA_CAP_OFFSCREEN_1) { + int scratchSizeBytes = ((OFFSCREEN_SCRATCH_SIZE + pVMWARE->fbPitch - 1) / + pVMWARE->fbPitch) * pVMWARE->fbPitch; + BoxRec box; + RegionRec region; + + box.x1 = 0; + box.y1 = (pVMWARE->FbSize + pVMWARE->fbPitch - 1) / pVMWARE->fbPitch; + box.x2 = pScrn->displayWidth; + box.y2 = pVMWARE->videoRam / pVMWARE->fbPitch; + +#ifdef RENDER + if (pVMWARE->vmwareCapability & SVGA_CAP_ALPHA_BLEND && + pScrn->bitsPerPixel > 8) { + if (box.y2 - (scratchSizeBytes / pVMWARE->fbPitch) > box.y1 + 4) { + CARD8* osPtr = pVMWARE->FbBase + pVMWARE->videoRam - + scratchSizeBytes; + box.y2 -= scratchSizeBytes / pVMWARE->fbPitch; + + VmwareLog(("Allocated %d bytes at offset %d for alpha scratch\n", + scratchSizeBytes, + pVMWARE->videoRam - scratchSizeBytes)); + + pVMWARE->heap = vmwareHeap_Create(osPtr, + scratchSizeBytes, + OFFSCREEN_SCRATCH_MAX_SLOTS, + pVMWARE->videoRam - scratchSizeBytes, + pScrn->virtualX, + pScrn->virtualY, + pVMWARE->bitsPerPixel, + pVMWARE->fbPitch, + pVMWARE->fbOffset); + pVMWARE->frontBuffer = vmwareHeap_GetFrontBuffer(pVMWARE->heap); + + xaaInfo->SetupForCPUToScreenAlphaTexture = + vmwareSetupForCPUToScreenAlphaTexture; + xaaInfo->SubsequentCPUToScreenAlphaTexture = + vmwareSubsequentCPUToScreenTexture; + xaaInfo->CPUToScreenAlphaTextureFlags = XAA_RENDER_NO_TILE | + XAA_RENDER_NO_SRC_ALPHA; + xaaInfo->CPUToScreenAlphaTextureFormats = vmwareAlphaTextureFormats; + + xaaInfo->SetupForCPUToScreenTexture = + vmwareSetupForCPUToScreenTexture; + xaaInfo->SubsequentCPUToScreenTexture = + vmwareSubsequentCPUToScreenTexture; + xaaInfo->CPUToScreenTextureFlags = XAA_RENDER_NO_TILE; + xaaInfo->CPUToScreenTextureFormats = vmwareTextureFormats; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Allocation of offscreen " + "scratch area for alpha blending failed\n"); + } + } +#endif + + if (box.y2 > box.y1) { + REGION_INIT(pScreen, ®ion, &box, 1); + + if (REGION_NOTEMPTY(pScreen, ®ion) && + xf86InitFBManagerRegion(pScreen, ®ion)) { + VmwareLog(("Offscreen memory initialized: (%d, %d) - (%d, %d)\n", + box.x1, box.y1, box.x2, box.y2)); + + xaaInfo->Flags = + LINEAR_FRAMEBUFFER | PIXMAP_CACHE | OFFSCREEN_PIXMAPS; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Offscreen memory manager " + "initialization failed.\n"); + } + + REGION_UNINIT(pScreen, ®ion); + } + } + + if (!XAAInit(pScreen, xaaInfo)) { + DESTROY_XAA_INFO(pVMWARE); + return FALSE; + } + + return TRUE; +} + +Bool +vmwareXAAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + /* + * Alloc a sufficiently large buffer for XAA to render scanlines + * for a color expand into. + */ + if (pVMWARE->vmwareCapability & SVGA_CAP_GLYPH) { + /* + * This formula came straight from the XAA.HOWTO doc. The +62 is + * there because we potentially have 31 extra bits off to the left, + * since we claim LEFT_EDGE_CLIPPING support. + */ + int scanLineSize = ((pScrn->virtualX + 62)/32) * 4; + if (pVMWARE->xaaColorExpScanLine[0]) { + xfree(pVMWARE->xaaColorExpScanLine[0]); + } + pVMWARE->xaaColorExpScanLine[0] = xalloc(scanLineSize); + return pVMWARE->xaaColorExpScanLine[0] != NULL; + } + + return TRUE; +} + +void +vmwareXAACloseScreen(ScreenPtr pScreen) +{ + VMWAREPtr pVMWARE = VMWAREPTR(xf86Screens[pScreen->myNum]); + + if (pVMWARE->xaaColorExpScanLine[0]) { + xfree(pVMWARE->xaaColorExpScanLine[0]); + pVMWARE->xaaColorExpScanLine[0] = NULL; + } + + DESTROY_XAA_INFO(pVMWARE); + +#ifdef RENDER + if (pVMWARE->heap) { + vmwareHeap_Destroy(pVMWARE->heap); + pVMWARE->heap = NULL; + } +#endif +} + +static void +vmwareXAASync(ScrnInfoPtr pScrn) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + VmwareLog(("Sync\n")); + + vmwareWaitForFB(pVMWARE); + +#ifdef RENDER + if (pVMWARE->heap) { + vmwareHeap_Clear(pVMWARE->heap); + } +#endif +} + +static void +vmwareSetupForSolidFill(ScrnInfoPtr pScrn, + int color, int rop, unsigned int planemask) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + pVMWARE->xaaFGColor = color; + pVMWARE->xaaRop = rop; + + VmwareLog(("Setup Solid Fill (color = %d, rop = %d)\n", color, rop)); +} + +static void +vmwareSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + VmwareLog((" Do Solid Fill (x = %d, y = %d, w = %d, h = %d)\n", x, y, w, h)); + + if (pVMWARE->xaaRop != GXcopy) { + /* + * We'll never get here if SVGA_CAP_RASTER_OP isn't set, since + * we tell XAA we are GXCOPY_ONLY. + */ + vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_RECT_ROP_FILL); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->xaaFGColor); + vmwareWriteWordToFIFO(pVMWARE, x); + vmwareWriteWordToFIFO(pVMWARE, y); + vmwareWriteWordToFIFO(pVMWARE, w); + vmwareWriteWordToFIFO(pVMWARE, h); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->xaaRop); + } else { + vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_RECT_FILL); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->xaaFGColor); + vmwareWriteWordToFIFO(pVMWARE, x); + vmwareWriteWordToFIFO(pVMWARE, y); + vmwareWriteWordToFIFO(pVMWARE, w); + vmwareWriteWordToFIFO(pVMWARE, h); + } +} + +static void +vmwareSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, + int trans_color) +{ + /* + * We can safely ignore xdir and ydir since our "hardware" is smart + * enough to figure out the direction from the srcx/y, dstx/y, w and h. + */ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + pVMWARE->xaaRop = rop; + + VmwareLog(("Setup Screen2Screen copy (rop = %d)\n", rop)); +} + +static void +vmwareSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int x1, int y1, + int x2, int y2, + int width, int height) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + VmwareLog((" Do Screen2Screen copy (x1 = %d, y1 = %d, x2 = %d, y2 = %d," + " w = %d, h = %d)\n", x1, y1, x2, y2, width, height)); + + if (pVMWARE->xaaRop != GXcopy) { + /* + * We'll never get here if SVGA_CAP_RASTER_OP isn't set, since + * we tell XAA we are GXCOPY_ONLY. + */ + vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_RECT_ROP_COPY); + vmwareWriteWordToFIFO(pVMWARE, x1); + vmwareWriteWordToFIFO(pVMWARE, y1); + vmwareWriteWordToFIFO(pVMWARE, x2); + vmwareWriteWordToFIFO(pVMWARE, y2); + vmwareWriteWordToFIFO(pVMWARE, width); + vmwareWriteWordToFIFO(pVMWARE, height); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->xaaRop); + } else { + vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_RECT_COPY); + vmwareWriteWordToFIFO(pVMWARE, x1); + vmwareWriteWordToFIFO(pVMWARE, y1); + vmwareWriteWordToFIFO(pVMWARE, x2); + vmwareWriteWordToFIFO(pVMWARE, y2); + vmwareWriteWordToFIFO(pVMWARE, width); + vmwareWriteWordToFIFO(pVMWARE, height); + } +} + +static void +vmwareSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + pVMWARE->xaaFGColor = fg; + pVMWARE->xaaBGColor = bg; + VmwareLog(("Setup color expand (fg = %d, bg = %d, rop = %d)\n", + fg, bg, rop)); +} + +static void +vmwareSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int x, int y, + int w, int h, + int skipleft ) +{ + /* + * XXX TODO: if xaaColorExpSize will fit entirely into the FIFO, + * temporarily switch to direct mode, and have XAA write bits + * directly into the fifo. See ATI driver for an example. + */ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + pVMWARE->xaaColorExpSize = SVGA_GLYPH_SCANLINE_SIZE_DWORDS(w); + + VmwareLog((" Do color expand (x = %d, y = %d, w = %d, h = %d," + " skipleft = %d, sizedw = %d)\n", + x, y, w, h, skipleft, pVMWARE->xaaColorExpSize)); + + vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_DRAW_GLYPH_CLIPPED); + vmwareWriteWordToFIFO(pVMWARE, x); + vmwareWriteWordToFIFO(pVMWARE, y); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->xaaColorExpSize * 32U); + vmwareWriteWordToFIFO(pVMWARE, h); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->xaaFGColor); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->xaaBGColor); + vmwareWriteWordToFIFO(pVMWARE, x + skipleft); + vmwareWriteWordToFIFO(pVMWARE, y); + vmwareWriteWordToFIFO(pVMWARE, w - skipleft); + vmwareWriteWordToFIFO(pVMWARE, h); +} + +static void +vmwareSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + CARD32* scanLine = (CARD32*)pVMWARE->xaaColorExpScanLine[0]; + unsigned int dwords = pVMWARE->xaaColorExpSize; + + while (dwords--) { + vmwareWriteWordToFIFO(pVMWARE, *scanLine++); + } +} + +#ifdef RENDER + +static void +RGBPlusAlphaChannelToPremultipliedRGBA( + CARD8 red, CARD8 blue, CARD8 green, + CARD8 *alphaPtr, /* in bytes */ + int alphaPitch, + CARD32 *dstPtr, + int dstPitch, /* in dwords */ + int width, int height) +{ + int x; + + while (height--) { + for (x = 0; x < width; x++) { + CARD8 alpha = alphaPtr[x]; + dstPtr[x] = (alpha << 24) | + ((red * alpha / 255) << 16) | + ((green * alpha / 255) << 8) | + (blue * alpha / 255); + } + dstPtr += dstPitch; + alphaPtr += alphaPitch; + } +} + +Bool +vmwareSetupForCPUToScreenAlphaTexture(ScrnInfoPtr pScrn, int op, + CARD16 red, CARD16 green, + CARD16 blue, CARD16 alpha, + int alphaType, CARD8 *alphaPtr, + int alphaPitch, + int width, int height, + int flags) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + SVGASurface* surf; + + VmwareLog(("Setup alpha texture (op = %d, r = %d, g = %d, b = %d," + " a = %d, alphaType = %d, alphaPitch = %d, w = %d, h = %d," + " flags = %d)\n", op, red, green, blue, alpha, alphaType, + alphaPitch, width, height, flags)); + + if (op > PictOpSaturate) { + return FALSE; + } + + surf = vmwareHeap_AllocSurface(pVMWARE->heap, width, height, width * 4, 32); + + if (!surf) { + return FALSE; + } + + RGBPlusAlphaChannelToPremultipliedRGBA( + red >> 8, green >> 8, blue >> 8, + alphaPtr, alphaPitch, + (CARD32*)(pVMWARE->FbBase + surf->dataOffset), + width, width, height); + + pVMWARE->curPict = surf; + pVMWARE->op = op; + + return TRUE; +} + +Bool +vmwareSetupForCPUToScreenTexture(ScrnInfoPtr pScrn, int op, + int texType, CARD8 *texPtr, + int texPitch, + int width, int height, + int flags) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + SVGASurface* surf; + + VmwareLog(("Setup texture (op = %d, texType = %d, texPitch = %d," + " w = %d, h = %d, flags = %d)\n", op, texType, texPitch, + width, height, flags)); + + if (op > PictOpSaturate) { + return FALSE; + } + + surf = vmwareHeap_AllocSurface(pVMWARE->heap, width, height, texPitch, 32); + + if (!surf) { + return FALSE; + } + + memcpy(pVMWARE->FbBase + surf->dataOffset, texPtr, texPitch * height); + + pVMWARE->curPict = surf; + pVMWARE->op = op; + + return TRUE; +} + +void +vmwareSubsequentCPUToScreenTexture(ScrnInfoPtr pScrn, + int dstx, int dsty, + int srcx, int srcy, + int width, int height) +{ + VMWAREPtr pVMWARE = VMWAREPTR(pScrn); + + VmwareLog((" Do texture (dstx = %d, dsty = %d, srcx = %d, srcy = %d" + " w = %d, h = %d)\n", dstx, dsty, srcx, srcy, width, height)); + + pVMWARE->curPict->numQueued++; + pVMWARE->frontBuffer->numQueued++; + + vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_SURFACE_ALPHA_BLEND); + vmwareWriteWordToFIFO(pVMWARE, (CARD8*)pVMWARE->curPict - pVMWARE->FbBase); + vmwareWriteWordToFIFO(pVMWARE, (CARD8*)pVMWARE->frontBuffer - pVMWARE->FbBase); + vmwareWriteWordToFIFO(pVMWARE, srcx); + vmwareWriteWordToFIFO(pVMWARE, srcy); + vmwareWriteWordToFIFO(pVMWARE, dstx); + vmwareWriteWordToFIFO(pVMWARE, dsty); + vmwareWriteWordToFIFO(pVMWARE, width); + vmwareWriteWordToFIFO(pVMWARE, height); + vmwareWriteWordToFIFO(pVMWARE, pVMWARE->op); + vmwareWriteWordToFIFO(pVMWARE, 0); /* flags */ + vmwareWriteWordToFIFO(pVMWARE, 0); /* param1 */ + vmwareWriteWordToFIFO(pVMWARE, 0); /* param2 */ +} +#endif |