#ifdef VMX86_DEVEL
char rcsId_vmwarexaa[] =
"Id: $";
#endif
#include "vmware.h"
#define OFFSCREEN_SCRATCH_SIZE 1*1024*1024
#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);
static void vmwareXAAEnableDisableFBAccess(int index, Bool enable);
CARD32 vmwareAlphaTextureFormats[2] = {PICT_a8, 0};
CARD32 vmwareTextureFormats[2] = {PICT_a8r8g8b8, 0};
#endif
#define SCRATCH_SIZE_BYTES(pvmware) \
(((OFFSCREEN_SCRATCH_SIZE + (pvmware)->fbPitch - 1) / \
(pvmware)->fbPitch) * (pvmware)->fbPitch)
static void vmwareXAACreateHeap(ScreenPtr pScreen, ScrnInfoPtr pScrn,
VMWAREPtr pVMWARE) {
int scratchSizeBytes = SCRATCH_SIZE_BYTES(pVMWARE);
CARD8* osPtr = pVMWARE->FbBase + 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);
}
#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);
}
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 = SCRATCH_SIZE_BYTES(pVMWARE);
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) {
box.y2 -= scratchSizeBytes / pVMWARE->fbPitch;
VmwareLog(("Allocated %d bytes at offset %d for alpha scratch\n",
scratchSizeBytes,
pVMWARE->videoRam - scratchSizeBytes));
vmwareXAACreateHeap(pScreen, pScrn, pVMWARE);
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;
}
#ifdef RENDER
if (pVMWARE->heap) {
pVMWARE->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
pScrn->EnableDisableFBAccess = vmwareXAAEnableDisableFBAccess;
}
#endif
return TRUE;
}
Bool
vmwareXAAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
if (pVMWARE->vmwareCapability & SVGA_CAP_GLYPH) {
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) {
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
pScrn->EnableDisableFBAccess = pVMWARE->EnableDisableFBAccess;
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) {
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)
{
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) {
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 )
{
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,
int alphaPitch,
CARD32 *dstPtr,
int dstPitch,
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);
vmwareWriteWordToFIFO(pVMWARE, 0);
vmwareWriteWordToFIFO(pVMWARE, 0);
}
void
vmwareXAAEnableDisableFBAccess(int index, Bool enable)
{
ScrnInfoPtr pScrn = xf86Screens[index];
ScreenPtr pScreen = pScrn->pScreen;
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
if (enable && pVMWARE->heap) {
vmwareHeap_Destroy(pVMWARE->heap);
vmwareXAACreateHeap(pScreen, pScrn, pVMWARE);
}
(*pVMWARE->EnableDisableFBAccess)(index, enable);
}
#endif