From 84166d4b457244bcc2f5ace63702d594d602d0c2 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 16 Jun 2011 15:55:07 +0200 Subject: vmwgfx, saa: Initial import This imports the vmwgfx driver, based on the Gallium3D Xorg state tracker, as well as the saa library. A "Shadow Acceleration Architecture", which is optimized for the case where transfers between system (shadow) and hw memory is very costly. Signed-off-by: Thomas Hellstrom --- Makefile.am | 2 +- configure.ac | 2 + saa/Makefile.am | 13 + saa/saa.c | 748 +++++++++++++++++++ saa/saa.h | 192 +++++ saa/saa_accel.c | 141 ++++ saa/saa_pixmap.c | 222 ++++++ saa/saa_priv.h | 263 +++++++ saa/saa_render.c | 313 ++++++++ saa/saa_unaccel.c | 896 ++++++++++++++++++++++ src/svga_reg.h | 1243 +++++++++++++++++++++---------- vmwgfx/Makefile.am | 24 + vmwgfx/svga3d_reg.h | 1801 +++++++++++++++++++++++++++++++++++++++++++++ vmwgfx/vmwgfx_bootstrap.c | 199 +++++ vmwgfx/vmwgfx_crtc.c | 456 ++++++++++++ vmwgfx/vmwgfx_ctrl.c | 525 +++++++++++++ vmwgfx/vmwgfx_ctrl.h | 48 ++ vmwgfx/vmwgfx_dri2.c | 373 ++++++++++ vmwgfx/vmwgfx_driver.c | 947 ++++++++++++++++++++++++ vmwgfx/vmwgfx_driver.h | 167 +++++ vmwgfx/vmwgfx_drmi.c | 507 +++++++++++++ vmwgfx/vmwgfx_drmi.h | 81 ++ vmwgfx/vmwgfx_output.c | 304 ++++++++ vmwgfx/vmwgfx_overlay.c | 893 ++++++++++++++++++++++ vmwgfx/vmwgfx_saa.c | 1208 ++++++++++++++++++++++++++++++ vmwgfx/vmwgfx_saa.h | 94 +++ vmwgfx/vmwgfx_tex_video.c | 723 ++++++++++++++++++ 27 files changed, 12009 insertions(+), 376 deletions(-) create mode 100644 saa/Makefile.am create mode 100644 saa/saa.c create mode 100644 saa/saa.h create mode 100644 saa/saa_accel.c create mode 100644 saa/saa_pixmap.c create mode 100644 saa/saa_priv.h create mode 100644 saa/saa_render.c create mode 100644 saa/saa_unaccel.c create mode 100644 vmwgfx/Makefile.am create mode 100644 vmwgfx/svga3d_reg.h create mode 100644 vmwgfx/vmwgfx_bootstrap.c create mode 100644 vmwgfx/vmwgfx_crtc.c create mode 100644 vmwgfx/vmwgfx_ctrl.c create mode 100644 vmwgfx/vmwgfx_ctrl.h create mode 100644 vmwgfx/vmwgfx_dri2.c create mode 100644 vmwgfx/vmwgfx_driver.c create mode 100644 vmwgfx/vmwgfx_driver.h create mode 100644 vmwgfx/vmwgfx_drmi.c create mode 100644 vmwgfx/vmwgfx_drmi.h create mode 100644 vmwgfx/vmwgfx_output.c create mode 100644 vmwgfx/vmwgfx_overlay.c create mode 100644 vmwgfx/vmwgfx_saa.c create mode 100644 vmwgfx/vmwgfx_saa.h create mode 100644 vmwgfx/vmwgfx_tex_video.c diff --git a/Makefile.am b/Makefile.am index 093e9f5..fff57f6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -SUBDIRS = src man vmwarectrl +SUBDIRS = src man vmwarectrl saa vmwgfx MAINTAINERCLEANFILES = ChangeLog INSTALL .PHONY: ChangeLog INSTALL diff --git a/configure.ac b/configure.ac index cd2854e..bbb530a 100644 --- a/configure.ac +++ b/configure.ac @@ -121,5 +121,7 @@ AC_CONFIG_FILES([ src/Makefile vmwarectrl/Makefile man/Makefile + saa/Makefile + vmwgfx/Makefile ]) AC_OUTPUT diff --git a/saa/Makefile.am b/saa/Makefile.am new file mode 100644 index 0000000..4f56d3f --- /dev/null +++ b/saa/Makefile.am @@ -0,0 +1,13 @@ +libsaa_la_LTLIBRARIES = libsaa.la +libsaa_ladir = @libdir@ + +libsaa_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) +libsaa_la_SOURCES = \ + saa.c \ + saa_pixmap.c \ + saa_unaccel.c \ + saa_priv.h \ + saa_render.c \ + saa_accel.c \ + saa.h + diff --git a/saa/saa.c b/saa/saa.c new file mode 100644 index 0000000..e9567e3 --- /dev/null +++ b/saa/saa.c @@ -0,0 +1,748 @@ +/* + * Copyright © 2001 Keith Packard + * + * Partly based on code that is Copyright © The XFree86 Project Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** @file + * This file covers the initialization and teardown of SAA, and has various + * functions not responsible for performing rendering, pixmap migration, or + * memory management. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "saa_priv.h" +#include +#include "dixfontstr.h" +#include "regionstr.h" +#include "saa.h" + +#ifdef SAA_DEVPRIVATEKEYREC +DevPrivateKeyRec saa_screen_index; +DevPrivateKeyRec saa_pixmap_index; +DevPrivateKeyRec saa_gc_index; +#else +int saa_screen_index = -1; +int saa_pixmap_index = -1; +int saa_gc_index = -1; +#endif + +/** + * saa_get_drawable_pixmap() returns a backing pixmap for a given drawable. + * + * @param pDrawable the drawable being requested. + * + * This function returns the backing pixmap for a drawable, whether it is a + * redirected window, unredirected window, or already a pixmap. Note that + * coordinate translation is needed when drawing to the backing pixmap of a + * redirected window, and the translation coordinates are provided by calling + * saa_get_drawable_pixmap() on the drawable. + */ +PixmapPtr +saa_get_drawable_pixmap(DrawablePtr pDrawable) +{ + if (pDrawable->type == DRAWABLE_WINDOW) + return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable); + else + return (PixmapPtr) pDrawable; +} + +/** + * Sets the offsets to add to coordinates to make them address the same bits in + * the backing drawable. These coordinates are nonzero only for redirected + * windows. + */ +void +saa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap, + int *xp, int *yp) +{ +#ifdef COMPOSITE + if (pDrawable->type == DRAWABLE_WINDOW) { + *xp = -pPixmap->screen_x; + *yp = -pPixmap->screen_y; + return; + } +#endif + + *xp = 0; + *yp = 0; +} + +/** + * Returns the pixmap which backs a drawable, and the offsets to add to + * coordinates to make them address the same bits in the backing drawable. + */ +PixmapPtr +saa_get_pixmap(DrawablePtr drawable, int *xp, int *yp) +{ + PixmapPtr pixmap = saa_get_drawable_pixmap(drawable); + + saa_get_drawable_deltas(drawable, pixmap, xp, yp); + + return pixmap; +} + +static Bool +saa_download_from_hw(PixmapPtr pix, RegionPtr readback) +{ + struct saa_screen_priv *sscreen = saa_screen(pix->drawable.pScreen); + struct saa_driver *driver = sscreen->driver; + struct saa_pixmap *spix = saa_pixmap(pix); + void *addr; + Bool ret; + + if (spix->mapped_access) + driver->release_from_cpu(driver, pix, spix->mapped_access); + + ret = driver->download_from_hw(driver, pix, readback); + + if (spix->mapped_access) { + addr = driver->sync_for_cpu(driver, pix, spix->mapped_access); + if (addr != NULL) + spix->addr = addr; + } + + return ret; +} + +Bool +saa_prepare_access_pixmap(PixmapPtr pix, saa_access_t access, + RegionPtr read_reg) +{ + ScreenPtr pScreen = pix->drawable.pScreen; + struct saa_screen_priv *sscreen = saa_screen(pScreen); + struct saa_driver *driver = sscreen->driver; + struct saa_pixmap *spix = saa_pixmap(pix); + saa_access_t map_access = 0; + Bool ret = TRUE; + + if (read_reg && REGION_NOTEMPTY(pScreen, read_reg)) + ret = saa_download_from_hw(pix, read_reg); + + if (!ret) { + LogMessage(X_ERROR, "Prepare access pixmap failed.\n"); + return ret; + } + + if ((access & SAA_ACCESS_R) != 0 && spix->read_access++ == 0) + map_access = SAA_ACCESS_R; + if ((access & SAA_ACCESS_W) != 0 && spix->write_access++ == 0) + map_access |= SAA_ACCESS_W; + + if (map_access) { + if (spix->auth_loc != saa_loc_override) { + (void)driver->sync_for_cpu(driver, pix, map_access); + spix->addr = driver->map(driver, pix, map_access); + } else + spix->addr = spix->override; + spix->mapped_access |= map_access; + } + + pix->devPrivate.ptr = spix->addr; + return TRUE; +} + +void +saa_finish_access_pixmap(PixmapPtr pix, saa_access_t access) +{ + struct saa_screen_priv *sscreen = saa_screen(pix->drawable.pScreen); + struct saa_driver *driver = sscreen->driver; + struct saa_pixmap *spix = saa_pixmap(pix); + saa_access_t unmap_access = 0; + + if ((access & SAA_ACCESS_R) != 0 && --spix->read_access == 0) + unmap_access = SAA_ACCESS_R; + if ((access & SAA_ACCESS_W) != 0 && --spix->write_access == 0) + unmap_access |= SAA_ACCESS_W; + + if (spix->read_access < 0) + LogMessage(X_ERROR, "Incorrect read access.\n"); + if (spix->write_access < 0) + LogMessage(X_ERROR, "Incorrect write access.\n"); + + if (unmap_access) { + if (spix->auth_loc != saa_loc_override) { + driver->unmap(driver, pix, unmap_access); + driver->release_from_cpu(driver, pix, unmap_access); + } + spix->mapped_access &= ~unmap_access; + } + if (!spix->mapped_access) { + spix->addr = NULL; + pix->devPrivate.ptr = SAA_INVALID_ADDRESS; + } +} + +/* + * Callback that is called after a rendering operation. We try to + * determine whether it's a shadow damage or a hw damage and call the + * driver callback. + */ + +static void +saa_report_damage(DamagePtr damage, RegionPtr reg, void *closure) +{ + PixmapPtr pixmap = (PixmapPtr) closure; + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + struct saa_driver *driver = saa_screen(pixmap->drawable.pScreen)->driver; + + if (spix->read_access || spix->write_access) + LogMessage(X_ERROR, "Damage report inside prepare access.\n"); + + driver->operation_complete(driver, pixmap); + DamageEmpty(damage); +} + +Bool +saa_add_damage(PixmapPtr pixmap) +{ + ScreenPtr pScreen = pixmap->drawable.pScreen; + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + + if (spix->damage) + return TRUE; + + spix->damage = DamageCreate(saa_report_damage, NULL, + DamageReportRawRegion, TRUE, pScreen, pixmap); + if (!spix->damage) + return FALSE; + + DamageRegister(&pixmap->drawable, spix->damage); + DamageSetReportAfterOp(spix->damage, TRUE); + + return TRUE; +} + +static inline RegionPtr +saa_pix_damage_region(struct saa_pixmap *spix) +{ + return (spix->damage ? DamageRegion(spix->damage) : NULL); +} + +Bool +saa_pad_read(DrawablePtr draw) +{ + ScreenPtr pScreen = draw->pScreen; + PixmapPtr pix; + int xp; + int yp; + BoxRec box; + RegionRec entire; + Bool ret; + + (void)pScreen; + pix = saa_get_pixmap(draw, &xp, &yp); + + box.x1 = draw->x + xp; + box.y1 = draw->y + yp; + box.x2 = box.x1 + draw->width; + box.y2 = box.y1 + draw->height; + + REGION_INIT(pScreen, &entire, &box, 1); + ret = saa_prepare_access_pixmap(pix, SAA_ACCESS_R, &entire); + REGION_UNINIT(pScreen, &entire); + return ret; +} + +Bool +saa_pad_read_box(DrawablePtr draw, int x, int y, int w, int h) +{ + ScreenPtr pScreen = draw->pScreen; + PixmapPtr pix; + int xp; + int yp; + BoxRec box; + RegionRec entire; + Bool ret; + + (void)pScreen; + pix = saa_get_pixmap(draw, &xp, &yp); + + box.x1 = x + xp; + box.y1 = y + yp; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + + REGION_INIT(pScreen, &entire, &box, 1); + ret = saa_prepare_access_pixmap(pix, SAA_ACCESS_R, &entire); + REGION_UNINIT(pScreen, &entire); + return ret; +} + +/** + * Prepares a drawable destination for access, and maps it read-write. + * If check_read is TRUE, pGC should point to a valid GC. The drawable + * may then be mapped write-only if the pending operation admits. + */ + +Bool +saa_pad_write(DrawablePtr draw, GCPtr pGC, Bool check_read, + saa_access_t * access) +{ + int xp; + int yp; + PixmapPtr pixmap = saa_get_pixmap(draw, &xp, &yp); + struct saa_pixmap *spix = saa_pixmap(pixmap); + + *access = SAA_ACCESS_W; + + /* + * If the to-be-damaged area doesn't depend at all on previous + * rendered contents, we don't need to do any readback. + */ + + if (check_read && !saa_gc_reads_destination(draw, pGC)) + return saa_prepare_access_pixmap(pixmap, *access, NULL); + + *access |= SAA_ACCESS_R; + + /* + * Read back the area to be damaged. + */ + + return saa_prepare_access_pixmap(pixmap, *access, + saa_pix_damage_pending(spix)); +} + +void +saa_fad_read(DrawablePtr draw) +{ + saa_finish_access_pixmap(saa_get_drawable_pixmap(draw), SAA_ACCESS_R); +} + +void +saa_fad_write(DrawablePtr draw, saa_access_t access) +{ + PixmapPtr pix = saa_get_drawable_pixmap(draw); + struct saa_pixmap *spix = saa_pixmap(pix); + + saa_finish_access_pixmap(pix, access); + if (spix->damage) + saa_pixmap_dirty(pix, FALSE, saa_pix_damage_pending(spix)); +} + +Bool +saa_gc_reads_destination(DrawablePtr pDrawable, GCPtr pGC) +{ + return ((pGC->alu != GXcopy && pGC->alu != GXclear && pGC->alu != GXset && + pGC->alu != GXcopyInverted) || pGC->fillStyle == FillStippled || + pGC->clientClipType != CT_NONE || + !SAA_PM_IS_SOLID(pDrawable, pGC->planemask)); +} + +Bool +saa_op_reads_destination(CARD8 op) +{ + /* FALSE (does not read destination) is the list of ops in the protocol + * document with "0" in the "Fb" column and no "Ab" in the "Fa" column. + * That's just Clear and Src. ReduceCompositeOp() will already have + * converted con/disjoint clear/src to Clear or Src. + */ + switch (op) { + case PictOpClear: + case PictOpSrc: + return FALSE; + default: + return TRUE; + } +} + +static void +saa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) +{ + /* fbValidateGC will do direct access to pixmaps if the tiling has changed. + * Do a few smart things so fbValidateGC can do it's work. + */ + + ScreenPtr pScreen = pDrawable->pScreen; + struct saa_screen_priv *sscreen = saa_screen(pScreen); + struct saa_gc_priv *sgc = saa_gc(pGC); + PixmapPtr pTile = NULL; + Bool finish_current_tile = FALSE; + + /* Either of these conditions is enough to trigger access to a tile pixmap. */ + /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */ + if (pGC->fillStyle == FillTiled + || ((changes & GCTile) && !pGC->tileIsPixel)) { + pTile = pGC->tile.pixmap; + + /* Sometimes tile pixmaps are swapped, you need access to: + * - The current tile if it depth matches. + * - Or the rotated tile if that one matches depth and !(changes & GCTile). + * - Or the current tile pixmap and a newly created one. + */ + if (pTile && pTile->drawable.depth != pDrawable->depth + && !(changes & GCTile)) { + PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC); + + if (pRotatedTile + && pRotatedTile->drawable.depth == pDrawable->depth) + pTile = pRotatedTile; + else + finish_current_tile = TRUE; /* CreatePixmap will be called. */ + } + } + + if (pGC->stipple && !saa_pad_read(&pGC->stipple->drawable)) { + LogMessage(X_ERROR, "Failed stipple prepareaccess.\n"); + return; + } + + if (pTile && !saa_pad_read(&pTile->drawable)) { + LogMessage(X_ERROR, "Failed stipple prepareaccess.\n"); + goto out_no_tile; + } + + /* Calls to Create/DestroyPixmap have to be identified as special, so + * up sscreen->fallback_count. + */ + + sscreen->fallback_count++; + saa_swap(sgc, pGC, funcs); + (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); + saa_swap(sgc, pGC, funcs); + + if (finish_current_tile && pGC->tile.pixmap) + saa_fad_write(&pGC->tile.pixmap->drawable, SAA_ACCESS_W); + sscreen->fallback_count--; + + if (pTile) + saa_fad_read(&pTile->drawable); + out_no_tile: + if (pGC->stipple) + saa_fad_read(&pGC->stipple->drawable); +} + +static void +saa_destroy_gc(GCPtr pGC) +{ + struct saa_gc_priv *sgc = saa_gc(pGC); + + saa_swap(sgc, pGC, funcs); + (*pGC->funcs->DestroyGC) (pGC); + saa_swap(sgc, pGC, funcs); +} + +static void +saa_change_gc(GCPtr pGC, unsigned long mask) +{ + struct saa_gc_priv *sgc = saa_gc(pGC); + + saa_swap(sgc, pGC, funcs); + (*pGC->funcs->ChangeGC) (pGC, mask); + saa_swap(sgc, pGC, funcs); +} + +static void +saa_copy_gc(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) +{ + struct saa_gc_priv *sgc = saa_gc(pGCDst); + + saa_swap(sgc, pGCDst, funcs); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + saa_swap(sgc, pGCDst, funcs); +} + +static void +saa_change_clip(GCPtr pGC, int type, pointer pvalue, int nrects) +{ + struct saa_gc_priv *sgc = saa_gc(pGC); + + saa_swap(sgc, pGC, funcs); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + saa_swap(sgc, pGC, funcs); +} + +static void +saa_copy_clip(GCPtr pGCDst, GCPtr pGCSrc) +{ + struct saa_gc_priv *sgc = saa_gc(pGCDst); + + saa_swap(sgc, pGCDst, funcs); + (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc); + saa_swap(sgc, pGCDst, funcs); +} + +static void +saa_destroy_clip(GCPtr pGC) +{ + struct saa_gc_priv *sgc = saa_gc(pGC); + + saa_swap(sgc, pGC, funcs); + (*pGC->funcs->DestroyClip) (pGC); + saa_swap(sgc, pGC, funcs); +} + +static GCFuncs saa_gc_funcs = { + saa_validate_gc, + saa_change_gc, + saa_copy_gc, + saa_destroy_gc, + saa_change_clip, + saa_destroy_clip, + saa_copy_clip +}; + +/** + * saa_create_gc makes a new GC and hooks up its funcs handler, so that + * saa_validate_gc() will get called. + */ +int +saa_create_gc(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + struct saa_screen_priv *sscreen = saa_screen(pScreen); + struct saa_gc_priv *sgc = saa_gc(pGC); + Bool ret; + + saa_swap(sscreen, pScreen, CreateGC); + ret = pScreen->CreateGC(pGC); + if (ret) { + saa_wrap(sgc, pGC, funcs, &saa_gc_funcs); + saa_wrap(sgc, pGC, ops, &saa_gc_ops); + } + saa_swap(sscreen, pScreen, CreateGC); + + return ret; +} + +static Bool +saa_prepare_access_window(WindowPtr pWin) +{ + if (pWin->backgroundState == BackgroundPixmap) { + if (!saa_pad_read(&pWin->background.pixmap->drawable)) + return FALSE; + } + + if (pWin->borderIsPixel == FALSE) { + if (!saa_pad_read(&pWin->border.pixmap->drawable)) { + if (pWin->backgroundState == BackgroundPixmap) + saa_fad_read(&pWin->background.pixmap->drawable); + return FALSE; + } + } + return TRUE; +} + +static void +saa_finish_access_window(WindowPtr pWin) +{ + if (pWin->backgroundState == BackgroundPixmap) + saa_fad_read(&pWin->background.pixmap->drawable); + + if (pWin->borderIsPixel == FALSE) + saa_fad_read(&pWin->border.pixmap->drawable); +} + +static Bool +saa_change_window_attributes(WindowPtr pWin, unsigned long mask) +{ + Bool ret; + + if (!saa_prepare_access_window(pWin)) + return FALSE; + ret = fbChangeWindowAttributes(pWin, mask); + saa_finish_access_window(pWin); + return ret; +} + +RegionPtr +saa_bitmap_to_region(PixmapPtr pPix) +{ + RegionPtr ret; + + if (!saa_pad_read(&pPix->drawable)) + return NULL; + ret = fbPixmapToRegion(pPix); + saa_fad_read(&pPix->drawable); + return ret; +} + +void +saa_set_fallback_debug(ScreenPtr screen, Bool enable) +{ + struct saa_screen_priv *sscreen = saa_screen(screen); + + sscreen->fallback_debug = enable; +} + +/** + * saa_close_screen() unwraps its wrapped screen functions and tears down SAA's + * screen private, before calling down to the next CloseScreen. + */ +Bool +saa_close_screen(int i, ScreenPtr pScreen) +{ + struct saa_screen_priv *sscreen = saa_screen(pScreen); + struct saa_driver *driver = sscreen->driver; + + if (pScreen->devPrivate) { + /* Destroy the pixmap created by miScreenInit() *before* + * chaining up as we finalize ourselves here and so this + * is the last chance we have of releasing our resources + * associated with the Pixmap. So do it first. + */ + (void)(*pScreen->DestroyPixmap) (pScreen->devPrivate); + pScreen->devPrivate = NULL; + } + + saa_unwrap(sscreen, pScreen, CloseScreen); + saa_unwrap(sscreen, pScreen, CreateGC); + saa_unwrap(sscreen, pScreen, ChangeWindowAttributes); + saa_unwrap(sscreen, pScreen, CreatePixmap); + saa_unwrap(sscreen, pScreen, DestroyPixmap); + saa_unwrap(sscreen, pScreen, ModifyPixmapHeader); + saa_unwrap(sscreen, pScreen, BitmapToRegion); +#ifdef RENDER + saa_render_takedown(pScreen); +#endif + saa_unaccel_takedown(pScreen); + driver->takedown(driver); + + free(sscreen); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +struct saa_driver * +saa_get_driver(ScreenPtr pScreen) +{ + return saa_screen(pScreen)->driver; +} + +/** + * @param pScreen screen being initialized + * @param pScreenInfo SAA driver record + * + * saa_driver_init sets up SAA given a driver record filled in by the driver. + * pScreenInfo should have been allocated by saa_driver_alloc(). See the + * comments in _SaaDriver for what must be filled in and what is optional. + * + * @return TRUE if SAA was successfully initialized. + */ +Bool +saa_driver_init(ScreenPtr screen, struct saa_driver * saa_driver) +{ + struct saa_screen_priv *sscreen; + + if (!saa_driver) + return FALSE; + + if (saa_driver->saa_major != SAA_VERSION_MAJOR || + saa_driver->saa_minor > SAA_VERSION_MINOR) { + LogMessage(X_ERROR, + "SAA(%d): driver's SAA version requirements " + "(%d.%d) are incompatible with SAA version (%d.%d)\n", + screen->myNum, saa_driver->saa_major, + saa_driver->saa_minor, SAA_VERSION_MAJOR, SAA_VERSION_MINOR); + return FALSE; + } +#if 0 + if (!saa_driver->prepare_solid) { + LogMessage(X_ERROR, + "SAA(%d): saa_driver_t::prepare_solid must be " + "non-NULL\n", screen->myNum); + return FALSE; + } + + if (!saa_driver->prepare_copy) { + LogMessage(X_ERROR, + "SAA(%d): saa_driver_t::prepare_copy must be " + "non-NULL\n", screen->myNum); + return FALSE; + } +#endif +#ifdef SAA_DEVPRIVATEKEYREC + if (!dixRegisterPrivateKey(&saa_screen_index, PRIVATE_SCREEN, 0)) { + LogMessage(X_ERROR, "Failed to register SAA screen private.\n"); + return FALSE; + } + if (!dixRegisterPrivateKey(&saa_pixmap_index, PRIVATE_PIXMAP, + saa_driver->pixmap_size)) { + LogMessage(X_ERROR, "Failed to register SAA pixmap private.\n"); + return FALSE; + } + if (!dixRegisterPrivateKey(&saa_gc_index, PRIVATE_GC, + sizeof(struct saa_gc_priv))) { + LogMessage(X_ERROR, "Failed to register SAA gc private.\n"); + return FALSE; + } +#else + if (!dixRequestPrivate(&saa_screen_index, 0)) { + LogMessage(X_ERROR, "Failed to register SAA screen private.\n"); + return FALSE; + } + if (!dixRequestPrivate(&saa_pixmap_index, saa_driver->pixmap_size)) { + LogMessage(X_ERROR, "Failed to register SAA pixmap private.\n"); + return FALSE; + } + if (!dixRequestPrivate(&saa_gc_index, sizeof(struct saa_gc_priv))) { + LogMessage(X_ERROR, "Failed to register SAA gc private.\n"); + return FALSE; + } +#endif + + sscreen = calloc(1, sizeof(*sscreen)); + + if (!sscreen) { + LogMessage(X_WARNING, + "SAA(%d): Failed to allocate screen private\n", + screen->myNum); + return FALSE; + } + + sscreen->driver = saa_driver; + dixSetPrivate(&screen->devPrivates, &saa_screen_index, sscreen); + + /* + * Replace various fb screen functions + */ + + saa_wrap(sscreen, screen, CloseScreen, saa_close_screen); + saa_wrap(sscreen, screen, CreateGC, saa_create_gc); + saa_wrap(sscreen, screen, ChangeWindowAttributes, + saa_change_window_attributes); + saa_wrap(sscreen, screen, CreatePixmap, saa_create_pixmap); + saa_wrap(sscreen, screen, DestroyPixmap, saa_destroy_pixmap); + saa_wrap(sscreen, screen, ModifyPixmapHeader, saa_modify_pixmap_header); + + saa_wrap(sscreen, screen, BitmapToRegion, saa_bitmap_to_region); + saa_unaccel_setup(screen); +#ifdef RENDER + saa_render_setup(screen); +#endif + + return TRUE; +} + +Bool +saa_resources_init(ScreenPtr screen) +{ +/* if (!saa_glyphs_init(screen)) + return FALSE; +*/ + return TRUE; +} diff --git a/saa/saa.h b/saa/saa.h new file mode 100644 index 0000000..fe9617f --- /dev/null +++ b/saa/saa.h @@ -0,0 +1,192 @@ +/* + * + * Copyright (C) 2000 Keith Packard + * 2004 Eric Anholt + * 2005 Zack Rusin + * + * Copyright 2011 VMWare, Inc. All rights reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of copyright holders not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Copyright holders make no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Author: Based on "exa.h" + * Author: Thomas Hellstrom + */ + +#ifndef _SAA_H_ +#define _SAA_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif +#ifdef HAVE_DIX_CONFIG_H +#include +#else +#include +#endif +#include +#include + +#define SAA_VERSION_MAJOR 0 +#define SAA_VERSION_MINOR 1 + +#define SAA_ACCESS_R (1 << 0) +#define SAA_ACCESS_W (1 << 1) +#define SAA_ACCESS_RW (SAA_ACCESS_R | SAA_ACCESS_W) + +#define SAA_PIXMAP_HINT_CREATE_HW (1 << 25) +#define SAA_PIXMAP_PREFER_SHADOW (1 << 0) + +typedef unsigned int saa_access_t; + +enum saa_pixmap_loc { + saa_loc_driver, + saa_loc_override, +}; + +struct saa_pixmap { + PixmapPtr pixmap; + int read_access; + int write_access; + unsigned int mapped_access; + Bool fallback_created; + RegionRec dirty_shadow; + RegionRec dirty_hw; + RegionRec shadow_damage; + DamagePtr damage; + void *addr; + void *override; + enum saa_pixmap_loc auth_loc; + uint32_t pad[16]; +}; + +struct saa_driver { + unsigned int saa_major; + unsigned int saa_minor; + size_t pixmap_size; + Bool(*damage) (struct saa_driver * driver, PixmapPtr pixmap, + Bool hw, RegionPtr damage); + void (*operation_complete) (struct saa_driver * driver, PixmapPtr pixmap); + Bool(*download_from_hw) (struct saa_driver * driver, PixmapPtr pixmap, + RegionPtr readback); + void (*release_from_cpu) (struct saa_driver * driver, PixmapPtr pixmap, + saa_access_t access); + void *(*sync_for_cpu) (struct saa_driver * driver, PixmapPtr pixmap, + saa_access_t access); + void *(*map) (struct saa_driver * driver, PixmapPtr pixmap, + saa_access_t access); + void (*unmap) (struct saa_driver * driver, PixmapPtr pixmap, + saa_access_t access); + Bool(*create_pixmap) (struct saa_driver * driver, struct saa_pixmap * spix, + int w, int h, int depth, unsigned int usage_hint, + int bpp, int *new_pitch); + void (*destroy_pixmap) (struct saa_driver * driver, PixmapPtr pixmap); + Bool(*modify_pixmap_header) (PixmapPtr pixmap, int w, int h, int depth, + int bpp, int devkind, void *pPixData); + + Bool(*copy_prepare) (struct saa_driver * driver, PixmapPtr src_pixmap, + PixmapPtr dst_pixmap, int dx, int dy, int alu, + RegionPtr scr_reg, uint32_t plane_mask); + void (*copy) (struct saa_driver * driver, int src_x, int src_y, int dst_x, + int dst_y, int w, int h); + void (*copy_done) (struct saa_driver * driver); + void (*takedown) (struct saa_driver * driver); + uint32_t pad[16]; +}; + +extern _X_EXPORT PixmapPtr +saa_get_drawable_pixmap(DrawablePtr pDrawable); + +extern _X_EXPORT void +saa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap, + int *xp, int *yp); + +extern _X_EXPORT PixmapPtr +saa_get_pixmap(DrawablePtr drawable, int *xp, int *yp); + +extern _X_EXPORT Bool +saa_prepare_access_pixmap(PixmapPtr pix, saa_access_t access, + RegionPtr read_reg); + +extern _X_EXPORT Bool +saa_pad_read(DrawablePtr draw); + +Bool +saa_pad_read_box(DrawablePtr draw, int x, int y, int w, int h); + +extern _X_EXPORT Bool +saa_pad_write(DrawablePtr draw, GCPtr pGC, Bool check_read, + saa_access_t * access); + +extern _X_EXPORT void +saa_finish_access_pixmap(PixmapPtr pix, saa_access_t access); + +extern _X_EXPORT void +saa_fad_read(DrawablePtr draw); + +extern _X_EXPORT void +saa_fad_write(DrawablePtr draw, saa_access_t access); + +extern _X_EXPORT Bool +saa_resources_init(ScreenPtr screen); + +extern _X_EXPORT void +saa_driver_fini(ScreenPtr pScreen); + +extern _X_EXPORT int +saa_create_gc(GCPtr pGC); + +extern _X_EXPORT RegionPtr +saa_bitmap_to_region(PixmapPtr pPix); + +extern _X_EXPORT Bool +saa_close_screen(int i, ScreenPtr pScreen); + +extern _X_EXPORT Bool +saa_gc_reads_destination(DrawablePtr pDrawable, GCPtr pGC); + +extern _X_EXPORT Bool +saa_op_reads_destination(CARD8 op); + +extern _X_EXPORT void +saa_set_fallback_debug(ScreenPtr screen, Bool enable); + +extern _X_EXPORT +struct saa_pixmap *saa_get_saa_pixmap(PixmapPtr pPixmap); + +extern _X_EXPORT Bool +saa_add_damage(PixmapPtr pixmap); + +extern _X_EXPORT struct saa_driver * +saa_get_driver(ScreenPtr pScreen); + +extern _X_EXPORT Bool +saa_driver_init(ScreenPtr screen, struct saa_driver *saa_driver); + +extern _X_EXPORT void +saa_pixmap_dirty(PixmapPtr pixmap, Bool hw, RegionPtr reg); + +extern _X_EXPORT void +saa_drawable_dirty(DrawablePtr draw, Bool hw, RegionPtr reg); + +#define SAA_PM_IS_SOLID(_pDrawable, _pm) \ + (((_pm) & FbFullMask((_pDrawable)->depth)) == \ + FbFullMask((_pDrawable)->depth)) + +#endif diff --git a/saa/saa_accel.c b/saa/saa_accel.c new file mode 100644 index 0000000..be33170 --- /dev/null +++ b/saa/saa_accel.c @@ -0,0 +1,141 @@ +/* + * Copyright © 2001 Keith Packard + * Copyright 2011 VMWare, Inc. All Rights Reserved. + * May partly be based on code that is Copyright © The XFree86 Project Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Eric Anholt + * Author: Michel Dänzer + * Author: Thomas Hellstrom + */ + +#include "saa.h" +#include "saa_priv.h" + +Bool +saa_hw_copy_nton(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, int dx, int dy, Bool reverse, Bool upsidedown) +{ + ScreenPtr pScreen = pDstDrawable->pScreen; + struct saa_screen_priv *sscreen = saa_screen(pDstDrawable->pScreen); + struct saa_driver *driver = sscreen->driver; + PixmapPtr pSrcPixmap, pDstPixmap; + struct saa_pixmap *src_spix, *dst_spix; + int src_off_x, src_off_y; + int dst_off_x, dst_off_y; + RegionRec dst_reg, *src_reg; + int ordering; + Bool ret = TRUE; + + (void)pScreen; + + /* avoid doing copy operations if no boxes */ + if (nbox == 0) + return TRUE; + + pSrcPixmap = saa_get_pixmap(pSrcDrawable, &src_off_x, &src_off_y); + pDstPixmap = saa_get_pixmap(pDstDrawable, &dst_off_x, &dst_off_y); + src_spix = saa_pixmap(pSrcPixmap); + dst_spix = saa_pixmap(pDstPixmap); + + ordering = (nbox == 1 || (dx > 0 && dy > 0) || + (pDstDrawable != pSrcDrawable && + (pDstDrawable->type != DRAWABLE_WINDOW || + pSrcDrawable->type != DRAWABLE_WINDOW))) ? + CT_YXBANDED : CT_UNSORTED; + + src_reg = saa_boxes_to_region(pScreen, nbox, pbox, ordering); + if (!src_reg) + return FALSE; + + REGION_NULL(pScreen, &dst_reg); + REGION_COPY(pScreen, &dst_reg, src_reg); + REGION_TRANSLATE(pScreen, src_reg, dx + src_off_x, dy + src_off_y); + REGION_TRANSLATE(pScreen, &dst_reg, dst_off_x, dst_off_y); + + if (!(driver->copy_prepare) (driver, pSrcPixmap, pDstPixmap, + reverse ? -1 : 1, + upsidedown ? -1 : 1, + pGC ? pGC->alu : GXcopy, + src_reg, pGC ? pGC->planemask : FB_ALLONES)) { + goto fallback; + } + + while (nbox--) { + (driver->copy) (driver, + pbox->x1 + dx + src_off_x, + pbox->y1 + dy + src_off_y, + pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + pbox++; + } + + (driver->copy_done) (driver); + saa_pixmap_dirty(pDstPixmap, TRUE, &dst_reg); + goto out; + + fallback: + ret = FALSE; + + out: + REGION_UNINIT(pScreen, &dst_reg); + REGION_DESTROY(pScreen, src_reg); + + return ret; +} + +static void +saa_copy_nton(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) +{ + if (saa_hw_copy_nton(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, + reverse, upsidedown)) + return; + + saa_check_copy_nton(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, + reverse, upsidedown, bitplane, closure); +} + +RegionPtr +saa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty) +{ + struct saa_screen_priv *sscreen = saa_screen(pDstDrawable->pScreen); + + if (sscreen->fallback_count) { + return saa_check_copy_area(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty); + } + + return miDoCopy(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, saa_copy_nton, 0, NULL); +} diff --git a/saa/saa_pixmap.c b/saa/saa_pixmap.c new file mode 100644 index 0000000..0d63091 --- /dev/null +++ b/saa/saa_pixmap.c @@ -0,0 +1,222 @@ +/* + * Copyright © 2009 Maarten Maathuis + * Copyright 2011 VMWare, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Based on "exa_driver.c" + * Author: Thomas Hellstrom + */ + +#include "saa_priv.h" +#include "saa.h" + +PixmapPtr +saa_create_pixmap(ScreenPtr pScreen, int w, int h, int depth, + unsigned usage_hint) +{ + PixmapPtr pPixmap; + struct saa_pixmap *spix; + int bpp; + size_t paddedWidth; + struct saa_screen_priv *sscreen = saa_screen(pScreen); + int new_pitch = 0; + struct saa_driver *driver = sscreen->driver; + + if (w > 32767 || h > 32767) + return NullPixmap; + + /* + * Create a scratch pixmap without backing storage (w and h are zero) + */ + + saa_swap(sscreen, pScreen, CreatePixmap); + pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint); + saa_swap(sscreen, pScreen, CreatePixmap); + + if (!pPixmap) + goto out_no_pix; + + spix = saa_pixmap(pPixmap); + memset(spix, 0, driver->pixmap_size); + REGION_NULL(pScreen, &spix->dirty_shadow); + REGION_NULL(pScreen, &spix->dirty_hw); + REGION_NULL(pScreen, &spix->shadow_damage); + spix->read_access = 0; + spix->write_access = 0; + spix->mapped_access = 0; + spix->addr = NULL; + spix->auth_loc = saa_loc_override; + spix->override = SAA_INVALID_ADDRESS; + spix->pixmap = pPixmap; + bpp = pPixmap->drawable.bitsPerPixel; + + if (!driver->create_pixmap(driver, spix, w, h, depth, + usage_hint, bpp, &new_pitch)) + goto out_no_driver_priv; + + paddedWidth = new_pitch; + spix->damage = NULL; + + /* + * Now set w and h to the correct value. This might allocate + * backing store if w and h are NON-NULL. + */ + + if (!(*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, + paddedWidth, NULL)) + goto out_no_pixmap_header; + + /* + * During a fallback we must prepare access. This hack is initially used + * for pixmaps created during ValidateGC. + */ + + spix->fallback_created = FALSE; + if (sscreen->fallback_count) { + if (!saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_W, NULL)) + goto out_no_access; + + spix->fallback_created = TRUE; + } + + return pPixmap; + out_no_access: + out_no_pixmap_header: + driver->destroy_pixmap(driver, pPixmap); + out_no_driver_priv: + saa_swap(sscreen, pScreen, DestroyPixmap); + pScreen->DestroyPixmap(pPixmap); + saa_swap(sscreen, pScreen, DestroyPixmap); + out_no_pix: + LogMessage(X_ERROR, "Failing pixmap creation.\n"); + return NullPixmap; +} + +Bool +saa_destroy_pixmap(PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + struct saa_screen_priv *sscreen = saa_screen(pScreen); + Bool ret; + struct saa_driver *driver = sscreen->driver; + + if (pPixmap->refcnt == 1) { + struct saa_pixmap *spix = saa_pixmap(pPixmap); + + if (spix->fallback_created) { + if (!sscreen->fallback_count) + LogMessage(X_ERROR, "Fallback pixmap destroyed outside " + "fallback.\n"); + + saa_finish_access_pixmap(pPixmap, SAA_ACCESS_W); + } + + driver->destroy_pixmap(driver, pPixmap); + + REGION_UNINIT(pScreen, &spix->dirty_hw); + REGION_UNINIT(pScreen, &spix->dirty_shadow); + spix->damage = NULL; + } + + saa_swap(sscreen, pScreen, DestroyPixmap); + ret = pScreen->DestroyPixmap(pPixmap); + saa_swap(sscreen, pScreen, DestroyPixmap); + + return ret; +} + +Bool +saa_modify_pixmap_header(PixmapPtr pPixmap, int width, int height, int depth, + int bitsPerPixel, int devKind, pointer pPixData) +{ + ScreenPtr pScreen; + struct saa_screen_priv *sscreen; + struct saa_pixmap *spix; + struct saa_driver *driver; + Bool ret = TRUE; + + if (!pPixmap) + return FALSE; + + pScreen = pPixmap->drawable.pScreen; + sscreen = saa_screen(pScreen); + spix = saa_pixmap(pPixmap); + driver = sscreen->driver; + + if (spix && driver->modify_pixmap_header && + driver->modify_pixmap_header(pPixmap, width, height, depth, + bitsPerPixel, devKind, pPixData)) { + spix->auth_loc = saa_loc_driver; + spix->override = SAA_INVALID_ADDRESS; + goto out; + } + + saa_swap(sscreen, pScreen, ModifyPixmapHeader); + ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, + bitsPerPixel, devKind, pPixData); + saa_swap(sscreen, pScreen, ModifyPixmapHeader); + spix->override = pPixmap->devPrivate.ptr; + spix->auth_loc = saa_loc_override; + + out: + pPixmap->devPrivate.ptr = NULL; + return ret; +} + +struct saa_pixmap * +saa_get_saa_pixmap(PixmapPtr pPixmap) +{ + return saa_pixmap(pPixmap); +} + +void +saa_pixmap_dirty(PixmapPtr pixmap, Bool hw, RegionPtr reg) +{ + struct saa_pixmap *spix = saa_pixmap(pixmap); + struct saa_screen_priv *sscreen = saa_screen(pixmap->drawable.pScreen); + + if (hw) { + REGION_UNION(pixmap->drawable.pScreen, &spix->dirty_hw, + &spix->dirty_hw, reg); + REGION_SUBTRACT(pixmap->drawable.pScreen, &spix->dirty_shadow, + &spix->dirty_shadow, reg); + } else { + REGION_UNION(pixmap->drawable.pScreen, &spix->dirty_shadow, + &spix->dirty_shadow, reg); + REGION_SUBTRACT(pixmap->drawable.pScreen, &spix->dirty_hw, + &spix->dirty_hw, reg); + } + + sscreen->driver->damage(sscreen->driver, pixmap, hw, reg); +} + +void +saa_drawable_dirty(DrawablePtr draw, Bool hw, RegionPtr reg) +{ + PixmapPtr pixmap; + int x_offset, y_offset; + + pixmap = saa_get_pixmap(draw, &x_offset, &y_offset); + REGION_TRANSLATE(draw->pScreen, reg, x_offset, y_offset); + saa_pixmap_dirty(pixmap, hw, reg); + REGION_TRANSLATE(draw->pScreen, reg, -x_offset, -y_offset); +} diff --git a/saa/saa_priv.h b/saa/saa_priv.h new file mode 100644 index 0000000..f86f196 --- /dev/null +++ b/saa/saa_priv.h @@ -0,0 +1,263 @@ +/* + * + * Copyright (C) 2000 Keith Packard, member of The XFree86 Project, Inc. + * 2005 Zack Rusin, Trolltech + * Copyright 2011 VMWare, inc. All rights reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * + * Authors: Based on exa_priv.h + * Authors: Thomas Hellstrom + */ + +#ifndef _SAA_PRIV_H +#define _SAA_PRIV_H + +#ifdef HAVE_CONFIG_H +#include +#endif +#ifdef HAVE_DIX_CONFIG_H +#include +#else +#include +#endif +#include "xf86.h" + +#include "saa.h" + +#include +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "mibstore.h" +#include "colormapst.h" +#include "gcstruct.h" +#include "input.h" +#include "mipointer.h" +#include "mi.h" +#include "dix.h" +#include "fb.h" +#include "fboverlay.h" +#ifdef RENDER +#include "glyphstr.h" +#endif +#include "damage.h" + +#define SAA_INVALID_ADDRESS \ + ((void *) ((unsigned long) 0xFFFFFFFF - 1024*1024)) + +struct saa_gc_priv { + /* GC values from the layer below. */ + GCOps *saved_ops; + GCFuncs *saved_funcs; +}; + +struct saa_screen_priv { + struct saa_driver *driver; + CreateGCProcPtr saved_CreateGC; + CloseScreenProcPtr saved_CloseScreen; + GetImageProcPtr saved_GetImage; + GetSpansProcPtr saved_GetSpans; + CreatePixmapProcPtr saved_CreatePixmap; + DestroyPixmapProcPtr saved_DestroyPixmap; + CopyWindowProcPtr saved_CopyWindow; + ChangeWindowAttributesProcPtr saved_ChangeWindowAttributes; + BitmapToRegionProcPtr saved_BitmapToRegion; + ModifyPixmapHeaderProcPtr saved_ModifyPixmapHeader; +#ifdef RENDER + CompositeProcPtr saved_Composite; + CompositeRectsProcPtr saved_CompositeRects; + TrianglesProcPtr saved_Triangles; + GlyphsProcPtr saved_Glyphs; + TrapezoidsProcPtr saved_Trapezoids; + AddTrapsProcPtr saved_AddTraps; + UnrealizeGlyphProcPtr saved_UnrealizeGlyph; + SourceValidateProcPtr saved_SourceValidate; +#endif + Bool fallback_debug; + + unsigned int fallback_count; + + RegionRec srcReg; + RegionRec maskReg; + PixmapPtr srcPix; +}; + +extern GCOps saa_gc_ops; + +#if DEBUG_TRACE_FALL +#define SAA_FALLBACK(x) \ +do { \ + ErrorF("SAA fallback at %s: ", __FUNCTION__); \ + ErrorF x; \ +} while (0) + +#define saa_drawable_location() ("u") +#else +#define SAA_FALLBACK(x) +#endif + +/* + * Some macros to deal with function wrapping. + */ +#define saa_wrap(priv, real, mem, func) {\ + (priv)->saved_##mem = (real)->mem; \ + (real)->mem = func; \ +} + +#define saa_unwrap(priv, real, mem) {\ + (real)->mem = (priv)->saved_##mem; \ +} + +#define saa_swap(priv, real, mem) {\ + void *tmp = (priv)->saved_##mem; \ + (priv)->saved_##mem = (real)->mem; \ + (real)->mem = tmp; \ +} + +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 8) +#define SAA_DEVPRIVATEKEYREC 1 + +extern DevPrivateKeyRec saa_screen_index; +extern DevPrivateKeyRec saa_pixmap_index; +extern DevPrivateKeyRec saa_gc_index; + +static inline struct saa_screen_priv * +saa_screen(ScreenPtr screen) +{ + return (struct saa_screen_priv *)dixGetPrivate(&screen->devPrivates, + &saa_screen_index); +} + +static inline struct saa_gc_priv * +saa_gc(GCPtr gc) +{ + return (struct saa_gc_priv *)dixGetPrivateAddr(&gc->devPrivates, + &saa_gc_index); +} + +static inline struct saa_pixmap * +saa_pixmap(PixmapPtr pix) +{ + return (struct saa_pixmap *)dixGetPrivateAddr(&pix->devPrivates, + &saa_pixmap_index); +} +#else +#undef SAA_DEVPRIVATEKEYREC +extern int saa_screen_index; +extern int saa_pixmap_index; +extern int saa_gc_index; + +static inline struct saa_screen_priv * +saa_screen(ScreenPtr screen) +{ + return (struct saa_screen_priv *)dixLookupPrivate(&screen->devPrivates, + &saa_screen_index); +} + +static inline struct saa_gc_priv * +saa_gc(GCPtr gc) +{ + return (struct saa_gc_priv *)dixLookupPrivateAddr(&gc->devPrivates, + &saa_gc_index); +} + +static inline struct saa_pixmap_priv * +saa_pixmap(PixmapPtr pix) +{ + return (struct saa_pixmap_priv *)dixLookupPrivateAddr(&pix->devPrivates, + &saa_pixmap_index); +} + +#endif + +extern void +saa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans, + DDXPointPtr ppt, int *pwidth, int fSorted); +extern void +saa_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC, + int nrect, xRectangle * prect); +extern RegionPtr +saa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, int dstx, int dsty); +extern void +saa_check_copy_nton(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, + Bool upsidedown, Pixel bitplane, void *closure); + +extern void +saa_unaccel_setup(ScreenPtr pScreen); + +extern void +saa_unaccel_takedown(ScreenPtr pScreen); + +extern RegionPtr +saa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty); + +extern Bool +saa_hw_copy_nton(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, int dx, int dy, Bool reverse, Bool upsidedown); + +#ifdef RENDER +extern void +saa_render_setup(ScreenPtr pScreen); + +extern void +saa_render_takedown(ScreenPtr pScreen); + +extern void +saa_check_composite(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 + +extern Bool +saa_modify_pixmap_header(PixmapPtr pPixmap, int width, int height, int depth, + int bitsPerPixel, int devKind, pointer pPixData); + +extern PixmapPtr +saa_create_pixmap(ScreenPtr pScreen, int w, int h, int depth, + unsigned usage_hint); + +extern Bool +saa_destroy_pixmap(PixmapPtr pPixmap); + +static inline RegionPtr +saa_pix_damage_pending(struct saa_pixmap *spix) +{ + return (spix->damage ? DamagePendingRegion(spix->damage) : NULL); +} + +extern RegionPtr +saa_boxes_to_region(ScreenPtr pScreen, int nbox, BoxPtr pbox, int ordering); + +#endif diff --git a/saa/saa_render.c b/saa/saa_render.c new file mode 100644 index 0000000..1df0dff --- /dev/null +++ b/saa/saa_render.c @@ -0,0 +1,313 @@ +/* + * Copyright © 2001 Keith Packard + * Copyright 2011 VMWare, Inc. All Rights Reserved. + * May partly be based on code that is Copyright © The XFree86 Project Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Eric Anholt + * Author: Michel Dänzer + * Author: Thomas Hellstrom + */ +#include "saa.h" +#include "saa_priv.h" + +#ifdef RENDER +#include + +/** + * Same as miCreateAlphaPicture, except it uses + * saa_check_poly_fill_rect instead + */ + +static PicturePtr +saa_create_alpha_picture(ScreenPtr pScreen, + PicturePtr pDst, + PictFormatPtr pPictFormat, CARD16 width, CARD16 height) +{ + PixmapPtr pPixmap; + PicturePtr pPicture; + GCPtr pGC; + int error; + xRectangle rect; + + if (width > 32767 || height > 32767) + return 0; + + if (!pPictFormat) { + if (pDst->polyEdge == PolyEdgeSharp) + pPictFormat = PictureMatchFormat(pScreen, 1, PICT_a1); + else + pPictFormat = PictureMatchFormat(pScreen, 8, PICT_a8); + if (!pPictFormat) + return 0; + } + + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, + pPictFormat->depth, 0); + if (!pPixmap) + return 0; + pGC = GetScratchGC(pPixmap->drawable.depth, pScreen); + if (!pGC) { + (*pScreen->DestroyPixmap) (pPixmap); + return 0; + } + ValidateGC(&pPixmap->drawable, pGC); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + saa_check_poly_fill_rect(&pPixmap->drawable, pGC, 1, &rect); + FreeScratchGC(pGC); + pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat, + 0, 0, serverClient, &error); + (*pScreen->DestroyPixmap) (pPixmap); + return pPicture; +} + +/** + * saa_trapezoids is essentially a copy of miTrapezoids that uses + * saa_create_alpha_picture instead of miCreateAlphaPicture. + * + * The problem with miCreateAlphaPicture is that it calls PolyFillRect + * to initialize the contents after creating the pixmap, which + * causes the pixmap to be moved in for acceleration. The subsequent + * call to RasterizeTrapezoid won't be accelerated however, which + * forces the pixmap to be moved out again. + * + */ +static void +saa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntrap, xTrapezoid * traps) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + BoxRec bounds; + + if (maskFormat) { + PicturePtr pPicture; + INT16 xDst, yDst; + INT16 xRel, yRel; + saa_access_t access; + + miTrapezoidBounds(ntrap, traps, &bounds); + + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + + xDst = traps[0].left.p1.x >> 16; + yDst = traps[0].left.p1.y >> 16; + + pPicture = saa_create_alpha_picture(pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + + if (saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access)) { + for (; ntrap; ntrap--, traps++) + (*ps->RasterizeTrapezoid) (pPicture, traps, + -bounds.x1, -bounds.y1); + saa_fad_write(pPicture->pDrawable, access); + } + + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture(op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + FreePicture(pPicture, 0); + } else { + if (pDst->polyEdge == PolyEdgeSharp) + maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1); + else + maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8); + for (; ntrap; ntrap--, traps++) + saa_trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps); + } +} + +/** + * saa_triangles is essentially a copy of miTriangles that uses + * saa_create_alpha_picture instead of miCreateAlphaPicture. + * + * The problem with miCreateAlphaPicture is that it calls PolyFillRect + * to initialize the contents after creating the pixmap, which + * causes the pixmap to be moved in for acceleration. The subsequent + * call to AddTriangles won't be accelerated however, which forces the pixmap + * to be moved out again. + */ +static void +saa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int ntri, xTriangle * tris) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + BoxRec bounds; + + if (maskFormat) { + PicturePtr pPicture; + INT16 xDst, yDst; + INT16 xRel, yRel; + saa_access_t access; + + miTriangleBounds(ntri, tris, &bounds); + + if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) + return; + + xDst = tris[0].p1.x >> 16; + yDst = tris[0].p1.y >> 16; + + pPicture = saa_create_alpha_picture(pScreen, pDst, maskFormat, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + if (!pPicture) + return; + + if (saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access)) { + (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris); + saa_fad_write(pPicture->pDrawable, access); + } + + xRel = bounds.x1 + xSrc - xDst; + yRel = bounds.y1 + ySrc - yDst; + CompositePicture(op, pSrc, pPicture, pDst, + xRel, yRel, 0, 0, bounds.x1, bounds.y1, + bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); + FreePicture(pPicture, 0); + } else { + if (pDst->polyEdge == PolyEdgeSharp) + maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1); + else + maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8); + + for (; ntri; ntri--, tris++) + saa_triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris); + } +} + +/* + * Try to turn a composite operation into an accelerated copy. + * We can do that in some special cases for PictOpSrc and PictOpOver. + */ + +static Bool +saa_copy_composite(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + if (!pSrc->pDrawable || pSrc->transform || + pSrc->repeat || xSrc < 0 || ySrc < 0 || + xSrc + width > pSrc->pDrawable->width || + ySrc + height > pSrc->pDrawable->height) + return FALSE; + + if ((op == PictOpSrc && + (pSrc->format == pDst->format || + (PICT_FORMAT_COLOR(pDst->format) && + PICT_FORMAT_COLOR(pSrc->format) && + pDst->format == PICT_FORMAT(PICT_FORMAT_BPP(pSrc->format), + PICT_FORMAT_TYPE(pSrc->format), + 0, + PICT_FORMAT_R(pSrc->format), + PICT_FORMAT_G(pSrc->format), + PICT_FORMAT_B(pSrc->format))))) || + (op == PictOpOver && pSrc->format == pDst->format && + !PICT_FORMAT_A(pSrc->format))) { + + Bool ret; + RegionRec region; + + REGION_NULL(pDst->pDrawable.pScreen, ®ion); + + xDst += pDst->pDrawable->x; + yDst += pDst->pDrawable->y; + xSrc += pSrc->pDrawable->x; + ySrc += pSrc->pDrawable->y; + + if (!miComputeCompositeRegion(®ion, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, + yDst, width, height)) { + return TRUE; + } + + ret = saa_hw_copy_nton(pSrc->pDrawable, pDst->pDrawable, NULL, + RegionRects(®ion), + RegionNumRects(®ion), + xSrc - xDst, ySrc - yDst, FALSE, FALSE); + RegionUninit(®ion); + if (ret) + return TRUE; + } + return FALSE; +} + +static void +saa_composite(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + if (!saa_copy_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height)) + saa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height); +} + +void +saa_render_setup(ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + struct saa_screen_priv *sscreen = saa_screen(pScreen); + + if (ps) { + saa_wrap(sscreen, ps, Trapezoids, saa_trapezoids); + saa_wrap(sscreen, ps, Triangles, saa_triangles); + saa_wrap(sscreen, ps, Composite, saa_composite); + } +} + +void +saa_render_takedown(ScreenPtr pScreen) +{ + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + struct saa_screen_priv *sscreen = saa_screen(pScreen); + + if (ps) { + saa_unwrap(sscreen, ps, Trapezoids); + saa_unwrap(sscreen, ps, Triangles); + saa_unwrap(sscreen, ps, Composite); + } +} +#endif diff --git a/saa/saa_unaccel.c b/saa/saa_unaccel.c new file mode 100644 index 0000000..27b399d --- /dev/null +++ b/saa/saa_unaccel.c @@ -0,0 +1,896 @@ +/* + * Copyright © 1999 Keith Packard + * Copyright 2011 VMWare, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Based on "exa_unaccel.c" + * Author: Thomas Hellstrom + */ + +#include "saa_priv.h" +#include "saa.h" +#include "mipict.h" + +/** + * Calls saa_prepare_access with SAA_ACCESS_R for the tile, if that is the + * current fill style. + * + * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are + * 1bpp and never in fb, so we don't worry about them. + * We should worry about them for completeness sake and going forward. + */ +static Bool +saa_prepare_access_gc(GCPtr pGC) +{ + if (pGC->stipple) + if (!saa_pad_read(&pGC->stipple->drawable)) + return FALSE; + if (pGC->fillStyle == FillTiled) + if (!saa_pad_read(&pGC->tile.pixmap->drawable)) { + if (pGC->stipple) + saa_fad_read(&pGC->stipple->drawable); + return FALSE; + } + return TRUE; +} + +/** + * Finishes access to the tile in the GC, if used. + */ +static void +saa_finish_access_gc(GCPtr pGC) +{ + if (pGC->fillStyle == FillTiled) + saa_fad_read(&pGC->tile.pixmap->drawable); + if (pGC->stipple) + saa_fad_read(&pGC->stipple->drawable); +} + +void +saa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access; + + SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_location(pDrawable))); + + sscreen->fallback_count++; + if (saa_pad_write(pDrawable, NULL, FALSE, &access)) { + if (saa_prepare_access_gc(pGC)) { + saa_swap(sgc, pGC, ops); + pGC->ops->FillSpans(pDrawable, pGC, nspans, ppt, pwidth, fSorted); + saa_swap(sgc, pGC, ops); + saa_finish_access_gc(pGC); + } + saa_fad_write(pDrawable, access); + } + sscreen->fallback_count--; +} + +static void +saa_check_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc, + DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) +{ + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access + SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); + + sscreen->fallback_count++; + if (saa_pad_write(pDrawable, NULL, FALSE, &access)) { + saa_swap(sgc, pGC, ops); + pGC->ops->SetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); + saa_swap(sgc, pGC, ops); + saa_fad_write(pDrawable, access); + } + sscreen->fallback_count--; +} + +static void +saa_check_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + char *bits) +{ + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access; + + SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); + sscreen->fallback_count++; + if (saa_pad_write(pDrawable, pGC, TRUE, &access)) { + saa_swap(sgc, pGC, ops); + pGC->ops->PutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, + format, bits); + saa_swap(sgc, pGC, ops); + saa_fad_write(pDrawable, access); + } + sscreen->fallback_count--; +} + +RegionPtr +saa_boxes_to_region(ScreenPtr pScreen, int nbox, BoxPtr pbox, int ordering) +{ + xRectangle *rects = malloc(nbox * sizeof(*rects)); + int i; + RegionPtr reg; + + if (!rects) + return NULL; + + for (i = 0; i < nbox; i++) { + rects[i].x = pbox[i].x1; + rects[i].y = pbox[i].y1; + rects[i].width = pbox[i].x2 - pbox[i].x1; + rects[i].height = pbox[i].y2 - pbox[i].y1; + } + + reg = RECTS_TO_REGION(pScreen, nbox, rects, ordering); + free(rects); + return reg; +} + +void +saa_check_copy_nton(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, + Bool upsidedown, Pixel bitplane, void *closure) +{ + ScreenPtr pScreen = pSrc->pScreen; + struct saa_screen_priv *sscreen = saa_screen(pScreen); + RegionPtr reg, readback; + int src_xoff, src_yoff, dst_xoff, dst_yoff; + struct saa_gc_priv *sgc = saa_gc(pGC); + PixmapPtr src_pixmap; + PixmapPtr dst_pixmap; + saa_access_t access = SAA_ACCESS_R; + int ordering; + + sscreen->fallback_count++; + SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, + saa_drawable_loc(pSrc), saa_drawable_loc(pDst))); + + src_pixmap = saa_get_pixmap(pSrc, &src_xoff, &src_yoff); + dst_pixmap = saa_get_pixmap(pDst, &dst_xoff, &dst_yoff); + + ordering = (nbox == 1 || (dx > 0 && dy > 0) || + (pDst != pSrc && + (pDst->type != DRAWABLE_WINDOW || + pSrc->type != DRAWABLE_WINDOW))) ? CT_YXBANDED : CT_UNSORTED; + + reg = saa_boxes_to_region(pScreen, nbox, pbox, ordering); + if (!reg) + return; + + REGION_TRANSLATE(pScreen, reg, src_xoff + dx, src_yoff + dy); + if (!saa_prepare_access_pixmap(src_pixmap, SAA_ACCESS_R, reg)) + goto out_no_access; + + REGION_TRANSLATE(pScreen, reg, dst_xoff - dx - src_xoff, + dst_yoff - dy - src_yoff); + + if (saa_gc_reads_destination(pDst, pGC)) { + readback = reg; + access = SAA_ACCESS_RW; + } else { + readback = NULL; + access = SAA_ACCESS_W; + } + + if (!saa_prepare_access_pixmap(dst_pixmap, access, readback)) + goto out_no_dst; + + saa_swap(sgc, pGC, ops); + while (nbox--) { + pGC->ops->CopyArea(pSrc, pDst, pGC, pbox->x1 - pSrc->x + dx, + pbox->y1 - pSrc->y + dy, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, + pbox->x1 - pDst->x, pbox->y1 - pDst->y); + pbox++; + } + + saa_swap(sgc, pGC, ops); + saa_finish_access_pixmap(dst_pixmap, access); + saa_pixmap_dirty(dst_pixmap, FALSE, reg); + out_no_dst: + saa_fad_read(pSrc); + out_no_access: + sscreen->fallback_count--; + REGION_DESTROY(pScreen, reg); +} + +RegionPtr +saa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, int dstx, int dsty) +{ + RegionPtr ret = NULL; + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access; + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + + SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, + saa_drawable_loc(pSrc), saa_drawable_loc(pDst))); + sscreen->fallback_count++; + if (!saa_pad_read_box(pSrc, srcx, srcy, w, h)) + goto out_no_access; + if (!saa_pad_write(pDst, pGC, TRUE, &access)) + goto out_no_dst; + + saa_swap(sgc, pGC, ops); + ret = pGC->ops->CopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + saa_swap(sgc, pGC, ops); + + saa_fad_write(pDst, access); + out_no_dst: + saa_fad_read(pSrc); + out_no_access: + sscreen->fallback_count--; + + return ret; +} + +static RegionPtr +saa_check_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, int dstx, int dsty, + unsigned long bitplane) +{ + RegionPtr ret = NULL; + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access; + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + + SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, + saa_drawable_loc(pSrc), saa_drawable_loc(pDst))); + sscreen->fallback_count++; + if (!saa_pad_read_box(pSrc, srcx, srcy, w, h)) + goto out_no_src; + if (!saa_pad_write(pDst, pGC, TRUE, &access)) + goto out_no_dst; + + saa_swap(sgc, pGC, ops); + ret = pGC->ops->CopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, + bitplane); + saa_swap(sgc, pGC, ops); + + saa_fad_write(pDst, access); + out_no_dst: + saa_fad_read(pSrc); + out_no_src: + sscreen->fallback_count--; + + return ret; +} + +static void +saa_check_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, + DDXPointPtr pptInit) +{ + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access; + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + + sscreen->fallback_count++; + SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); + if (!saa_pad_write(pDrawable, NULL, FALSE, &access)) + goto out_no_access; + saa_swap(sgc, pGC, ops); + pGC->ops->PolyPoint(pDrawable, pGC, mode, npt, pptInit); + saa_swap(sgc, pGC, ops); + saa_fad_write(pDrawable, access); + + out_no_access: + sscreen->fallback_count--; +} + +static void +saa_check_poly_lines(DrawablePtr pDrawable, GCPtr pGC, + int mode, int npt, DDXPointPtr ppt) +{ + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access; + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + + SAA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n", + pDrawable, saa_drawable_loc(pDrawable), + pGC->lineWidth, mode, npt)); + + sscreen->fallback_count++; + if (!saa_pad_write(pDrawable, NULL, FALSE, &access)) + goto out_no_access; + if (!saa_prepare_access_gc(pGC)) + goto out_no_gc; + saa_swap(sgc, pGC, ops); + pGC->ops->Polylines(pDrawable, pGC, mode, npt, ppt); + saa_swap(sgc, pGC, ops); + saa_finish_access_gc(pGC); + out_no_gc: + saa_fad_write(pDrawable, access); + out_no_access: + sscreen->fallback_count--; +} + +static void +saa_check_poly_segment(DrawablePtr pDrawable, GCPtr pGC, + int nsegInit, xSegment * pSegInit) +{ + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access; + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + + SAA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable, + saa_drawable_loc(pDrawable), pGC->lineWidth, nsegInit)); + + sscreen->fallback_count++; + if (!saa_pad_write(pDrawable, NULL, FALSE, &access)) + goto out_no_access;; + if (!saa_prepare_access_gc(pGC)) + goto out_no_gc; + saa_swap(sgc, pGC, ops); + pGC->ops->PolySegment(pDrawable, pGC, nsegInit, pSegInit); + saa_swap(sgc, pGC, ops); + saa_finish_access_gc(pGC); + out_no_gc: + saa_fad_write(pDrawable, access); + out_no_access: + sscreen->fallback_count--; +} + +static void +saa_check_poly_arc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs) +{ + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access; + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + + SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); + + sscreen->fallback_count++; + if (!saa_pad_write(pDrawable, NULL, FALSE, &access)) + goto out_no_access;; + if (!saa_prepare_access_gc(pGC)) + goto out_no_gc; + saa_swap(sgc, pGC, ops); + pGC->ops->PolyArc(pDrawable, pGC, narcs, pArcs); + saa_swap(sgc, pGC, ops); + saa_finish_access_gc(pGC); + out_no_gc: + saa_fad_write(pDrawable, access); + out_no_access: + sscreen->fallback_count--; +} + +void +saa_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC, + int nrect, xRectangle * prect) +{ + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access; + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + + SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); + + sscreen->fallback_count++; + if (!saa_pad_write(pDrawable, pGC, TRUE, &access)) + goto out_no_access;; + if (!saa_prepare_access_gc(pGC)) + goto out_no_gc; + saa_swap(sgc, pGC, ops); + pGC->ops->PolyFillRect(pDrawable, pGC, nrect, prect); + saa_swap(sgc, pGC, ops); + saa_finish_access_gc(pGC); + out_no_gc: + saa_fad_write(pDrawable, access); + out_no_access: + sscreen->fallback_count--; +} + +static void +saa_check_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase) +{ + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access; + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + + SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); + + sscreen->fallback_count++; + if (!saa_pad_write(pDrawable, NULL, FALSE, &access)) + goto out_no_access;; + if (!saa_prepare_access_gc(pGC)) + goto out_no_gc; + saa_swap(sgc, pGC, ops); + pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + saa_swap(sgc, pGC, ops); + saa_finish_access_gc(pGC); + out_no_gc: + saa_fad_write(pDrawable, access); + out_no_access: + sscreen->fallback_count--; +} + +static void +saa_check_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase) +{ + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access; + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + + SAA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable, + saa_drawable_loc(pDrawable), pGC->fillStyle, pGC->alu)); + + sscreen->fallback_count++; + if (!saa_pad_write(pDrawable, NULL, FALSE, &access)) + goto out_no_access;; + if (!saa_prepare_access_gc(pGC)) + goto out_no_gc; + saa_swap(sgc, pGC, ops); + pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + saa_swap(sgc, pGC, ops); + saa_finish_access_gc(pGC); + out_no_gc: + saa_fad_write(pDrawable, access); + out_no_access: + sscreen->fallback_count--; +} + +static void +saa_check_push_pixels(GCPtr pGC, PixmapPtr pBitmap, + DrawablePtr pDrawable, int w, int h, int x, int y) +{ + struct saa_gc_priv *sgc = saa_gc(pGC); + saa_access_t access; + struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen); + + SAA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable, + saa_drawable_loc(&pBitmap->drawable), + saa_drawable_loc(pDrawable))); + + sscreen->fallback_count++; + if (!saa_pad_write(pDrawable, pGC, TRUE, &access)) + goto out_no_access;; + if (!saa_pad_read_box(&pBitmap->drawable, 0, 0, w, h)) + goto out_no_src; + if (!saa_prepare_access_gc(pGC)) + goto out_no_gc; + saa_swap(sgc, pGC, ops); + pGC->ops->PushPixels(pGC, pBitmap, pDrawable, w, h, x, y); + saa_swap(sgc, pGC, ops); + saa_finish_access_gc(pGC); + out_no_gc: + saa_fad_read(&pBitmap->drawable); + out_no_src: + saa_fad_write(pDrawable, access); + out_no_access: + sscreen->fallback_count--; +} + +static void +saa_check_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + DrawablePtr pDrawable = &pWin->drawable; + ScreenPtr pScreen = pDrawable->pScreen; + struct saa_screen_priv *sscreen = saa_screen(pScreen); + int xoff, yoff; + PixmapPtr pPixmap = saa_get_pixmap(&pWin->drawable, &xoff, &yoff); + Bool ret; + + SAA_FALLBACK(("from %p\n", pWin)); + + /* Only need the source bits, the destination region will be overwritten */ + + sscreen->fallback_count++; + REGION_TRANSLATE(pScreen, prgnSrc, xoff, yoff); + ret = saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_R, prgnSrc); + REGION_TRANSLATE(pScreen, prgnSrc, -xoff, -yoff); + if (!ret) + goto out_no_access;; + + if (saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_W, NULL)) { + saa_swap(sscreen, pScreen, CopyWindow); + pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc); + saa_swap(sscreen, pScreen, CopyWindow); + saa_fad_write(pDrawable, SAA_ACCESS_W); + } + saa_fad_read(pDrawable); + out_no_access: + sscreen->fallback_count--; +} + +#ifdef RENDER + +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10) +static void +saa_src_validate(DrawablePtr pDrawable, + int x, + int y, int width, int height, unsigned int subWindowMode) +#else +static void +saa_src_validate(DrawablePtr pDrawable, int x, int y, int width, int height) +#endif +{ + ScreenPtr pScreen = pDrawable->pScreen; + struct saa_screen_priv *sscreen = saa_screen(pScreen); + PixmapPtr pPix = saa_get_drawable_pixmap(pDrawable); + BoxRec box; + RegionRec reg; + RegionPtr dst; + int xoff, yoff; + + saa_get_drawable_deltas(pDrawable, pPix, &xoff, &yoff); + + box.x1 = x + xoff; + box.y1 = y + yoff; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + + dst = (sscreen->srcPix == pPix) ? &sscreen->srcReg : &sscreen->maskReg; + + REGION_INIT(pScreen, ®, &box, 1); + REGION_UNION(pScreen, dst, dst, ®); + REGION_UNINIT(pScreen, ®); + + if (sscreen->saved_SourceValidate) { + saa_swap(sscreen, pScreen, SourceValidate); + pScreen->SourceValidate(pDrawable, x, y, width, height +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10) + , subWindowMode +#endif + ); + saa_swap(sscreen, pScreen, SourceValidate); + } +} + +static void +saa_check_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int format, unsigned long planeMask, char *d) +{ + ScreenPtr pScreen = pDrawable->pScreen; + struct saa_screen_priv *sscreen = saa_screen(pScreen); + + SAA_FALLBACK(("from %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); + + sscreen->fallback_count++; + if (!saa_pad_read_box(pDrawable, x, y, w, h)) + goto out_no_access;; + saa_swap(sscreen, pScreen, GetImage); + pScreen->GetImage(pDrawable, x, y, w, h, format, planeMask, d); + saa_swap(sscreen, pScreen, GetImage); + saa_fad_read(pDrawable); + out_no_access: + sscreen->fallback_count--; +} + +static void +saa_check_get_spans(DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart) +{ + ScreenPtr pScreen = pDrawable->pScreen; + struct saa_screen_priv *sscreen = saa_screen(pScreen); + + SAA_FALLBACK(("from %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); + + sscreen->fallback_count++; + if (!saa_pad_read(pDrawable)) + goto out_no_access;; + saa_swap(sscreen, pScreen, GetSpans); + pScreen->GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + saa_swap(sscreen, pScreen, GetSpans); + saa_fad_read(pDrawable); + out_no_access: + sscreen->fallback_count--; +} + +static Bool +saa_prepare_composite_reg(ScreenPtr pScreen, + CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height, + RegionPtr region, saa_access_t * access) +{ + RegionPtr dstReg = NULL; + RegionPtr srcReg = NULL; + RegionPtr maskReg = NULL; + PixmapPtr pSrcPix = NULL; + PixmapPtr pMaskPix = NULL; + PixmapPtr pDstPix; + struct saa_screen_priv *sscreen = saa_screen(pScreen); + struct saa_pixmap *dst_spix; + Bool ret; + + *access = SAA_ACCESS_W; + + if (pSrc->pDrawable) { + pSrcPix = saa_get_drawable_pixmap(pSrc->pDrawable); + REGION_NULL(pScreen, &sscreen->srcReg); + srcReg = &sscreen->srcReg; + sscreen->srcPix = pSrcPix; + if (pSrc != pDst) + REGION_TRANSLATE(pScreen, pSrc->pCompositeClip, + -pSrc->pDrawable->x, -pSrc->pDrawable->y); + } + + if (pMask && pMask->pDrawable) { + pMaskPix = saa_get_drawable_pixmap(pMask->pDrawable); + REGION_NULL(pScreen, &sscreen->maskReg); + maskReg = &sscreen->maskReg; + if (pMask != pDst && pMask != pSrc) + REGION_TRANSLATE(pScreen, pMask->pCompositeClip, + -pMask->pDrawable->x, -pMask->pDrawable->y); + } + + REGION_TRANSLATE(pScreen, pDst->pCompositeClip, + -pDst->pDrawable->x, -pDst->pDrawable->y); + + sscreen->saved_SourceValidate = saa_src_validate; + saa_swap(sscreen, pScreen, SourceValidate); + ret = miComputeCompositeRegion(region, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height); + saa_swap(sscreen, pScreen, SourceValidate); + + REGION_TRANSLATE(pScreen, pDst->pCompositeClip, + pDst->pDrawable->x, pDst->pDrawable->y); + if (pSrc->pDrawable && pSrc != pDst) + REGION_TRANSLATE(pScreen, pSrc->pCompositeClip, + pSrc->pDrawable->x, pSrc->pDrawable->y); + if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc) + REGION_TRANSLATE(pScreen, pMask->pCompositeClip, + pMask->pDrawable->x, pMask->pDrawable->y); + + if (!ret) { + if (srcReg) + REGION_UNINIT(pScreen, srcReg); + if (maskReg) + REGION_UNINIT(pScreen, maskReg); + + return FALSE; + } + + /* + * Don't limit alphamaps readbacks for now until we've figured out how that + * should be done. + */ + + if (pSrc->alphaMap && pSrc->alphaMap->pDrawable) + if (!saa_pad_read(pSrc->alphaMap->pDrawable)) + goto out_no_src_alpha; + if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) + if (!saa_pad_read(pMask->alphaMap->pDrawable)) + goto out_no_mask_alpha; + if (pSrcPix) + if (!saa_prepare_access_pixmap(pSrcPix, SAA_ACCESS_R, srcReg)) + goto out_no_src; + if (pMaskPix) + if (!saa_prepare_access_pixmap(pMaskPix, SAA_ACCESS_R, maskReg)) + goto out_no_mask; + if (srcReg) + REGION_UNINIT(pScreen, srcReg); + if (maskReg) + REGION_UNINIT(pScreen, maskReg); + + pDstPix = saa_get_drawable_pixmap(pDst->pDrawable); + dst_spix = saa_get_saa_pixmap(pDstPix); + + if (dst_spix->damage) { + int xoff, yoff; + + saa_get_drawable_deltas(pDst->pDrawable, pDstPix, &xoff, &yoff); + REGION_TRANSLATE(pScreen, region, pDst->pDrawable->x + xoff, + pDst->pDrawable->y + yoff); + if (saa_op_reads_destination(op)) { + dstReg = region; + *access |= SAA_ACCESS_R; + } + } + + if (pDst->alphaMap && pDst->alphaMap->pDrawable) + if (!saa_prepare_access_pixmap + (saa_get_drawable_pixmap(pDst->alphaMap->pDrawable), + *access, dstReg)) + goto out_no_dst_alpha; + + if (!saa_prepare_access_pixmap(pDstPix, *access, dstReg)) + goto out_no_dst; + + return TRUE; + + out_no_dst: + LogMessage(X_ERROR, "No dst\n"); + saa_finish_access_pixmap + (saa_get_drawable_pixmap(pDst->alphaMap->pDrawable), *access); + out_no_dst_alpha: + LogMessage(X_ERROR, "No dst alpha\n"); + if (pMaskPix) + saa_finish_access_pixmap(pMaskPix, SAA_ACCESS_R); + out_no_mask: + LogMessage(X_ERROR, "No mask\n"); + if (pSrcPix) + saa_finish_access_pixmap(pSrcPix, SAA_ACCESS_R); + out_no_src: + LogMessage(X_ERROR, "No src\n"); + if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) + saa_fad_read(pMask->alphaMap->pDrawable); + out_no_mask_alpha: + LogMessage(X_ERROR, "No mask alpha\n"); + if (pSrc && pSrc->alphaMap && pSrc->alphaMap->pDrawable) + saa_fad_read(pSrc->alphaMap->pDrawable); + out_no_src_alpha: + LogMessage(X_ERROR, "No src alpha\n"); + if (srcReg) + REGION_UNINIT(pScreen, srcReg); + if (maskReg) + REGION_UNINIT(pScreen, maskReg); + return FALSE; + +} + +void +saa_check_composite(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; + PictureScreenPtr ps = GetPictureScreen(pScreen); + struct saa_screen_priv *sscreen = saa_screen(pScreen); + saa_access_t access; + RegionRec reg; + PixmapPtr pixmap; + + sscreen->fallback_count++; + REGION_NULL(pScreen, ®); + if (!saa_prepare_composite_reg(pScreen, op, pSrc, pMask, pDst, xSrc, + ySrc, xMask, yMask, xDst, yDst, width, + height, ®, &access)) { + goto out_no_access;; + } + + saa_swap(sscreen, ps, Composite); + ps->Composite(op, + pSrc, + pMask, + pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); + saa_swap(sscreen, ps, Composite); + if (pMask && pMask->pDrawable != NULL) + saa_fad_read(pMask->pDrawable); + if (pSrc->pDrawable != NULL) + saa_fad_read(pSrc->pDrawable); + pixmap = saa_get_drawable_pixmap(pDst->pDrawable); + saa_finish_access_pixmap(pixmap, access); + saa_pixmap_dirty(pixmap, FALSE, ®); + if (pDst->alphaMap && pDst->alphaMap->pDrawable) { + pixmap = saa_get_drawable_pixmap(pDst->alphaMap->pDrawable); + saa_finish_access_pixmap(pixmap, access); + saa_pixmap_dirty(pixmap, FALSE, ®); + } + if (pSrc->alphaMap && pSrc->alphaMap->pDrawable) + saa_fad_read(pSrc->alphaMap->pDrawable); + if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) + saa_fad_read(pMask->alphaMap->pDrawable); + out_no_access: + sscreen->fallback_count--; + REGION_UNINIT(pScreen, ®); +} + +static void +saa_check_add_traps(PicturePtr pPicture, + INT16 x_off, INT16 y_off, int ntrap, xTrap * traps) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + struct saa_screen_priv *sscreen = saa_screen(pScreen); + saa_access_t access; + + SAA_FALLBACK(("to pict %p (%c)\n", saa_drawable_loc(pPicture->pDrawable))); + + sscreen->fallback_count++; + if (!saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access)) + goto out_no_access; + saa_swap(sscreen, ps, AddTraps); + ps->AddTraps(pPicture, x_off, y_off, ntrap, traps); + saa_swap(sscreen, ps, AddTraps); + saa_fad_write(pPicture->pDrawable, access); + out_no_access: + sscreen->fallback_count--; +} + +#endif + +void +saa_unaccel_setup(ScreenPtr pScreen) +{ +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); +#endif + struct saa_screen_priv *sscreen = saa_screen(pScreen); + + saa_wrap(sscreen, pScreen, GetImage, saa_check_get_image); + saa_wrap(sscreen, pScreen, GetSpans, saa_check_get_spans); + saa_wrap(sscreen, pScreen, CopyWindow, saa_check_copy_window); + +#ifdef RENDER + if (ps) { + saa_wrap(sscreen, ps, AddTraps, saa_check_add_traps); + } +#endif +} + +void +saa_unaccel_takedown(ScreenPtr pScreen) +{ +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); +#endif + struct saa_screen_priv *sscreen = saa_screen(pScreen); + + saa_unwrap(sscreen, pScreen, GetImage); + saa_unwrap(sscreen, pScreen, GetSpans); + saa_unwrap(sscreen, pScreen, CopyWindow); + +#ifdef RENDER + if (ps) { + saa_unwrap(sscreen, ps, AddTraps); + } +#endif +} + +GCOps saa_gc_ops = { + saa_check_fill_spans, + saa_check_set_spans, + saa_check_put_image, + saa_copy_area, + saa_check_copy_plane, + saa_check_poly_point, + saa_check_poly_lines, + saa_check_poly_segment, + miPolyRectangle, + saa_check_poly_arc, + miFillPolygon, + saa_check_poly_fill_rect, + miPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + saa_check_image_glyph_blt, + saa_check_poly_glyph_blt, + saa_check_push_pixels, +}; diff --git a/src/svga_reg.h b/src/svga_reg.h index 4fa363a..5d36029 100644 --- a/src/svga_reg.h +++ b/src/svga_reg.h @@ -1,52 +1,72 @@ -/* ********************************************************** - * Copyright 1998 VMware, Inc. All rights reserved. - * **********************************************************/ +/********************************************************** + * Copyright 1998-2009 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + **********************************************************/ /* * svga_reg.h -- * - * SVGA hardware definitions + * Virtual hardware definitions for the VMware SVGA II device. */ #ifndef _SVGA_REG_H_ #define _SVGA_REG_H_ -#define INCLUDE_ALLOW_USERLEVEL -#define INCLUDE_ALLOW_VMMEXT -#define INCLUDE_ALLOW_VMCORE -#include "includeCheck.h" - /* - * Memory and port addresses and fundamental constants + * PCI device IDs. */ +#define PCI_VENDOR_ID_VMWARE 0x15AD +#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405 /* - * Note-- MAX_WIDTH and MAX_HEIGHT are largely ignored by the code. This - * isn't such a bad thing for forward compatibility. --Jeremy. + * Legal values for the SVGA_REG_CURSOR_ON register in old-fashioned + * cursor bypass mode. This is still supported, but no new guest + * drivers should use it. */ -#define SVGA_MAX_WIDTH 2360 -#define SVGA_MAX_HEIGHT 1770 -#define SVGA_MAX_BITS_PER_PIXEL 32 -#define SVGA_MAX_DEPTH 24 -#define SVGA_MAX_DISPLAYS 10 +#define SVGA_CURSOR_ON_HIDE 0x0 /* Must be 0 to maintain backward compatibility */ +#define SVGA_CURSOR_ON_SHOW 0x1 /* Must be 1 to maintain backward compatibility */ +#define SVGA_CURSOR_ON_REMOVE_FROM_FB 0x2 /* Remove the cursor from the framebuffer because we need to see what's under it */ +#define SVGA_CURSOR_ON_RESTORE_TO_FB 0x3 /* Put the cursor back in the framebuffer so the user can see it */ /* - * The maximum size of the onscreen framebuffer. The size of the - * changeMap in the monitor is proportional to this number since it's - * the amount of memory we need to trace in VESA mode. Therefore, we'd + * The maximum framebuffer size that can traced for e.g. guests in VESA mode. + * The changeMap in the monitor is proportional to this number. Therefore, we'd * like to keep it as small as possible to reduce monitor overhead (using - * SVGA_VRAM_MAX_SIZE for this increases the size of the shared area - * by over 4k!). + * SVGA_VRAM_MAX_SIZE for this increases the size of the shared area by over + * 4k!). + * + * NB: For compatibility reasons, this value must be greater than 0xff0000. + * See bug 335072. */ - -#define SVGA_FB_MAX_SIZE \ - ((((SVGA_MAX_WIDTH * SVGA_MAX_HEIGHT * \ - SVGA_MAX_BITS_PER_PIXEL / 8) >> PAGE_SHIFT) + 1) << PAGE_SHIFT) +#define SVGA_FB_MAX_TRACEABLE_SIZE 0x1000000 -#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8 -#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH) +#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8 +#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH) #define SVGA_NUM_PALETTE_REGS (3 * SVGA_MAX_PSEUDOCOLORS) +/* Base and Offset gets us headed the right way for PCI Base Addr Registers */ +#define SVGA_LEGACY_BASE_PORT 0x4560 + #define SVGA_MAGIC 0x900000UL #define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver)) @@ -63,19 +83,14 @@ #define SVGA_VERSION_0 0 #define SVGA_ID_0 SVGA_MAKE_ID(SVGA_VERSION_0) -/* Invalid SVGA_ID_ */ +/* "Invalid" value for all SVGA IDs. (Version ID, screen object ID, surface 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 -#define SVGA_IRQSTATUS_PORT 0x8 +/* Port offsets, relative to BAR0 */ +#define SVGA_INDEX_PORT 0x0 +#define SVGA_VALUE_PORT 0x1 +#define SVGA_BIOS_PORT 0x2 +#define SVGA_IRQSTATUS_PORT 0x8 /* * Interrupt source flags for IRQSTATUS_PORT and IRQMASK. @@ -87,15 +102,6 @@ #define SVGA_IRQFLAG_FIFO_PROGRESS 0x2 /* Made forward progress in the FIFO */ #define SVGA_IRQFLAG_FENCE_GOAL 0x4 /* SVGA_FIFO_FENCE_GOAL reached */ -/* 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 */ @@ -108,13 +114,13 @@ enum { 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_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_START = 13, /* (Deprecated) */ SVGA_REG_FB_OFFSET = 14, SVGA_REG_VRAM_SIZE = 15, SVGA_REG_FB_SIZE = 16, @@ -122,33 +128,44 @@ enum { /* ID 0 implementation only had the above registers, then the palette */ SVGA_REG_CAPABILITIES = 17, - SVGA_REG_MEM_START = 18, /* Memory for command FIFO and bitmaps */ + SVGA_REG_MEM_START = 18, /* (Deprecated) */ SVGA_REG_MEM_SIZE = 19, - SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */ - SVGA_REG_SYNC = 21, /* See "FIFO Synchronization Registers" */ - SVGA_REG_BUSY = 22, /* See "FIFO Synchronization Registers" */ - SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */ - SVGA_REG_CURSOR_ID = 24, /* 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_SCRATCH_SIZE = 29, /* Number of scratch registers */ - SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */ - SVGA_REG_NUM_DISPLAYS = 31, /* Number of guest displays */ - SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */ - SVGA_REG_IRQMASK = 33, /* Interrupt mask */ + SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */ + SVGA_REG_SYNC = 21, /* See "FIFO Synchronization Registers" */ + SVGA_REG_BUSY = 22, /* See "FIFO Synchronization Registers" */ + SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */ + SVGA_REG_CURSOR_ID = 24, /* (Deprecated) */ + SVGA_REG_CURSOR_X = 25, /* (Deprecated) */ + SVGA_REG_CURSOR_Y = 26, /* (Deprecated) */ + SVGA_REG_CURSOR_ON = 27, /* (Deprecated) */ + SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* (Deprecated) */ + SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */ + SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */ + SVGA_REG_NUM_DISPLAYS = 31, /* (Deprecated) */ + SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */ + SVGA_REG_IRQMASK = 33, /* Interrupt mask */ + + /* Legacy multi-monitor support */ SVGA_REG_NUM_GUEST_DISPLAYS = 34,/* Number of guest displays in X/Y direction */ - SVGA_REG_DISPLAY_ID = 35, /* The display ID for the following display attributes */ + SVGA_REG_DISPLAY_ID = 35, /* Display ID for the following display attributes */ SVGA_REG_DISPLAY_IS_PRIMARY = 36,/* Whether this is a primary display */ SVGA_REG_DISPLAY_POSITION_X = 37,/* The display position x */ SVGA_REG_DISPLAY_POSITION_Y = 38,/* The display position y */ SVGA_REG_DISPLAY_WIDTH = 39, /* The display's width */ SVGA_REG_DISPLAY_HEIGHT = 40, /* The display's height */ - SVGA_REG_TOP = 41, /* Must be 1 more than the last register */ - SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ + /* See "Guest memory regions" below. */ + SVGA_REG_GMR_ID = 41, + SVGA_REG_GMR_DESCRIPTOR = 42, + SVGA_REG_GMR_MAX_IDS = 43, + SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44, + + SVGA_REG_TRACES = 45, /* Enable trace-based updates even when FIFO is on */ + SVGA_REG_TOP = 46, /* Must be 1 more than the last register */ + + SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ /* Next 768 (== 256*3) registers exist for colormap */ + SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + SVGA_NUM_PALETTE_REGS /* Base of scratch registers */ /* Next reg[SVGA_REG_SCRATCH_SIZE] registers exist for scratch usage: @@ -156,126 +173,231 @@ enum { the use of the current SVGA driver. */ }; +/* + * 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_PIXMAP_SIZE(w,h,bpp) ((( ((w)*(bpp))+31 ) >> 5) * (h)) +#define SVGA_BITMAP_INCREMENT(w) ((( (w)+31 ) >> 5) * sizeof (uint32)) +#define SVGA_PIXMAP_INCREMENT(w,bpp) ((( ((w)*(bpp))+31 ) >> 5) * sizeof (uint32)) /* - * Capabilities + * Guest memory regions (GMRs): + * + * This is a new memory mapping feature available in SVGA devices + * which have the SVGA_CAP_GMR bit set. Previously, there were two + * fixed memory regions available with which to share data between the + * device and the driver: the FIFO ('MEM') and the framebuffer. GMRs + * are our name for an extensible way of providing arbitrary DMA + * buffers for use between the driver and the SVGA device. They are a + * new alternative to framebuffer memory, usable for both 2D and 3D + * graphics operations. + * + * Since GMR mapping must be done synchronously with guest CPU + * execution, we use a new pair of SVGA registers: + * + * SVGA_REG_GMR_ID -- + * + * Read/write. + * This register holds the 32-bit ID (a small positive integer) + * of a GMR to create, delete, or redefine. Writing this register + * has no side-effects. + * + * SVGA_REG_GMR_DESCRIPTOR -- + * + * Write-only. + * Writing this register will create, delete, or redefine the GMR + * specified by the above ID register. If this register is zero, + * the GMR is deleted. Any pointers into this GMR (including those + * currently being processed by FIFO commands) will be + * synchronously invalidated. + * + * If this register is nonzero, it must be the physical page + * number (PPN) of a data structure which describes the physical + * layout of the memory region this GMR should describe. The + * descriptor structure will be read synchronously by the SVGA + * device when this register is written. The descriptor need not + * remain allocated for the lifetime of the GMR. + * + * The guest driver should write SVGA_REG_GMR_ID first, then + * SVGA_REG_GMR_DESCRIPTOR. + * + * SVGA_REG_GMR_MAX_IDS -- + * + * Read-only. + * The SVGA device may choose to support a maximum number of + * user-defined GMR IDs. This register holds the number of supported + * IDs. (The maximum supported ID plus 1) + * + * SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH -- + * + * Read-only. + * The SVGA device may choose to put a limit on the total number + * of SVGAGuestMemDescriptor structures it will read when defining + * a single GMR. + * + * The descriptor structure is an array of SVGAGuestMemDescriptor + * structures. Each structure may do one of three things: + * + * - Terminate the GMR descriptor list. + * (ppn==0, numPages==0) + * + * - Add a PPN or range of PPNs to the GMR's virtual address space. + * (ppn != 0, numPages != 0) + * + * - Provide the PPN of the next SVGAGuestMemDescriptor, in order to + * support multi-page GMR descriptor tables without forcing the + * driver to allocate physically contiguous memory. + * (ppn != 0, numPages == 0) + * + * Note that each physical page of SVGAGuestMemDescriptor structures + * can describe at least 2MB of guest memory. If the driver needs to + * use more than one page of descriptor structures, it must use one of + * its SVGAGuestMemDescriptors to point to an additional page. The + * device will never automatically cross a page boundary. + * + * Once the driver has described a GMR, it is immediately available + * for use via any FIFO command that uses an SVGAGuestPtr structure. + * These pointers include a GMR identifier plus an offset into that + * GMR. + * + * The driver must check the SVGA_CAP_GMR bit before using the GMR + * registers. */ -#define SVGA_CAP_NONE 0x00000000 -#define SVGA_CAP_RECT_FILL 0x00000001 -#define SVGA_CAP_RECT_COPY 0x00000002 -#define SVGA_CAP_RECT_PAT_FILL 0x00000004 -#define SVGA_CAP_LEGACY_OFFSCREEN 0x00000008 -#define SVGA_CAP_RASTER_OP 0x00000010 -#define SVGA_CAP_CURSOR 0x00000020 -#define SVGA_CAP_CURSOR_BYPASS 0x00000040 -#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 -#define SVGA_CAP_8BIT_EMULATION 0x00000100 -#define SVGA_CAP_ALPHA_CURSOR 0x00000200 -#define SVGA_CAP_GLYPH 0x00000400 -#define SVGA_CAP_GLYPH_CLIPPING 0x00000800 -#define SVGA_CAP_OFFSCREEN_1 0x00001000 -#define SVGA_CAP_ALPHA_BLEND 0x00002000 -#define SVGA_CAP_3D 0x00004000 -#define SVGA_CAP_EXTENDED_FIFO 0x00008000 -#define SVGA_CAP_MULTIMON 0x00010000 -#define SVGA_CAP_PITCHLOCK 0x00020000 -#define SVGA_CAP_IRQMASK 0x00040000 -#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 +/* + * Special GMR IDs, allowing SVGAGuestPtrs to point to framebuffer + * memory as well. In the future, these IDs could even be used to + * allow legacy memory regions to be redefined by the guest as GMRs. + * + * Using the guest framebuffer (GFB) at BAR1 for general purpose DMA + * is being phased out. Please try to use user-defined GMRs whenever + * possible. + */ +#define SVGA_GMR_NULL ((uint32) -1) +#define SVGA_GMR_FRAMEBUFFER ((uint32) -2) // Guest Framebuffer (GFB) + +typedef +struct SVGAGuestMemDescriptor { + uint32 ppn; + uint32 numPages; +} SVGAGuestMemDescriptor; + +typedef +struct SVGAGuestPtr { + uint32 gmrId; + uint32 offset; +} SVGAGuestPtr; /* - * Raster op codes (same encoding as X) used by FIFO drivers. + * SVGAGMRImageFormat -- + * + * This is a packed representation of the source 2D image format + * for a GMR-to-screen blit. Currently it is defined as an encoding + * of the screen's color depth and bits-per-pixel, however, 16 bits + * are reserved for future use to identify other encodings (such as + * RGBA or higher-precision images). + * + * Currently supported formats: + * + * bpp depth Format Name + * --- ----- ----------- + * 32 24 32-bit BGRX + * 24 24 24-bit BGR + * 16 16 RGB 5-6-5 + * 16 15 RGB 5-5-5 + * */ -#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 +typedef +struct SVGAGMRImageFormat { + union { + struct { + uint32 bitsPerPixel : 8; + uint32 colorDepth : 8; + uint32 reserved : 16; // Must be zero + }; -#define SVGA_NUM_SUPPORTED_ROPS 16 -#define SVGA_ROP_ALL (MASK(SVGA_NUM_SUPPORTED_ROPS)) -#define SVGA_IS_VALID_ROP(rop) (rop < SVGA_NUM_SUPPORTED_ROPS) + uint32 value; + }; +} SVGAGMRImageFormat; + +/* + * SVGAColorBGRX -- + * + * A 24-bit color format (BGRX), which does not depend on the + * format of the legacy guest framebuffer (GFB) or the current + * GMRFB state. + */ + +typedef +struct SVGAColorBGRX { + union { + struct { + uint32 b : 8; + uint32 g : 8; + uint32 r : 8; + uint32 x : 8; // Unused + }; + + uint32 value; + }; +} SVGAColorBGRX; -#define SVGA_INVALID_DISPLAY_ID ((uint32)-1) /* - * 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) + * SVGASignedRect -- + * SVGASignedPoint -- + * + * Signed rectangle and point primitives. These are used by the new + * 2D primitives for drawing to Screen Objects, which can occupy a + * signed virtual coordinate space. + * + * SVGASignedRect specifies a half-open interval: the (left, top) + * pixel is part of the rectangle, but the (right, bottom) pixel is + * not. + */ + +typedef +struct SVGASignedRect { + int32 left; + int32 top; + int32 right; + int32 bottom; +} SVGASignedRect; + +typedef +struct SVGASignedPoint { + int32 x; + int32 y; +} SVGASignedPoint; + + +/* + * Capabilities + * + * Note the holes in the bitfield. Missing bits have been deprecated, + * and must not be reused. Those capabilities will never be reported + * by new versions of the SVGA device. + */ + +#define SVGA_CAP_NONE 0x00000000 +#define SVGA_CAP_RECT_COPY 0x00000002 +#define SVGA_CAP_CURSOR 0x00000020 +#define SVGA_CAP_CURSOR_BYPASS 0x00000040 // Legacy (Use Cursor Bypass 3 instead) +#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 // Legacy (Use Cursor Bypass 3 instead) +#define SVGA_CAP_8BIT_EMULATION 0x00000100 +#define SVGA_CAP_ALPHA_CURSOR 0x00000200 +#define SVGA_CAP_3D 0x00004000 +#define SVGA_CAP_EXTENDED_FIFO 0x00008000 +#define SVGA_CAP_MULTIMON 0x00010000 // Legacy multi-monitor support +#define SVGA_CAP_PITCHLOCK 0x00020000 +#define SVGA_CAP_IRQMASK 0x00040000 +#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 // Legacy multi-monitor support +#define SVGA_CAP_GMR 0x00100000 +#define SVGA_CAP_TRACES 0x00200000 /* @@ -320,7 +442,7 @@ enum { SVGA_FIFO_CAPABILITIES = 4, SVGA_FIFO_FLAGS, - /* Valid with SVGA_FIFO_CAP_FENCE: */ + // Valid with SVGA_FIFO_CAP_FENCE: SVGA_FIFO_FENCE, /* @@ -332,19 +454,33 @@ enum { * These in block 3a, the VMX currently considers mandatory for the * extended FIFO. */ - - /* Valid if exists (i.e. if extended FIFO enabled): */ + + // Valid if exists (i.e. if extended FIFO enabled): SVGA_FIFO_3D_HWVERSION, /* See SVGA3dHardwareVersion in svga3d_reg.h */ - /* Valid with SVGA_FIFO_CAP_PITCHLOCK: */ + // Valid with SVGA_FIFO_CAP_PITCHLOCK: SVGA_FIFO_PITCHLOCK, - /* Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: */ + + // Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: SVGA_FIFO_CURSOR_ON, /* Cursor bypass 3 show/hide register */ SVGA_FIFO_CURSOR_X, /* Cursor bypass 3 x register */ SVGA_FIFO_CURSOR_Y, /* Cursor bypass 3 y register */ SVGA_FIFO_CURSOR_COUNT, /* Incremented when any of the other 3 change */ SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */ - /* Valid with SVGA_FIFO_CAP_RESERVE: */ + + // Valid with SVGA_FIFO_CAP_RESERVE: SVGA_FIFO_RESERVED, /* Bytes past NEXT_CMD with real contents */ + + /* + * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT: + * + * By default this is SVGA_ID_INVALID, to indicate that the cursor + * coordinates are specified relative to the virtual root. If this + * is set to a specific screen ID, cursor position is reinterpreted + * as a signed offset relative to that screen's origin. This is the + * only way to place the cursor on a non-rooted screen. + */ + SVGA_FIFO_CURSOR_SCREEN_ID, + /* * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new * registers, but this must be done carefully and with judicious use of @@ -361,6 +497,7 @@ enum { * before 3D_CAPS, needs to reason about something other than * SVGA_FIFO_MIN. */ + /* * 3D caps block space; valid with 3D hardware version >= * SVGA3D_HWVERSION_WS6_B1. @@ -382,7 +519,7 @@ enum { * sets SVGA_FIFO_MIN high enough to leave room for them. */ - /* Valid if register exists: */ + // Valid if register exists: SVGA_FIFO_GUEST_3D_HWVERSION, /* Guest driver's 3D version */ SVGA_FIFO_FENCE_GOAL, /* Matching target for SVGA_IRQFLAG_FENCE_GOAL */ SVGA_FIFO_BUSY, /* See "FIFO Synchronization Registers" */ @@ -533,6 +670,56 @@ enum { * Pitch Lock -- Pitch lock register is supported * Video -- SVGA Video overlay units are supported * Escape -- Escape command is supported + * + * XXX: Add longer descriptions for each capability, including a list + * of the new features that each capability provides. + * + * SVGA_FIFO_CAP_SCREEN_OBJECT -- + * + * Provides dynamic multi-screen rendering, for improved Unity and + * multi-monitor modes. With Screen Object, the guest can + * dynamically create and destroy 'screens', which can represent + * Unity windows or virtual monitors. Screen Object also provides + * strong guarantees that DMA operations happen only when + * guest-initiated. Screen Object deprecates the BAR1 guest + * framebuffer (GFB) and all commands that work only with the GFB. + * + * New registers: + * FIFO_CURSOR_SCREEN_ID, VIDEO_DATA_GMRID, VIDEO_DST_SCREEN_ID + * + * New 2D commands: + * DEFINE_SCREEN, DESTROY_SCREEN, DEFINE_GMRFB, BLIT_GMRFB_TO_SCREEN, + * BLIT_SCREEN_TO_GMRFB, ANNOTATION_FILL, ANNOTATION_COPY + * + * New 3D commands: + * BLIT_SURFACE_TO_SCREEN + * + * New guarantees: + * + * - The host will not read or write guest memory, including the GFB, + * except when explicitly initiated by a DMA command. + * + * - All DMA, including legacy DMA like UPDATE and PRESENT_READBACK, + * is guaranteed to complete before any subsequent FENCEs. + * + * - All legacy commands which affect a Screen (UPDATE, PRESENT, + * PRESENT_READBACK) as well as new Screen blit commands will + * all behave consistently as blits, and memory will be read + * or written in FIFO order. + * + * For example, if you PRESENT from one SVGA3D surface to multiple + * places on the screen, the data copied will always be from the + * SVGA3D surface at the time the PRESENT was issued in the FIFO. + * This was not necessarily true on devices without Screen Object. + * + * This means that on devices that support Screen Object, the + * PRESENT_READBACK command should not be necessary unless you + * actually want to read back the results of 3D rendering into + * system memory. (And for that, the BLIT_SCREEN_TO_GMRFB + * command provides a strict superset of functionality.) + * + * - When a screen is resized, either using Screen Object commands or + * legacy multimon registers, its contents are preserved. */ #define SVGA_FIFO_CAP_NONE 0 @@ -543,6 +730,7 @@ enum { #define SVGA_FIFO_CAP_CURSOR_BYPASS_3 (1<<4) #define SVGA_FIFO_CAP_ESCAPE (1<<5) #define SVGA_FIFO_CAP_RESERVE (1<<6) +#define SVGA_FIFO_CAP_SCREEN_OBJECT (1<<7) /* @@ -553,7 +741,7 @@ enum { #define SVGA_FIFO_FLAG_NONE 0 #define SVGA_FIFO_FLAG_ACCELFRONT (1<<0) -#define SVGA_FIFO_FLAG_RESERVED (1<<31) /* Internal use only */ +#define SVGA_FIFO_FLAG_RESERVED (1<<31) // Internal use only /* * FIFO reservation sentinel value @@ -586,20 +774,22 @@ enum { SVGA_VIDEO_DATA_OFFSET, SVGA_VIDEO_FORMAT, SVGA_VIDEO_COLORKEY, - SVGA_VIDEO_SIZE, + SVGA_VIDEO_SIZE, // Deprecated SVGA_VIDEO_WIDTH, SVGA_VIDEO_HEIGHT, SVGA_VIDEO_SRC_X, SVGA_VIDEO_SRC_Y, SVGA_VIDEO_SRC_WIDTH, SVGA_VIDEO_SRC_HEIGHT, - SVGA_VIDEO_DST_X, - SVGA_VIDEO_DST_Y, + SVGA_VIDEO_DST_X, // Signed int32 + SVGA_VIDEO_DST_Y, // Signed int32 SVGA_VIDEO_DST_WIDTH, SVGA_VIDEO_DST_HEIGHT, SVGA_VIDEO_PITCH_1, SVGA_VIDEO_PITCH_2, SVGA_VIDEO_PITCH_3, + SVGA_VIDEO_DATA_GMRID, // Optional, defaults to SVGA_GMR_FRAMEBUFFER + SVGA_VIDEO_DST_SCREEN_ID, // Optional, defaults to virtual coords (SVGA_ID_INVALID) SVGA_VIDEO_NUM_REGS }; @@ -625,242 +815,545 @@ typedef struct SVGAOverlayUnit { uint32 srcY; uint32 srcWidth; uint32 srcHeight; - uint32 dstX; - uint32 dstY; + int32 dstX; + int32 dstY; uint32 dstWidth; uint32 dstHeight; uint32 pitches[3]; + uint32 dataGMRId; + uint32 dstScreenId; } SVGAOverlayUnit; /* - * Drawing object ID's, in the range 0 to SVGA_MAX_ID + * SVGAScreenObject -- + * + * This is a new way to represent a guest's multi-monitor screen or + * Unity window. Screen objects are only supported if the + * SVGA_FIFO_CAP_SCREEN_OBJECT capability bit is set. + * + * If Screen Objects are supported, they can be used to fully + * replace the functionality provided by the framebuffer registers + * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY. + * + * The screen object is a struct with guaranteed binary + * compatibility. New flags can be added, and the struct may grow, + * but existing fields must retain their meaning. + * */ -#define SVGA_MAX_ID 499 +#define SVGA_SCREEN_HAS_ROOT (1 << 0) // Screen is present in the virtual coord space +#define SVGA_SCREEN_IS_PRIMARY (1 << 1) // Guest considers this screen to be 'primary' +#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) // Guest is running a fullscreen app here + +typedef +struct SVGAScreenObject { + uint32 structSize; // sizeof(SVGAScreenObject) + uint32 id; + uint32 flags; + struct { + uint32 width; + uint32 height; + } size; + struct { + int32 x; + int32 y; + } root; // Only used if SVGA_SCREEN_HAS_ROOT is set. +} SVGAScreenObject; + /* - * Macros to compute variable length items (sizes in 32-bit words, except - * for SVGA_GLYPH_SCANLINE_SIZE, which is in bytes). + * Commands in the command FIFO: + * + * Command IDs defined below are used for the traditional 2D FIFO + * communication (not all commands are available for all versions of the + * SVGA FIFO protocol). + * + * Note the holes in the command ID numbers: These commands have been + * deprecated, and the old IDs must not be reused. + * + * Command IDs from 1000 to 1999 are reserved for use by the SVGA3D + * protocol. + * + * Each command's parameters are described by the comments and + * structs below. */ -#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) -#define SVGA_ESCAPE_SIZE(s) (((s) + 3) >> 2) +typedef enum { + SVGA_CMD_INVALID_CMD = 0, + SVGA_CMD_UPDATE = 1, + SVGA_CMD_RECT_COPY = 3, + SVGA_CMD_DEFINE_CURSOR = 19, + SVGA_CMD_DEFINE_ALPHA_CURSOR = 22, + SVGA_CMD_UPDATE_VERBOSE = 25, + SVGA_CMD_FRONT_ROP_FILL = 29, + SVGA_CMD_FENCE = 30, + SVGA_CMD_ESCAPE = 33, + SVGA_CMD_DEFINE_SCREEN = 34, + SVGA_CMD_DESTROY_SCREEN = 35, + SVGA_CMD_DEFINE_GMRFB = 36, + SVGA_CMD_BLIT_GMRFB_TO_SCREEN = 37, + SVGA_CMD_BLIT_SCREEN_TO_GMRFB = 38, + SVGA_CMD_ANNOTATION_FILL = 39, + SVGA_CMD_ANNOTATION_COPY = 40, + SVGA_CMD_MAX +} SVGAFifoCmdId; + +#define SVGA_CMD_MAX_ARGS 64 + /* - * Increment from one scanline to the next of a bitmap or pixmap + * SVGA_CMD_UPDATE -- + * + * This is a DMA transfer which copies from the Guest Framebuffer + * (GFB) at BAR1 + SVGA_REG_FB_OFFSET to any screens which + * intersect with the provided virtual rectangle. + * + * This command does not support using arbitrary guest memory as a + * data source- it only works with the pre-defined GFB memory. + * This command also does not support signed virtual coordinates. + * If you have defined screens (using SVGA_CMD_DEFINE_SCREEN) with + * negative root x/y coordinates, the negative portion of those + * screens will not be reachable by this command. + * + * This command is not necessary when using framebuffer + * traces. Traces are automatically enabled if the SVGA FIFO is + * disabled, and you may explicitly enable/disable traces using + * SVGA_REG_TRACES. With traces enabled, any write to the GFB will + * automatically act as if a subsequent SVGA_CMD_UPDATE was issued. + * + * Traces and SVGA_CMD_UPDATE are the only supported ways to render + * pseudocolor screen updates. The newer Screen Object commands + * only support true color formats. + * + * Availability: + * Always available. */ -#define SVGA_BITMAP_INCREMENT(w) ((( (w)+31 ) >> 5) * sizeof (uint32)) -#define SVGA_PIXMAP_INCREMENT(w,bpp) ((( ((w)*(bpp))+31 ) >> 5) * sizeof (uint32)) + +typedef +struct { + uint32 x; + uint32 y; + uint32 width; + uint32 height; +} SVGAFifoCmdUpdate; + /* - * Transparent color for DRAW_GLYPH_CLIPPED + * SVGA_CMD_RECT_COPY -- + * + * Perform a rectangular DMA transfer from one area of the GFB to + * another, and copy the result to any screens which intersect it. + * + * Availability: + * SVGA_CAP_RECT_COPY */ -#define SVGA_COLOR_TRANSPARENT (~0) + +typedef +struct { + uint32 srcX; + uint32 srcY; + uint32 destX; + uint32 destY; + uint32 width; + uint32 height; +} SVGAFifoCmdRectCopy; + /* - * Commands in the command FIFO + * SVGA_CMD_DEFINE_CURSOR -- + * + * Provide a new cursor image, as an AND/XOR mask. + * + * The recommended way to position the cursor overlay is by using + * the SVGA_FIFO_CURSOR_* registers, supported by the + * SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability. + * + * Availability: + * SVGA_CAP_CURSOR */ -#define SVGA_CMD_INVALID_CMD 0 - /* FIFO layout: - (well, undefined) */ +typedef +struct { + uint32 id; // Reserved, must be zero. + uint32 hotspotX; + uint32 hotspotY; + uint32 width; + uint32 height; + uint32 andMaskDepth; // Value must be 1 or equal to BITS_PER_PIXEL + uint32 xorMaskDepth; // Value must be 1 or equal to BITS_PER_PIXEL + /* + * Followed by scanline data for AND mask, then XOR mask. + * Each scanline is padded to a 32-bit boundary. + */ +} SVGAFifoCmdDefineCursor; + + +/* + * SVGA_CMD_DEFINE_ALPHA_CURSOR -- + * + * Provide a new cursor image, in 32-bit BGRA format. + * + * The recommended way to position the cursor overlay is by using + * the SVGA_FIFO_CURSOR_* registers, supported by the + * SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability. + * + * Availability: + * SVGA_CAP_ALPHA_CURSOR + */ + +typedef +struct { + uint32 id; // Reserved, must be zero. + uint32 hotspotX; + uint32 hotspotY; + uint32 width; + uint32 height; + /* Followed by scanline data */ +} SVGAFifoCmdDefineAlphaCursor; + + +/* + * SVGA_CMD_UPDATE_VERBOSE -- + * + * Just like SVGA_CMD_UPDATE, but also provide a per-rectangle + * 'reason' value, an opaque cookie which is used by internal + * debugging tools. Third party drivers should not use this + * command. + * + * Availability: + * SVGA_CAP_EXTENDED_FIFO + */ + +typedef +struct { + uint32 x; + uint32 y; + uint32 width; + uint32 height; + uint32 reason; +} SVGAFifoCmdUpdateVerbose; + + +/* + * SVGA_CMD_FRONT_ROP_FILL -- + * + * This is a hint which tells the SVGA device that the driver has + * just filled a rectangular region of the GFB with a solid + * color. Instead of reading these pixels from the GFB, the device + * can assume that they all equal 'color'. This is primarily used + * for remote desktop protocols. + * + * Availability: + * SVGA_FIFO_CAP_ACCELFRONT + */ + +#define SVGA_ROP_COPY 0x03 + +#define SVGA_INVALID_DISPLAY_ID ((uint32)-1) + +typedef +struct { + uint32 color; // In the same format as the GFB + uint32 x; + uint32 y; + uint32 width; + uint32 height; + uint32 rop; // Must be SVGA_ROP_COPY +} SVGAFifoCmdFrontRopFill; + + +/* + * SVGA_CMD_FENCE -- + * + * Insert a synchronization fence. When the SVGA device reaches + * this command, it will copy the 'fence' value into the + * SVGA_FIFO_FENCE register. It will also compare the fence against + * SVGA_FIFO_FENCE_GOAL. If the fence matches the goal and the + * SVGA_IRQFLAG_FENCE_GOAL interrupt is enabled, the device will + * raise this interrupt. + * + * Availability: + * SVGA_FIFO_FENCE for this command, + * SVGA_CAP_IRQMASK for SVGA_FIFO_FENCE_GOAL. + */ -#define SVGA_CMD_UPDATE 1 - /* FIFO layout: - X, Y, Width, Height */ +typedef +struct { + uint32 fence; +} SVGAFifoCmdFence; -#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 */ +/* + * SVGA_CMD_ESCAPE -- + * + * Send an extended or vendor-specific variable length command. + * This is used for video overlay, third party plugins, and + * internal debugging tools. See svga_escape.h + * + * Availability: + * SVGA_FIFO_CAP_ESCAPE + */ -#define SVGA_CMD_DEFINE_BITMAP 4 - /* FIFO layout: - Pixmap ID, Width, Height, */ +typedef +struct { + uint32 nsid; + uint32 size; + /* followed by 'size' bytes of data */ +} SVGAFifoCmdEscape; -#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, */ +/* + * SVGA_CMD_DEFINE_SCREEN -- + * + * Define or redefine an SVGAScreenObject. See the description of + * SVGAScreenObject above. The video driver is responsible for + * generating new screen IDs. They should be small positive + * integers. The virtual device will have an implementation + * specific upper limit on the number of screen IDs + * supported. Drivers are responsible for recycling IDs. The first + * valid ID is zero. + * + * - Interaction with other registers: + * + * For backwards compatibility, when the GFB mode registers (WIDTH, + * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device + * deletes all screens other than screen #0, and redefines screen + * #0 according to the specified mode. Drivers that use + * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0. + * + * If you use screen objects, do not use the legacy multi-mon + * registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*). + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT + */ -#define SVGA_CMD_DEFINE_PIXMAP_SCANLINE 7 - /* FIFO layout: - Pixmap ID, Width, Height, Depth, Line #, scanline */ +typedef +struct { + SVGAScreenObject screen; // Variable-length according to version +} SVGAFifoCmdDefineScreen; -#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 */ +/* + * SVGA_CMD_DESTROY_SCREEN -- + * + * Destroy an SVGAScreenObject. Its ID is immediately available for + * re-use. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT + */ -#define SVGA_CMD_RECT_BITMAP_COPY 10 - /* FIFO layout: - Bitmap ID, Source X, Source Y, Dest X, Dest Y, - Width, Height, Foreground, Background */ +typedef +struct { + uint32 screenId; +} SVGAFifoCmdDestroyScreen; -#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 */ +/* + * SVGA_CMD_DEFINE_GMRFB -- + * + * This command sets a piece of SVGA device state called the + * Guest Memory Region Framebuffer, or GMRFB. The GMRFB is a + * piece of light-weight state which identifies the location and + * format of an image in guest memory or in BAR1. The GMRFB has + * an arbitrary size, and it doesn't need to match the geometry + * of the GFB or any screen object. + * + * The GMRFB can be redefined as often as you like. You could + * always use the same GMRFB, you could redefine it before + * rendering from a different guest screen, or you could even + * redefine it before every blit. + * + * There are multiple ways to use this command. The simplest way is + * to use it to move the framebuffer either to elsewhere in the GFB + * (BAR1) memory region, or to a user-defined GMR. This lets a + * driver use a framebuffer allocated entirely out of normal system + * memory, which we encourage. + * + * Another way to use this command is to set up a ring buffer of + * updates in GFB memory. If a driver wants to ensure that no + * frames are skipped by the SVGA device, it is important that the + * driver not modify the source data for a blit until the device is + * done processing the command. One efficient way to accomplish + * this is to use a ring of small DMA buffers. Each buffer is used + * for one blit, then we move on to the next buffer in the + * ring. The FENCE mechanism is used to protect each buffer from + * re-use until the device is finished with that buffer's + * corresponding blit. + * + * This command does not affect the meaning of SVGA_CMD_UPDATE. + * UPDATEs always occur from the legacy GFB memory area. This + * command has no support for pseudocolor GMRFBs. Currently only + * true-color 15, 16, and 24-bit depths are supported. Future + * devices may expose capabilities for additional framebuffer + * formats. + * + * The default GMRFB value is undefined. Drivers must always send + * this command at least once before performing any blit from the + * GMRFB. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT + */ -#define SVGA_CMD_RECT_ROP_FILL 13 - /* FIFO layout: - Color, X, Y, Width, Height, ROP */ +typedef +struct { + SVGAGuestPtr ptr; + uint32 bytesPerLine; + SVGAGMRImageFormat format; +} SVGAFifoCmdDefineGMRFB; -#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 */ +/* + * SVGA_CMD_BLIT_GMRFB_TO_SCREEN -- + * + * This is a guest-to-host blit. It performs a DMA operation to + * copy a rectangular region of pixels from the current GMRFB to + * one or more Screen Objects. + * + * The destination coordinate may be specified relative to a + * screen's origin (if a screen ID is specified) or relative to the + * virtual coordinate system's origin (if the screen ID is + * SVGA_ID_INVALID). The actual destination may span zero or more + * screens, in the case of a virtual destination rect or a rect + * which extends off the edge of the specified screen. + * + * This command writes to the screen's "base layer": the underlying + * framebuffer which exists below any cursor or video overlays. No + * action is necessary to explicitly hide or update any overlays + * which exist on top of the updated region. + * + * The SVGA device is guaranteed to finish reading from the GMRFB + * by the time any subsequent FENCE commands are reached. + * + * This command consumes an annotation. See the + * SVGA_CMD_ANNOTATION_* commands for details. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT + */ -#define SVGA_CMD_RECT_ROP_PIXMAP_FILL 16 - /* FIFO layout: - ID, X, Y, Width, Height, ROP */ +typedef +struct { + SVGASignedPoint srcOrigin; + SVGASignedRect destRect; + uint32 destScreenId; +} SVGAFifoCmdBlitGMRFBToScreen; -#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 */ +/* + * SVGA_CMD_BLIT_SCREEN_TO_GMRFB -- + * + * This is a host-to-guest blit. It performs a DMA operation to + * copy a rectangular region of pixels from a single Screen Object + * back to the current GMRFB. + * + * Usage note: This command should be used rarely. It will + * typically be inefficient, but it is necessary for some types of + * synchronization between 3D (GPU) and 2D (CPU) rendering into + * overlapping areas of a screen. + * + * The source coordinate is specified relative to a screen's + * origin. The provided screen ID must be valid. If any parameters + * are invalid, the resulting pixel values are undefined. + * + * This command reads the screen's "base layer". Overlays like + * video and cursor are not included, but any data which was sent + * using a blit-to-screen primitive will be available, no matter + * whether the data's original source was the GMRFB or the 3D + * acceleration hardware. + * + * Note that our guest-to-host blits and host-to-guest blits aren't + * symmetric in their current implementation. While the parameters + * are identical, host-to-guest blits are a lot less featureful. + * They do not support clipping: If the source parameters don't + * fully fit within a screen, the blit fails. They must originate + * from exactly one screen. Virtual coordinates are not directly + * supported. + * + * Host-to-guest blits do support the same set of GMRFB formats + * offered by guest-to-host blits. + * + * The SVGA device is guaranteed to finish writing to the GMRFB by + * the time any subsequent FENCE commands are reached. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT + */ -#define SVGA_CMD_DEFINE_CURSOR 19 - /* FIFO layout: - ID, Hotspot X, Hotspot Y, Width, Height, - Depth for AND mask, Depth for XOR mask, - , */ +typedef +struct { + SVGASignedPoint destOrigin; + SVGASignedRect srcRect; + uint32 srcScreenId; +} SVGAFifoCmdBlitScreenToGMRFB; -#define SVGA_CMD_DISPLAY_CURSOR 20 - /* FIFO layout: - ID, On/Off (1 or 0) */ -#define SVGA_CMD_MOVE_CURSOR 21 - /* FIFO layout: - X, Y */ +/* + * SVGA_CMD_ANNOTATION_FILL -- + * + * This is a blit annotation. This command stores a small piece of + * device state which is consumed by the next blit-to-screen + * command. The state is only cleared by commands which are + * specifically documented as consuming an annotation. Other + * commands (such as ESCAPEs for debugging) may intervene between + * the annotation and its associated blit. + * + * This annotation is a promise about the contents of the next + * blit: The video driver is guaranteeing that all pixels in that + * blit will have the same value, specified here as a color in + * SVGAColorBGRX format. + * + * The SVGA device can still render the blit correctly even if it + * ignores this annotation, but the annotation may allow it to + * perform the blit more efficiently, for example by ignoring the + * source data and performing a fill in hardware. + * + * This annotation is most important for performance when the + * user's display is being remoted over a network connection. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT + */ -#define SVGA_CMD_DEFINE_ALPHA_CURSOR 22 - /* FIFO layout: - ID, Hotspot X, Hotspot Y, Width, Height, - */ +typedef +struct { + SVGAColorBGRX color; +} SVGAFifoCmdAnnotationFill; -#define SVGA_CMD_DRAW_GLYPH 23 - /* FIFO layout: - X, Y, W, H, FGCOLOR, */ - -#define SVGA_CMD_DRAW_GLYPH_CLIPPED 24 - /* FIFO layout: - X, Y, W, H, FGCOLOR, BGCOLOR, , - 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_FRONT_ROP_FILL 29 - /* FIFO layout: - Color, X, Y, Width, Height, ROP */ - -#define SVGA_CMD_FENCE 30 - /* FIFO layout: - Fence value */ - -#define SVGA_CMD_VIDEO_PLAY_OBSOLETE 31 - /* Obsolete; do not use. */ - -#define SVGA_CMD_VIDEO_END_OBSOLETE 32 - /* Obsolete; do not use. */ - -#define SVGA_CMD_ESCAPE 33 - /* FIFO layout: - Namespace ID, size(bytes), data */ - -#define SVGA_CMD_MAX 34 - -#define SVGA_CMD_MAX_ARGS 64 - -/* - * Location and size of SVGA frame buffer and the FIFO. - */ -#define SVGA_VRAM_MIN_SIZE (4 * 640 * 480) /* bytes */ -#define SVGA_VRAM_MAX_SIZE (128 * 1024 * 1024) - -#define SVGA_VRAM_SIZE_WS (16 * 1024 * 1024) /* 16 MB */ -#define SVGA_MEM_SIZE_WS (2 * 1024 * 1024) /* 2 MB */ -#define SVGA_VRAM_SIZE_SERVER (4 * 1024 * 1024) /* 4 MB */ -#define SVGA_MEM_SIZE_SERVER (256 * 1024) /* 256 KB */ - -#if /* defined(VMX86_WGS) || */ defined(VMX86_SERVER) -#define SVGA_VRAM_SIZE SVGA_VRAM_SIZE_SERVER -#define SVGA_MEM_SIZE SVGA_MEM_SIZE_SERVER -#else -#define SVGA_VRAM_SIZE SVGA_VRAM_SIZE_WS -#define SVGA_MEM_SIZE SVGA_MEM_SIZE_WS -#endif /* - * 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 + * SVGA_CMD_ANNOTATION_COPY -- + * + * This is a blit annotation. See SVGA_CMD_ANNOTATION_FILL for more + * information about annotations. + * + * This annotation is a promise about the contents of the next + * blit: The video driver is guaranteeing that all pixels in that + * blit will have the same value as those which already exist at an + * identically-sized region on the same or a different screen. + * + * Note that the source pixels for the COPY in this annotation are + * sampled before applying the anqnotation's associated blit. They + * are allowed to overlap with the blit's destination pixels. + * + * The copy source rectangle is specified the same way as the blit + * destination: it can be a rectangle which spans zero or more + * screens, specified relative to either a screen or to the virtual + * coordinate system's origin. If the source rectangle includes + * pixels which are not from exactly one screen, the results are + * undefined. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT + */ + +typedef +struct { + SVGASignedPoint srcOrigin; + uint32 srcScreenId; +} SVGAFifoCmdAnnotationCopy; #endif diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am new file mode 100644 index 0000000..5efa8cd --- /dev/null +++ b/vmwgfx/Makefile.am @@ -0,0 +1,24 @@ +vmwgfx_drv_la_LTLIBRARIES = vmwgfx_drv.la +vmwgfx_drv_la_LDFLAGS = -module -avoid-version +vmwgfx_drv_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) @LIBDRM_CFLAGS@ -I$(top_srcdir)/src -I$(top_srcdir)/saa +vmwgfx_drv_la_LIBADD = @LIBDRM_LIBS@ $(top_srcdir)/saa/.libs/libsaa.la -lxatracker +vmwgfx_drv_ladir = @moduledir@/drivers + +vmwgfx_drv_la_SOURCES = \ + vmwgfx_driver.c \ + vmwgfx_driver.h \ + vmwgfx_crtc.c \ + vmwgfx_output.c \ + vmwgfx_dri2.c \ + vmwgfx_tex_video.c \ + vmwgfx_saa.c \ + vmwgfx_saa.h \ + vmwgfx_drmi.c \ + vmwgfx_drmi.h \ + vmwgfx_bootstrap.c \ + vmwgfx_overlay.c \ + vmwgfx_ctrl.c \ + vmwgfx_ctrl.h + + + diff --git a/vmwgfx/svga3d_reg.h b/vmwgfx/svga3d_reg.h new file mode 100644 index 0000000..a527d7d --- /dev/null +++ b/vmwgfx/svga3d_reg.h @@ -0,0 +1,1801 @@ +/********************************************************** + * Copyright 1998-2009 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + **********************************************************/ + +/* + * svga3d_reg.h -- + * + * SVGA 3D hardware definitions + */ + +#ifndef _SVGA3D_REG_H_ +#define _SVGA3D_REG_H_ + +#include "svga_reg.h" + + +/* + * 3D Hardware Version + * + * The hardware version is stored in the SVGA_FIFO_3D_HWVERSION fifo + * register. Is set by the host and read by the guest. This lets + * us make new guest drivers which are backwards-compatible with old + * SVGA hardware revisions. It does not let us support old guest + * drivers. Good enough for now. + * + */ + +#define SVGA3D_MAKE_HWVERSION(major, minor) (((major) << 16) | ((minor) & 0xFF)) +#define SVGA3D_MAJOR_HWVERSION(version) ((version) >> 16) +#define SVGA3D_MINOR_HWVERSION(version) ((version) & 0xFF) + +typedef enum { + SVGA3D_HWVERSION_WS5_RC1 = SVGA3D_MAKE_HWVERSION(0, 1), + SVGA3D_HWVERSION_WS5_RC2 = SVGA3D_MAKE_HWVERSION(0, 2), + SVGA3D_HWVERSION_WS51_RC1 = SVGA3D_MAKE_HWVERSION(0, 3), + SVGA3D_HWVERSION_WS6_B1 = SVGA3D_MAKE_HWVERSION(1, 1), + SVGA3D_HWVERSION_FUSION_11 = SVGA3D_MAKE_HWVERSION(1, 4), + SVGA3D_HWVERSION_WS65_B1 = SVGA3D_MAKE_HWVERSION(2, 0), + SVGA3D_HWVERSION_CURRENT = SVGA3D_HWVERSION_WS65_B1, +} SVGA3dHardwareVersion; + +/* + * Generic Types + */ + +typedef uint32 SVGA3dBool; /* 32-bit Bool definition */ +#define SVGA3D_NUM_CLIPPLANES 6 +#define SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS 8 + + +/* + * Surface formats. + * + * If you modify this list, be sure to keep GLUtil.c in sync. It + * includes the internal format definition of each surface in + * GLUtil_ConvertSurfaceFormat, and it contains a table of + * human-readable names in GLUtil_GetFormatName. + */ + +typedef enum SVGA3dSurfaceFormat { + SVGA3D_FORMAT_INVALID = 0, + + SVGA3D_X8R8G8B8 = 1, + SVGA3D_A8R8G8B8 = 2, + + SVGA3D_R5G6B5 = 3, + SVGA3D_X1R5G5B5 = 4, + SVGA3D_A1R5G5B5 = 5, + SVGA3D_A4R4G4B4 = 6, + + SVGA3D_Z_D32 = 7, + SVGA3D_Z_D16 = 8, + SVGA3D_Z_D24S8 = 9, + SVGA3D_Z_D15S1 = 10, + + SVGA3D_LUMINANCE8 = 11, + SVGA3D_LUMINANCE4_ALPHA4 = 12, + SVGA3D_LUMINANCE16 = 13, + SVGA3D_LUMINANCE8_ALPHA8 = 14, + + SVGA3D_DXT1 = 15, + SVGA3D_DXT2 = 16, + SVGA3D_DXT3 = 17, + SVGA3D_DXT4 = 18, + SVGA3D_DXT5 = 19, + + SVGA3D_BUMPU8V8 = 20, + SVGA3D_BUMPL6V5U5 = 21, + SVGA3D_BUMPX8L8V8U8 = 22, + SVGA3D_BUMPL8V8U8 = 23, + + SVGA3D_ARGB_S10E5 = 24, /* 16-bit floating-point ARGB */ + SVGA3D_ARGB_S23E8 = 25, /* 32-bit floating-point ARGB */ + + SVGA3D_A2R10G10B10 = 26, + + /* signed formats */ + SVGA3D_V8U8 = 27, + SVGA3D_Q8W8V8U8 = 28, + SVGA3D_CxV8U8 = 29, + + /* mixed formats */ + SVGA3D_X8L8V8U8 = 30, + SVGA3D_A2W10V10U10 = 31, + + SVGA3D_ALPHA8 = 32, + + /* Single- and dual-component floating point formats */ + SVGA3D_R_S10E5 = 33, + SVGA3D_R_S23E8 = 34, + SVGA3D_RG_S10E5 = 35, + SVGA3D_RG_S23E8 = 36, + + /* + * Any surface can be used as a buffer object, but SVGA3D_BUFFER is + * the most efficient format to use when creating new surfaces + * expressly for index or vertex data. + */ + SVGA3D_BUFFER = 37, + + SVGA3D_Z_D24X8 = 38, + + SVGA3D_V16U16 = 39, + + SVGA3D_G16R16 = 40, + SVGA3D_A16B16G16R16 = 41, + + /* Packed Video formats */ + SVGA3D_UYVY = 42, + SVGA3D_YUY2 = 43, + + SVGA3D_FORMAT_MAX +} SVGA3dSurfaceFormat; + +typedef uint32 SVGA3dColor; /* a, r, g, b */ + +/* + * These match the D3DFORMAT_OP definitions used by Direct3D. We need + * them so that we can query the host for what the supported surface + * operations are (when we're using the D3D backend, in particular), + * and so we can send those operations to the guest. + */ +typedef enum { + SVGA3DFORMAT_OP_TEXTURE = 0x00000001, + SVGA3DFORMAT_OP_VOLUMETEXTURE = 0x00000002, + SVGA3DFORMAT_OP_CUBETEXTURE = 0x00000004, + SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET = 0x00000008, + SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET = 0x00000010, + SVGA3DFORMAT_OP_ZSTENCIL = 0x00000040, + SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH = 0x00000080, + +/* + * This format can be used as a render target if the current display mode + * is the same depth if the alpha channel is ignored. e.g. if the device + * can render to A8R8G8B8 when the display mode is X8R8G8B8, then the + * format op list entry for A8R8G8B8 should have this cap. + */ + SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET = 0x00000100, + +/* + * This format contains DirectDraw support (including Flip). This flag + * should not to be set on alpha formats. + */ + SVGA3DFORMAT_OP_DISPLAYMODE = 0x00000400, + +/* + * The rasterizer can support some level of Direct3D support in this format + * and implies that the driver can create a Context in this mode (for some + * render target format). When this flag is set, the SVGA3DFORMAT_OP_DISPLAYMODE + * flag must also be set. + */ + SVGA3DFORMAT_OP_3DACCELERATION = 0x00000800, + +/* + * This is set for a private format when the driver has put the bpp in + * the structure. + */ + SVGA3DFORMAT_OP_PIXELSIZE = 0x00001000, + +/* + * Indicates that this format can be converted to any RGB format for which + * SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB is specified + */ + SVGA3DFORMAT_OP_CONVERT_TO_ARGB = 0x00002000, + +/* + * Indicates that this format can be used to create offscreen plain surfaces. + */ + SVGA3DFORMAT_OP_OFFSCREENPLAIN = 0x00004000, + +/* + * Indicated that this format can be read as an SRGB texture (meaning that the + * sampler will linearize the looked up data) + */ + SVGA3DFORMAT_OP_SRGBREAD = 0x00008000, + +/* + * Indicates that this format can be used in the bumpmap instructions + */ + SVGA3DFORMAT_OP_BUMPMAP = 0x00010000, + +/* + * Indicates that this format can be sampled by the displacement map sampler + */ + SVGA3DFORMAT_OP_DMAP = 0x00020000, + +/* + * Indicates that this format cannot be used with texture filtering + */ + SVGA3DFORMAT_OP_NOFILTER = 0x00040000, + +/* + * Indicates that format conversions are supported to this RGB format if + * SVGA3DFORMAT_OP_CONVERT_TO_ARGB is specified in the source format. + */ + SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB = 0x00080000, + +/* + * Indicated that this format can be written as an SRGB target (meaning that the + * pixel pipe will DE-linearize data on output to format) + */ + SVGA3DFORMAT_OP_SRGBWRITE = 0x00100000, + +/* + * Indicates that this format cannot be used with alpha blending + */ + SVGA3DFORMAT_OP_NOALPHABLEND = 0x00200000, + +/* + * Indicates that the device can auto-generated sublevels for resources + * of this format + */ + SVGA3DFORMAT_OP_AUTOGENMIPMAP = 0x00400000, + +/* + * Indicates that this format can be used by vertex texture sampler + */ + SVGA3DFORMAT_OP_VERTEXTEXTURE = 0x00800000, + +/* + * Indicates that this format supports neither texture coordinate wrap + * modes, nor mipmapping + */ + SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP = 0x01000000 +} SVGA3dFormatOp; + +/* + * This structure is a conversion of SVGA3DFORMAT_OP_*. + * Entries must be located at the same position. + */ +typedef union { + uint32 value; + struct { + uint32 texture : 1; + uint32 volumeTexture : 1; + uint32 cubeTexture : 1; + uint32 offscreenRenderTarget : 1; + uint32 sameFormatRenderTarget : 1; + uint32 unknown1 : 1; + uint32 zStencil : 1; + uint32 zStencilArbitraryDepth : 1; + uint32 sameFormatUpToAlpha : 1; + uint32 unknown2 : 1; + uint32 displayMode : 1; + uint32 acceleration3d : 1; + uint32 pixelSize : 1; + uint32 convertToARGB : 1; + uint32 offscreenPlain : 1; + uint32 sRGBRead : 1; + uint32 bumpMap : 1; + uint32 dmap : 1; + uint32 noFilter : 1; + uint32 memberOfGroupARGB : 1; + uint32 sRGBWrite : 1; + uint32 noAlphaBlend : 1; + uint32 autoGenMipMap : 1; + uint32 vertexTexture : 1; + uint32 noTexCoordWrapNorMip : 1; + }; +} SVGA3dSurfaceFormatCaps; + +/* + * SVGA_3D_CMD_SETRENDERSTATE Types. All value types + * must fit in a uint32. + */ + +typedef enum { + SVGA3D_RS_INVALID = 0, + SVGA3D_RS_ZENABLE = 1, /* SVGA3dBool */ + SVGA3D_RS_ZWRITEENABLE = 2, /* SVGA3dBool */ + SVGA3D_RS_ALPHATESTENABLE = 3, /* SVGA3dBool */ + SVGA3D_RS_DITHERENABLE = 4, /* SVGA3dBool */ + SVGA3D_RS_BLENDENABLE = 5, /* SVGA3dBool */ + SVGA3D_RS_FOGENABLE = 6, /* SVGA3dBool */ + SVGA3D_RS_SPECULARENABLE = 7, /* SVGA3dBool */ + SVGA3D_RS_STENCILENABLE = 8, /* SVGA3dBool */ + SVGA3D_RS_LIGHTINGENABLE = 9, /* SVGA3dBool */ + SVGA3D_RS_NORMALIZENORMALS = 10, /* SVGA3dBool */ + SVGA3D_RS_POINTSPRITEENABLE = 11, /* SVGA3dBool */ + SVGA3D_RS_POINTSCALEENABLE = 12, /* SVGA3dBool */ + SVGA3D_RS_STENCILREF = 13, /* uint32 */ + SVGA3D_RS_STENCILMASK = 14, /* uint32 */ + SVGA3D_RS_STENCILWRITEMASK = 15, /* uint32 */ + SVGA3D_RS_FOGSTART = 16, /* float */ + SVGA3D_RS_FOGEND = 17, /* float */ + SVGA3D_RS_FOGDENSITY = 18, /* float */ + SVGA3D_RS_POINTSIZE = 19, /* float */ + SVGA3D_RS_POINTSIZEMIN = 20, /* float */ + SVGA3D_RS_POINTSIZEMAX = 21, /* float */ + SVGA3D_RS_POINTSCALE_A = 22, /* float */ + SVGA3D_RS_POINTSCALE_B = 23, /* float */ + SVGA3D_RS_POINTSCALE_C = 24, /* float */ + SVGA3D_RS_FOGCOLOR = 25, /* SVGA3dColor */ + SVGA3D_RS_AMBIENT = 26, /* SVGA3dColor */ + SVGA3D_RS_CLIPPLANEENABLE = 27, /* SVGA3dClipPlanes */ + SVGA3D_RS_FOGMODE = 28, /* SVGA3dFogMode */ + SVGA3D_RS_FILLMODE = 29, /* SVGA3dFillMode */ + SVGA3D_RS_SHADEMODE = 30, /* SVGA3dShadeMode */ + SVGA3D_RS_LINEPATTERN = 31, /* SVGA3dLinePattern */ + SVGA3D_RS_SRCBLEND = 32, /* SVGA3dBlendOp */ + SVGA3D_RS_DSTBLEND = 33, /* SVGA3dBlendOp */ + SVGA3D_RS_BLENDEQUATION = 34, /* SVGA3dBlendEquation */ + SVGA3D_RS_CULLMODE = 35, /* SVGA3dFace */ + SVGA3D_RS_ZFUNC = 36, /* SVGA3dCmpFunc */ + SVGA3D_RS_ALPHAFUNC = 37, /* SVGA3dCmpFunc */ + SVGA3D_RS_STENCILFUNC = 38, /* SVGA3dCmpFunc */ + SVGA3D_RS_STENCILFAIL = 39, /* SVGA3dStencilOp */ + SVGA3D_RS_STENCILZFAIL = 40, /* SVGA3dStencilOp */ + SVGA3D_RS_STENCILPASS = 41, /* SVGA3dStencilOp */ + SVGA3D_RS_ALPHAREF = 42, /* float (0.0 .. 1.0) */ + SVGA3D_RS_FRONTWINDING = 43, /* SVGA3dFrontWinding */ + SVGA3D_RS_COORDINATETYPE = 44, /* SVGA3dCoordinateType */ + SVGA3D_RS_ZBIAS = 45, /* float */ + SVGA3D_RS_RANGEFOGENABLE = 46, /* SVGA3dBool */ + SVGA3D_RS_COLORWRITEENABLE = 47, /* SVGA3dColorMask */ + SVGA3D_RS_VERTEXMATERIALENABLE = 48, /* SVGA3dBool */ + SVGA3D_RS_DIFFUSEMATERIALSOURCE = 49, /* SVGA3dVertexMaterial */ + SVGA3D_RS_SPECULARMATERIALSOURCE = 50, /* SVGA3dVertexMaterial */ + SVGA3D_RS_AMBIENTMATERIALSOURCE = 51, /* SVGA3dVertexMaterial */ + SVGA3D_RS_EMISSIVEMATERIALSOURCE = 52, /* SVGA3dVertexMaterial */ + SVGA3D_RS_TEXTUREFACTOR = 53, /* SVGA3dColor */ + SVGA3D_RS_LOCALVIEWER = 54, /* SVGA3dBool */ + SVGA3D_RS_SCISSORTESTENABLE = 55, /* SVGA3dBool */ + SVGA3D_RS_BLENDCOLOR = 56, /* SVGA3dColor */ + SVGA3D_RS_STENCILENABLE2SIDED = 57, /* SVGA3dBool */ + SVGA3D_RS_CCWSTENCILFUNC = 58, /* SVGA3dCmpFunc */ + SVGA3D_RS_CCWSTENCILFAIL = 59, /* SVGA3dStencilOp */ + SVGA3D_RS_CCWSTENCILZFAIL = 60, /* SVGA3dStencilOp */ + SVGA3D_RS_CCWSTENCILPASS = 61, /* SVGA3dStencilOp */ + SVGA3D_RS_VERTEXBLEND = 62, /* SVGA3dVertexBlendFlags */ + SVGA3D_RS_SLOPESCALEDEPTHBIAS = 63, /* float */ + SVGA3D_RS_DEPTHBIAS = 64, /* float */ + + + /* + * Output Gamma Level + * + * Output gamma effects the gamma curve of colors that are output from the + * rendering pipeline. A value of 1.0 specifies a linear color space. If the + * value is <= 0.0, gamma correction is ignored and linear color space is + * used. + */ + + SVGA3D_RS_OUTPUTGAMMA = 65, /* float */ + SVGA3D_RS_ZVISIBLE = 66, /* SVGA3dBool */ + SVGA3D_RS_LASTPIXEL = 67, /* SVGA3dBool */ + SVGA3D_RS_CLIPPING = 68, /* SVGA3dBool */ + SVGA3D_RS_WRAP0 = 69, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP1 = 70, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP2 = 71, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP3 = 72, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP4 = 73, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP5 = 74, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP6 = 75, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP7 = 76, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP8 = 77, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP9 = 78, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP10 = 79, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP11 = 80, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP12 = 81, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP13 = 82, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP14 = 83, /* SVGA3dWrapFlags */ + SVGA3D_RS_WRAP15 = 84, /* SVGA3dWrapFlags */ + SVGA3D_RS_MULTISAMPLEANTIALIAS = 85, /* SVGA3dBool */ + SVGA3D_RS_MULTISAMPLEMASK = 86, /* uint32 */ + SVGA3D_RS_INDEXEDVERTEXBLENDENABLE = 87, /* SVGA3dBool */ + SVGA3D_RS_TWEENFACTOR = 88, /* float */ + SVGA3D_RS_ANTIALIASEDLINEENABLE = 89, /* SVGA3dBool */ + SVGA3D_RS_COLORWRITEENABLE1 = 90, /* SVGA3dColorMask */ + SVGA3D_RS_COLORWRITEENABLE2 = 91, /* SVGA3dColorMask */ + SVGA3D_RS_COLORWRITEENABLE3 = 92, /* SVGA3dColorMask */ + SVGA3D_RS_SEPARATEALPHABLENDENABLE = 93, /* SVGA3dBool */ + SVGA3D_RS_SRCBLENDALPHA = 94, /* SVGA3dBlendOp */ + SVGA3D_RS_DSTBLENDALPHA = 95, /* SVGA3dBlendOp */ + SVGA3D_RS_BLENDEQUATIONALPHA = 96, /* SVGA3dBlendEquation */ + SVGA3D_RS_MAX +} SVGA3dRenderStateName; + +typedef enum { + SVGA3D_VERTEXMATERIAL_NONE = 0, /* Use the value in the current material */ + SVGA3D_VERTEXMATERIAL_DIFFUSE = 1, /* Use the value in the diffuse component */ + SVGA3D_VERTEXMATERIAL_SPECULAR = 2, /* Use the value in the specular component */ +} SVGA3dVertexMaterial; + +typedef enum { + SVGA3D_FILLMODE_INVALID = 0, + SVGA3D_FILLMODE_POINT = 1, + SVGA3D_FILLMODE_LINE = 2, + SVGA3D_FILLMODE_FILL = 3, + SVGA3D_FILLMODE_MAX +} SVGA3dFillModeType; + + +typedef +union { + struct { + uint16 mode; /* SVGA3dFillModeType */ + uint16 face; /* SVGA3dFace */ + }; + uint32 uintValue; +} SVGA3dFillMode; + +typedef enum { + SVGA3D_SHADEMODE_INVALID = 0, + SVGA3D_SHADEMODE_FLAT = 1, + SVGA3D_SHADEMODE_SMOOTH = 2, + SVGA3D_SHADEMODE_PHONG = 3, /* Not supported */ + SVGA3D_SHADEMODE_MAX +} SVGA3dShadeMode; + +typedef +union { + struct { + uint16 repeat; + uint16 pattern; + }; + uint32 uintValue; +} SVGA3dLinePattern; + +typedef enum { + SVGA3D_BLENDOP_INVALID = 0, + SVGA3D_BLENDOP_ZERO = 1, + SVGA3D_BLENDOP_ONE = 2, + SVGA3D_BLENDOP_SRCCOLOR = 3, + SVGA3D_BLENDOP_INVSRCCOLOR = 4, + SVGA3D_BLENDOP_SRCALPHA = 5, + SVGA3D_BLENDOP_INVSRCALPHA = 6, + SVGA3D_BLENDOP_DESTALPHA = 7, + SVGA3D_BLENDOP_INVDESTALPHA = 8, + SVGA3D_BLENDOP_DESTCOLOR = 9, + SVGA3D_BLENDOP_INVDESTCOLOR = 10, + SVGA3D_BLENDOP_SRCALPHASAT = 11, + SVGA3D_BLENDOP_BLENDFACTOR = 12, + SVGA3D_BLENDOP_INVBLENDFACTOR = 13, + SVGA3D_BLENDOP_MAX +} SVGA3dBlendOp; + +typedef enum { + SVGA3D_BLENDEQ_INVALID = 0, + SVGA3D_BLENDEQ_ADD = 1, + SVGA3D_BLENDEQ_SUBTRACT = 2, + SVGA3D_BLENDEQ_REVSUBTRACT = 3, + SVGA3D_BLENDEQ_MINIMUM = 4, + SVGA3D_BLENDEQ_MAXIMUM = 5, + SVGA3D_BLENDEQ_MAX +} SVGA3dBlendEquation; + +typedef enum { + SVGA3D_FRONTWINDING_INVALID = 0, + SVGA3D_FRONTWINDING_CW = 1, + SVGA3D_FRONTWINDING_CCW = 2, + SVGA3D_FRONTWINDING_MAX +} SVGA3dFrontWinding; + +typedef enum { + SVGA3D_FACE_INVALID = 0, + SVGA3D_FACE_NONE = 1, + SVGA3D_FACE_FRONT = 2, + SVGA3D_FACE_BACK = 3, + SVGA3D_FACE_FRONT_BACK = 4, + SVGA3D_FACE_MAX +} SVGA3dFace; + +/* + * The order and the values should not be changed + */ + +typedef enum { + SVGA3D_CMP_INVALID = 0, + SVGA3D_CMP_NEVER = 1, + SVGA3D_CMP_LESS = 2, + SVGA3D_CMP_EQUAL = 3, + SVGA3D_CMP_LESSEQUAL = 4, + SVGA3D_CMP_GREATER = 5, + SVGA3D_CMP_NOTEQUAL = 6, + SVGA3D_CMP_GREATEREQUAL = 7, + SVGA3D_CMP_ALWAYS = 8, + SVGA3D_CMP_MAX +} SVGA3dCmpFunc; + +/* + * SVGA3D_FOGFUNC_* specifies the fog equation, or PER_VERTEX which allows + * the fog factor to be specified in the alpha component of the specular + * (a.k.a. secondary) vertex color. + */ +typedef enum { + SVGA3D_FOGFUNC_INVALID = 0, + SVGA3D_FOGFUNC_EXP = 1, + SVGA3D_FOGFUNC_EXP2 = 2, + SVGA3D_FOGFUNC_LINEAR = 3, + SVGA3D_FOGFUNC_PER_VERTEX = 4 +} SVGA3dFogFunction; + +/* + * SVGA3D_FOGTYPE_* specifies if fog factors are computed on a per-vertex + * or per-pixel basis. + */ +typedef enum { + SVGA3D_FOGTYPE_INVALID = 0, + SVGA3D_FOGTYPE_VERTEX = 1, + SVGA3D_FOGTYPE_PIXEL = 2, + SVGA3D_FOGTYPE_MAX = 3 +} SVGA3dFogType; + +/* + * SVGA3D_FOGBASE_* selects depth or range-based fog. Depth-based fog is + * computed using the eye Z value of each pixel (or vertex), whereas range- + * based fog is computed using the actual distance (range) to the eye. + */ +typedef enum { + SVGA3D_FOGBASE_INVALID = 0, + SVGA3D_FOGBASE_DEPTHBASED = 1, + SVGA3D_FOGBASE_RANGEBASED = 2, + SVGA3D_FOGBASE_MAX = 3 +} SVGA3dFogBase; + +typedef enum { + SVGA3D_STENCILOP_INVALID = 0, + SVGA3D_STENCILOP_KEEP = 1, + SVGA3D_STENCILOP_ZERO = 2, + SVGA3D_STENCILOP_REPLACE = 3, + SVGA3D_STENCILOP_INCRSAT = 4, + SVGA3D_STENCILOP_DECRSAT = 5, + SVGA3D_STENCILOP_INVERT = 6, + SVGA3D_STENCILOP_INCR = 7, + SVGA3D_STENCILOP_DECR = 8, + SVGA3D_STENCILOP_MAX +} SVGA3dStencilOp; + +typedef enum { + SVGA3D_CLIPPLANE_0 = (1 << 0), + SVGA3D_CLIPPLANE_1 = (1 << 1), + SVGA3D_CLIPPLANE_2 = (1 << 2), + SVGA3D_CLIPPLANE_3 = (1 << 3), + SVGA3D_CLIPPLANE_4 = (1 << 4), + SVGA3D_CLIPPLANE_5 = (1 << 5), +} SVGA3dClipPlanes; + +typedef enum { + SVGA3D_CLEAR_COLOR = 0x1, + SVGA3D_CLEAR_DEPTH = 0x2, + SVGA3D_CLEAR_STENCIL = 0x4 +} SVGA3dClearFlag; + +typedef enum { + SVGA3D_RT_DEPTH = 0, + SVGA3D_RT_STENCIL = 1, + SVGA3D_RT_COLOR0 = 2, + SVGA3D_RT_COLOR1 = 3, + SVGA3D_RT_COLOR2 = 4, + SVGA3D_RT_COLOR3 = 5, + SVGA3D_RT_COLOR4 = 6, + SVGA3D_RT_COLOR5 = 7, + SVGA3D_RT_COLOR6 = 8, + SVGA3D_RT_COLOR7 = 9, + SVGA3D_RT_MAX, + SVGA3D_RT_INVALID = ((uint32)-1), +} SVGA3dRenderTargetType; + +#define SVGA3D_MAX_RT_COLOR (SVGA3D_RT_COLOR7 - SVGA3D_RT_COLOR0 + 1) + +typedef +union { + struct { + uint32 red : 1; + uint32 green : 1; + uint32 blue : 1; + uint32 alpha : 1; + }; + uint32 uintValue; +} SVGA3dColorMask; + +typedef enum { + SVGA3D_VBLEND_DISABLE = 0, + SVGA3D_VBLEND_1WEIGHT = 1, + SVGA3D_VBLEND_2WEIGHT = 2, + SVGA3D_VBLEND_3WEIGHT = 3, +} SVGA3dVertexBlendFlags; + +typedef enum { + SVGA3D_WRAPCOORD_0 = 1 << 0, + SVGA3D_WRAPCOORD_1 = 1 << 1, + SVGA3D_WRAPCOORD_2 = 1 << 2, + SVGA3D_WRAPCOORD_3 = 1 << 3, + SVGA3D_WRAPCOORD_ALL = 0xF, +} SVGA3dWrapFlags; + +/* + * SVGA_3D_CMD_TEXTURESTATE Types. All value types + * must fit in a uint32. + */ + +typedef enum { + SVGA3D_TS_INVALID = 0, + SVGA3D_TS_BIND_TEXTURE = 1, /* SVGA3dSurfaceId */ + SVGA3D_TS_COLOROP = 2, /* SVGA3dTextureCombiner */ + SVGA3D_TS_COLORARG1 = 3, /* SVGA3dTextureArgData */ + SVGA3D_TS_COLORARG2 = 4, /* SVGA3dTextureArgData */ + SVGA3D_TS_ALPHAOP = 5, /* SVGA3dTextureCombiner */ + SVGA3D_TS_ALPHAARG1 = 6, /* SVGA3dTextureArgData */ + SVGA3D_TS_ALPHAARG2 = 7, /* SVGA3dTextureArgData */ + SVGA3D_TS_ADDRESSU = 8, /* SVGA3dTextureAddress */ + SVGA3D_TS_ADDRESSV = 9, /* SVGA3dTextureAddress */ + SVGA3D_TS_MIPFILTER = 10, /* SVGA3dTextureFilter */ + SVGA3D_TS_MAGFILTER = 11, /* SVGA3dTextureFilter */ + SVGA3D_TS_MINFILTER = 12, /* SVGA3dTextureFilter */ + SVGA3D_TS_BORDERCOLOR = 13, /* SVGA3dColor */ + SVGA3D_TS_TEXCOORDINDEX = 14, /* uint32 */ + SVGA3D_TS_TEXTURETRANSFORMFLAGS = 15, /* SVGA3dTexTransformFlags */ + SVGA3D_TS_TEXCOORDGEN = 16, /* SVGA3dTextureCoordGen */ + SVGA3D_TS_BUMPENVMAT00 = 17, /* float */ + SVGA3D_TS_BUMPENVMAT01 = 18, /* float */ + SVGA3D_TS_BUMPENVMAT10 = 19, /* float */ + SVGA3D_TS_BUMPENVMAT11 = 20, /* float */ + SVGA3D_TS_TEXTURE_MIPMAP_LEVEL = 21, /* uint32 */ + SVGA3D_TS_TEXTURE_LOD_BIAS = 22, /* float */ + SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL = 23, /* uint32 */ + SVGA3D_TS_ADDRESSW = 24, /* SVGA3dTextureAddress */ + + + /* + * Sampler Gamma Level + * + * Sampler gamma effects the color of samples taken from the sampler. A + * value of 1.0 will produce linear samples. If the value is <= 0.0 the + * gamma value is ignored and a linear space is used. + */ + + SVGA3D_TS_GAMMA = 25, /* float */ + SVGA3D_TS_BUMPENVLSCALE = 26, /* float */ + SVGA3D_TS_BUMPENVLOFFSET = 27, /* float */ + SVGA3D_TS_COLORARG0 = 28, /* SVGA3dTextureArgData */ + SVGA3D_TS_ALPHAARG0 = 29, /* SVGA3dTextureArgData */ + SVGA3D_TS_MAX +} SVGA3dTextureStateName; + +typedef enum { + SVGA3D_TC_INVALID = 0, + SVGA3D_TC_DISABLE = 1, + SVGA3D_TC_SELECTARG1 = 2, + SVGA3D_TC_SELECTARG2 = 3, + SVGA3D_TC_MODULATE = 4, + SVGA3D_TC_ADD = 5, + SVGA3D_TC_ADDSIGNED = 6, + SVGA3D_TC_SUBTRACT = 7, + SVGA3D_TC_BLENDTEXTUREALPHA = 8, + SVGA3D_TC_BLENDDIFFUSEALPHA = 9, + SVGA3D_TC_BLENDCURRENTALPHA = 10, + SVGA3D_TC_BLENDFACTORALPHA = 11, + SVGA3D_TC_MODULATE2X = 12, + SVGA3D_TC_MODULATE4X = 13, + SVGA3D_TC_DSDT = 14, + SVGA3D_TC_DOTPRODUCT3 = 15, + SVGA3D_TC_BLENDTEXTUREALPHAPM = 16, + SVGA3D_TC_ADDSIGNED2X = 17, + SVGA3D_TC_ADDSMOOTH = 18, + SVGA3D_TC_PREMODULATE = 19, + SVGA3D_TC_MODULATEALPHA_ADDCOLOR = 20, + SVGA3D_TC_MODULATECOLOR_ADDALPHA = 21, + SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR = 22, + SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA = 23, + SVGA3D_TC_BUMPENVMAPLUMINANCE = 24, + SVGA3D_TC_MULTIPLYADD = 25, + SVGA3D_TC_LERP = 26, + SVGA3D_TC_MAX +} SVGA3dTextureCombiner; + +#define SVGA3D_TC_CAP_BIT(svga3d_tc_op) (svga3d_tc_op ? (1 << (svga3d_tc_op - 1)) : 0) + +typedef enum { + SVGA3D_TEX_ADDRESS_INVALID = 0, + SVGA3D_TEX_ADDRESS_WRAP = 1, + SVGA3D_TEX_ADDRESS_MIRROR = 2, + SVGA3D_TEX_ADDRESS_CLAMP = 3, + SVGA3D_TEX_ADDRESS_BORDER = 4, + SVGA3D_TEX_ADDRESS_MIRRORONCE = 5, + SVGA3D_TEX_ADDRESS_EDGE = 6, + SVGA3D_TEX_ADDRESS_MAX +} SVGA3dTextureAddress; + +/* + * SVGA3D_TEX_FILTER_NONE as the minification filter means mipmapping is + * disabled, and the rasterizer should use the magnification filter instead. + */ +typedef enum { + SVGA3D_TEX_FILTER_NONE = 0, + SVGA3D_TEX_FILTER_NEAREST = 1, + SVGA3D_TEX_FILTER_LINEAR = 2, + SVGA3D_TEX_FILTER_ANISOTROPIC = 3, + SVGA3D_TEX_FILTER_FLATCUBIC = 4, // Deprecated, not implemented + SVGA3D_TEX_FILTER_GAUSSIANCUBIC = 5, // Deprecated, not implemented + SVGA3D_TEX_FILTER_PYRAMIDALQUAD = 6, // Not currently implemented + SVGA3D_TEX_FILTER_GAUSSIANQUAD = 7, // Not currently implemented + SVGA3D_TEX_FILTER_MAX +} SVGA3dTextureFilter; + +typedef enum { + SVGA3D_TEX_TRANSFORM_OFF = 0, + SVGA3D_TEX_TRANSFORM_S = (1 << 0), + SVGA3D_TEX_TRANSFORM_T = (1 << 1), + SVGA3D_TEX_TRANSFORM_R = (1 << 2), + SVGA3D_TEX_TRANSFORM_Q = (1 << 3), + SVGA3D_TEX_PROJECTED = (1 << 15), +} SVGA3dTexTransformFlags; + +typedef enum { + SVGA3D_TEXCOORD_GEN_OFF = 0, + SVGA3D_TEXCOORD_GEN_EYE_POSITION = 1, + SVGA3D_TEXCOORD_GEN_EYE_NORMAL = 2, + SVGA3D_TEXCOORD_GEN_REFLECTIONVECTOR = 3, + SVGA3D_TEXCOORD_GEN_SPHERE = 4, + SVGA3D_TEXCOORD_GEN_MAX +} SVGA3dTextureCoordGen; + +/* + * Texture argument constants for texture combiner + */ +typedef enum { + SVGA3D_TA_INVALID = 0, + SVGA3D_TA_CONSTANT = 1, + SVGA3D_TA_PREVIOUS = 2, + SVGA3D_TA_DIFFUSE = 3, + SVGA3D_TA_TEXTURE = 4, + SVGA3D_TA_SPECULAR = 5, + SVGA3D_TA_MAX +} SVGA3dTextureArgData; + +#define SVGA3D_TM_MASK_LEN 4 + +/* Modifiers for texture argument constants defined above. */ +typedef enum { + SVGA3D_TM_NONE = 0, + SVGA3D_TM_ALPHA = (1 << SVGA3D_TM_MASK_LEN), + SVGA3D_TM_ONE_MINUS = (2 << SVGA3D_TM_MASK_LEN), +} SVGA3dTextureArgModifier; + +#define SVGA3D_INVALID_ID ((uint32)-1) +#define SVGA3D_MAX_CLIP_PLANES 6 + +/* + * This is the limit to the number of fixed-function texture + * transforms and texture coordinates we can support. It does *not* + * correspond to the number of texture image units (samplers) we + * support! + */ +#define SVGA3D_MAX_TEXTURE_COORDS 8 + +/* + * Vertex declarations + * + * Notes: + * + * SVGA3D_DECLUSAGE_POSITIONT is for pre-transformed vertices. If you + * draw with any POSITIONT vertex arrays, the programmable vertex + * pipeline will be implicitly disabled. Drawing will take place as if + * no vertex shader was bound. + */ + +typedef enum { + SVGA3D_DECLUSAGE_POSITION = 0, + SVGA3D_DECLUSAGE_BLENDWEIGHT, // 1 + SVGA3D_DECLUSAGE_BLENDINDICES, // 2 + SVGA3D_DECLUSAGE_NORMAL, // 3 + SVGA3D_DECLUSAGE_PSIZE, // 4 + SVGA3D_DECLUSAGE_TEXCOORD, // 5 + SVGA3D_DECLUSAGE_TANGENT, // 6 + SVGA3D_DECLUSAGE_BINORMAL, // 7 + SVGA3D_DECLUSAGE_TESSFACTOR, // 8 + SVGA3D_DECLUSAGE_POSITIONT, // 9 + SVGA3D_DECLUSAGE_COLOR, // 10 + SVGA3D_DECLUSAGE_FOG, // 11 + SVGA3D_DECLUSAGE_DEPTH, // 12 + SVGA3D_DECLUSAGE_SAMPLE, // 13 + SVGA3D_DECLUSAGE_MAX +} SVGA3dDeclUsage; + +typedef enum { + SVGA3D_DECLMETHOD_DEFAULT = 0, + SVGA3D_DECLMETHOD_PARTIALU, + SVGA3D_DECLMETHOD_PARTIALV, + SVGA3D_DECLMETHOD_CROSSUV, // Normal + SVGA3D_DECLMETHOD_UV, + SVGA3D_DECLMETHOD_LOOKUP, // Lookup a displacement map + SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map +} SVGA3dDeclMethod; + +typedef enum { + SVGA3D_DECLTYPE_FLOAT1 = 0, + SVGA3D_DECLTYPE_FLOAT2 = 1, + SVGA3D_DECLTYPE_FLOAT3 = 2, + SVGA3D_DECLTYPE_FLOAT4 = 3, + SVGA3D_DECLTYPE_D3DCOLOR = 4, + SVGA3D_DECLTYPE_UBYTE4 = 5, + SVGA3D_DECLTYPE_SHORT2 = 6, + SVGA3D_DECLTYPE_SHORT4 = 7, + SVGA3D_DECLTYPE_UBYTE4N = 8, + SVGA3D_DECLTYPE_SHORT2N = 9, + SVGA3D_DECLTYPE_SHORT4N = 10, + SVGA3D_DECLTYPE_USHORT2N = 11, + SVGA3D_DECLTYPE_USHORT4N = 12, + SVGA3D_DECLTYPE_UDEC3 = 13, + SVGA3D_DECLTYPE_DEC3N = 14, + SVGA3D_DECLTYPE_FLOAT16_2 = 15, + SVGA3D_DECLTYPE_FLOAT16_4 = 16, + SVGA3D_DECLTYPE_MAX, +} SVGA3dDeclType; + +/* + * This structure is used for the divisor for geometry instancing; + * it's a direct translation of the Direct3D equivalent. + */ +typedef union { + struct { + /* + * For index data, this number represents the number of instances to draw. + * For instance data, this number represents the number of + * instances/vertex in this stream + */ + uint32 count : 30; + + /* + * This is 1 if this is supposed to be the data that is repeated for + * every instance. + */ + uint32 indexedData : 1; + + /* + * This is 1 if this is supposed to be the per-instance data. + */ + uint32 instanceData : 1; + }; + + uint32 value; +} SVGA3dVertexDivisor; + +typedef enum { + SVGA3D_PRIMITIVE_INVALID = 0, + SVGA3D_PRIMITIVE_TRIANGLELIST = 1, + SVGA3D_PRIMITIVE_POINTLIST = 2, + SVGA3D_PRIMITIVE_LINELIST = 3, + SVGA3D_PRIMITIVE_LINESTRIP = 4, + SVGA3D_PRIMITIVE_TRIANGLESTRIP = 5, + SVGA3D_PRIMITIVE_TRIANGLEFAN = 6, + SVGA3D_PRIMITIVE_MAX +} SVGA3dPrimitiveType; + +typedef enum { + SVGA3D_COORDINATE_INVALID = 0, + SVGA3D_COORDINATE_LEFTHANDED = 1, + SVGA3D_COORDINATE_RIGHTHANDED = 2, + SVGA3D_COORDINATE_MAX +} SVGA3dCoordinateType; + +typedef enum { + SVGA3D_TRANSFORM_INVALID = 0, + SVGA3D_TRANSFORM_WORLD = 1, + SVGA3D_TRANSFORM_VIEW = 2, + SVGA3D_TRANSFORM_PROJECTION = 3, + SVGA3D_TRANSFORM_TEXTURE0 = 4, + SVGA3D_TRANSFORM_TEXTURE1 = 5, + SVGA3D_TRANSFORM_TEXTURE2 = 6, + SVGA3D_TRANSFORM_TEXTURE3 = 7, + SVGA3D_TRANSFORM_TEXTURE4 = 8, + SVGA3D_TRANSFORM_TEXTURE5 = 9, + SVGA3D_TRANSFORM_TEXTURE6 = 10, + SVGA3D_TRANSFORM_TEXTURE7 = 11, + SVGA3D_TRANSFORM_WORLD1 = 12, + SVGA3D_TRANSFORM_WORLD2 = 13, + SVGA3D_TRANSFORM_WORLD3 = 14, + SVGA3D_TRANSFORM_MAX +} SVGA3dTransformType; + +typedef enum { + SVGA3D_LIGHTTYPE_INVALID = 0, + SVGA3D_LIGHTTYPE_POINT = 1, + SVGA3D_LIGHTTYPE_SPOT1 = 2, /* 1-cone, in degrees */ + SVGA3D_LIGHTTYPE_SPOT2 = 3, /* 2-cone, in radians */ + SVGA3D_LIGHTTYPE_DIRECTIONAL = 4, + SVGA3D_LIGHTTYPE_MAX +} SVGA3dLightType; + +typedef enum { + SVGA3D_CUBEFACE_POSX = 0, + SVGA3D_CUBEFACE_NEGX = 1, + SVGA3D_CUBEFACE_POSY = 2, + SVGA3D_CUBEFACE_NEGY = 3, + SVGA3D_CUBEFACE_POSZ = 4, + SVGA3D_CUBEFACE_NEGZ = 5, +} SVGA3dCubeFace; + +typedef enum { + SVGA3D_SHADERTYPE_COMPILED_DX8 = 0, + SVGA3D_SHADERTYPE_VS = 1, + SVGA3D_SHADERTYPE_PS = 2, + SVGA3D_SHADERTYPE_MAX +} SVGA3dShaderType; + +typedef enum { + SVGA3D_CONST_TYPE_FLOAT = 0, + SVGA3D_CONST_TYPE_INT = 1, + SVGA3D_CONST_TYPE_BOOL = 2, +} SVGA3dShaderConstType; + +#define SVGA3D_MAX_SURFACE_FACES 6 + +typedef enum { + SVGA3D_STRETCH_BLT_POINT = 0, + SVGA3D_STRETCH_BLT_LINEAR = 1, + SVGA3D_STRETCH_BLT_MAX +} SVGA3dStretchBltMode; + +typedef enum { + SVGA3D_QUERYTYPE_OCCLUSION = 0, + SVGA3D_QUERYTYPE_MAX +} SVGA3dQueryType; + +typedef enum { + SVGA3D_QUERYSTATE_PENDING = 0, /* Waiting on the host (set by guest) */ + SVGA3D_QUERYSTATE_SUCCEEDED = 1, /* Completed successfully (set by host) */ + SVGA3D_QUERYSTATE_FAILED = 2, /* Completed unsuccessfully (set by host) */ + SVGA3D_QUERYSTATE_NEW = 3, /* Never submitted (For guest use only) */ +} SVGA3dQueryState; + +typedef enum { + SVGA3D_WRITE_HOST_VRAM = 1, + SVGA3D_READ_HOST_VRAM = 2, +} SVGA3dTransferType; + +/* + * The maximum number of vertex arrays we're guaranteed to support in + * SVGA_3D_CMD_DRAWPRIMITIVES. + */ +#define SVGA3D_MAX_VERTEX_ARRAYS 32 + +/* + * The maximum number of primitive ranges we're guaranteed to support + * in SVGA_3D_CMD_DRAWPRIMITIVES. + */ +#define SVGA3D_MAX_DRAW_PRIMITIVE_RANGES 32 + +/* + * Identifiers for commands in the command FIFO. + * + * IDs between 1000 and 1039 (inclusive) were used by obsolete versions of + * the SVGA3D protocol and remain reserved; they should not be used in the + * future. + * + * IDs between 1040 and 1999 (inclusive) are available for use by the + * current SVGA3D protocol. + * + * FIFO clients other than SVGA3D should stay below 1000, or at 2000 + * and up. + */ + +#define SVGA_3D_CMD_LEGACY_BASE 1000 +#define SVGA_3D_CMD_BASE 1040 + +#define SVGA_3D_CMD_SURFACE_DEFINE SVGA_3D_CMD_BASE + 0 +#define SVGA_3D_CMD_SURFACE_DESTROY SVGA_3D_CMD_BASE + 1 +#define SVGA_3D_CMD_SURFACE_COPY SVGA_3D_CMD_BASE + 2 +#define SVGA_3D_CMD_SURFACE_STRETCHBLT SVGA_3D_CMD_BASE + 3 +#define SVGA_3D_CMD_SURFACE_DMA SVGA_3D_CMD_BASE + 4 +#define SVGA_3D_CMD_CONTEXT_DEFINE SVGA_3D_CMD_BASE + 5 +#define SVGA_3D_CMD_CONTEXT_DESTROY SVGA_3D_CMD_BASE + 6 +#define SVGA_3D_CMD_SETTRANSFORM SVGA_3D_CMD_BASE + 7 +#define SVGA_3D_CMD_SETZRANGE SVGA_3D_CMD_BASE + 8 +#define SVGA_3D_CMD_SETRENDERSTATE SVGA_3D_CMD_BASE + 9 +#define SVGA_3D_CMD_SETRENDERTARGET SVGA_3D_CMD_BASE + 10 +#define SVGA_3D_CMD_SETTEXTURESTATE SVGA_3D_CMD_BASE + 11 +#define SVGA_3D_CMD_SETMATERIAL SVGA_3D_CMD_BASE + 12 +#define SVGA_3D_CMD_SETLIGHTDATA SVGA_3D_CMD_BASE + 13 +#define SVGA_3D_CMD_SETLIGHTENABLED SVGA_3D_CMD_BASE + 14 +#define SVGA_3D_CMD_SETVIEWPORT SVGA_3D_CMD_BASE + 15 +#define SVGA_3D_CMD_SETCLIPPLANE SVGA_3D_CMD_BASE + 16 +#define SVGA_3D_CMD_CLEAR SVGA_3D_CMD_BASE + 17 +#define SVGA_3D_CMD_PRESENT SVGA_3D_CMD_BASE + 18 // Deprecated +#define SVGA_3D_CMD_SHADER_DEFINE SVGA_3D_CMD_BASE + 19 +#define SVGA_3D_CMD_SHADER_DESTROY SVGA_3D_CMD_BASE + 20 +#define SVGA_3D_CMD_SET_SHADER SVGA_3D_CMD_BASE + 21 +#define SVGA_3D_CMD_SET_SHADER_CONST SVGA_3D_CMD_BASE + 22 +#define SVGA_3D_CMD_DRAW_PRIMITIVES SVGA_3D_CMD_BASE + 23 +#define SVGA_3D_CMD_SETSCISSORRECT SVGA_3D_CMD_BASE + 24 +#define SVGA_3D_CMD_BEGIN_QUERY SVGA_3D_CMD_BASE + 25 +#define SVGA_3D_CMD_END_QUERY SVGA_3D_CMD_BASE + 26 +#define SVGA_3D_CMD_WAIT_FOR_QUERY SVGA_3D_CMD_BASE + 27 +#define SVGA_3D_CMD_PRESENT_READBACK SVGA_3D_CMD_BASE + 28 // Deprecated +#define SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN SVGA_3D_CMD_BASE + 29 +#define SVGA_3D_CMD_MAX SVGA_3D_CMD_BASE + 30 + +#define SVGA_3D_CMD_FUTURE_MAX 2000 + +/* + * Common substructures used in multiple FIFO commands: + */ + +typedef struct { + union { + struct { + uint16 function; // SVGA3dFogFunction + uint8 type; // SVGA3dFogType + uint8 base; // SVGA3dFogBase + }; + uint32 uintValue; + }; +} SVGA3dFogMode; + +/* + * Uniquely identify one image (a 1D/2D/3D array) from a surface. This + * is a surface ID as well as face/mipmap indices. + */ + +typedef +struct SVGA3dSurfaceImageId { + uint32 sid; + uint32 face; + uint32 mipmap; +} SVGA3dSurfaceImageId; + +typedef +struct SVGA3dGuestImage { + SVGAGuestPtr ptr; + + /* + * A note on interpretation of pitch: This value of pitch is the + * number of bytes between vertically adjacent image + * blocks. Normally this is the number of bytes between the first + * pixel of two adjacent scanlines. With compressed textures, + * however, this may represent the number of bytes between + * compression blocks rather than between rows of pixels. + * + * XXX: Compressed textures currently must be tightly packed in guest memory. + * + * If the image is 1-dimensional, pitch is ignored. + * + * If 'pitch' is zero, the SVGA3D device calculates a pitch value + * assuming each row of blocks is tightly packed. + */ + uint32 pitch; +} SVGA3dGuestImage; + + +/* + * FIFO command format definitions: + */ + +/* + * The data size header following cmdNum for every 3d command + */ +typedef +struct { + uint32 id; + uint32 size; +} SVGA3dCmdHeader; + +/* + * A surface is a hierarchy of host VRAM surfaces: 1D, 2D, or 3D, with + * optional mipmaps and cube faces. + */ + +typedef +struct { + uint32 width; + uint32 height; + uint32 depth; +} SVGA3dSize; + +typedef enum { + SVGA3D_SURFACE_CUBEMAP = (1 << 0), + SVGA3D_SURFACE_HINT_STATIC = (1 << 1), + SVGA3D_SURFACE_HINT_DYNAMIC = (1 << 2), + SVGA3D_SURFACE_HINT_INDEXBUFFER = (1 << 3), + SVGA3D_SURFACE_HINT_VERTEXBUFFER = (1 << 4), + SVGA3D_SURFACE_HINT_TEXTURE = (1 << 5), + SVGA3D_SURFACE_HINT_RENDERTARGET = (1 << 6), + SVGA3D_SURFACE_HINT_DEPTHSTENCIL = (1 << 7), + SVGA3D_SURFACE_HINT_WRITEONLY = (1 << 8), +} SVGA3dSurfaceFlags; + +typedef +struct { + uint32 numMipLevels; +} SVGA3dSurfaceFace; + +typedef +struct { + uint32 sid; + SVGA3dSurfaceFlags surfaceFlags; + SVGA3dSurfaceFormat format; + SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES]; + /* + * Followed by an SVGA3dSize structure for each mip level in each face. + * + * A note on surface sizes: Sizes are always specified in pixels, + * even if the true surface size is not a multiple of the minimum + * block size of the surface's format. For example, a 3x3x1 DXT1 + * compressed texture would actually be stored as a 4x4x1 image in + * memory. + */ +} SVGA3dCmdDefineSurface; /* SVGA_3D_CMD_SURFACE_DEFINE */ + +typedef +struct { + uint32 sid; +} SVGA3dCmdDestroySurface; /* SVGA_3D_CMD_SURFACE_DESTROY */ + +typedef +struct { + uint32 cid; +} SVGA3dCmdDefineContext; /* SVGA_3D_CMD_CONTEXT_DEFINE */ + +typedef +struct { + uint32 cid; +} SVGA3dCmdDestroyContext; /* SVGA_3D_CMD_CONTEXT_DESTROY */ + +typedef +struct { + uint32 cid; + SVGA3dClearFlag clearFlag; + uint32 color; + float depth; + uint32 stencil; + /* Followed by variable number of SVGA3dRect structures */ +} SVGA3dCmdClear; /* SVGA_3D_CMD_CLEAR */ + +typedef +struct SVGA3dCopyRect { + uint32 x; + uint32 y; + uint32 w; + uint32 h; + uint32 srcx; + uint32 srcy; +} SVGA3dCopyRect; + +typedef +struct SVGA3dCopyBox { + uint32 x; + uint32 y; + uint32 z; + uint32 w; + uint32 h; + uint32 d; + uint32 srcx; + uint32 srcy; + uint32 srcz; +} SVGA3dCopyBox; + +typedef +struct { + uint32 x; + uint32 y; + uint32 w; + uint32 h; +} SVGA3dRect; + +typedef +struct { + uint32 x; + uint32 y; + uint32 z; + uint32 w; + uint32 h; + uint32 d; +} SVGA3dBox; + +typedef +struct { + uint32 x; + uint32 y; + uint32 z; +} SVGA3dPoint; + +typedef +struct { + SVGA3dLightType type; + SVGA3dBool inWorldSpace; + float diffuse[4]; + float specular[4]; + float ambient[4]; + float position[4]; + float direction[4]; + float range; + float falloff; + float attenuation0; + float attenuation1; + float attenuation2; + float theta; + float phi; +} SVGA3dLightData; + +typedef +struct { + uint32 sid; + /* Followed by variable number of SVGA3dCopyRect structures */ +} SVGA3dCmdPresent; /* SVGA_3D_CMD_PRESENT */ + +typedef +struct { + SVGA3dRenderStateName state; + union { + uint32 uintValue; + float floatValue; + }; +} SVGA3dRenderState; + +typedef +struct { + uint32 cid; + /* Followed by variable number of SVGA3dRenderState structures */ +} SVGA3dCmdSetRenderState; /* SVGA_3D_CMD_SETRENDERSTATE */ + +typedef +struct { + uint32 cid; + SVGA3dRenderTargetType type; + SVGA3dSurfaceImageId target; +} SVGA3dCmdSetRenderTarget; /* SVGA_3D_CMD_SETRENDERTARGET */ + +typedef +struct { + SVGA3dSurfaceImageId src; + SVGA3dSurfaceImageId dest; + /* Followed by variable number of SVGA3dCopyBox structures */ +} SVGA3dCmdSurfaceCopy; /* SVGA_3D_CMD_SURFACE_COPY */ + +typedef +struct { + SVGA3dSurfaceImageId src; + SVGA3dSurfaceImageId dest; + SVGA3dBox boxSrc; + SVGA3dBox boxDest; + SVGA3dStretchBltMode mode; +} SVGA3dCmdSurfaceStretchBlt; /* SVGA_3D_CMD_SURFACE_STRETCHBLT */ + +typedef +struct { + /* + * If the discard flag is present in a surface DMA operation, the host may + * discard the contents of the current mipmap level and face of the target + * surface before applying the surface DMA contents. + */ + uint32 discard : 1; + + /* + * If the unsynchronized flag is present, the host may perform this upload + * without syncing to pending reads on this surface. + */ + uint32 unsynchronized : 1; + + /* + * Guests *MUST* set the reserved bits to 0 before submitting the command + * suffix as future flags may occupy these bits. + */ + uint32 reserved : 30; +} SVGA3dSurfaceDMAFlags; + +typedef +struct { + SVGA3dGuestImage guest; + SVGA3dSurfaceImageId host; + SVGA3dTransferType transfer; + /* + * Followed by variable number of SVGA3dCopyBox structures. For consistency + * in all clipping logic and coordinate translation, we define the + * "source" in each copyBox as the guest image and the + * "destination" as the host image, regardless of transfer + * direction. + * + * For efficiency, the SVGA3D device is free to copy more data than + * specified. For example, it may round copy boxes outwards such + * that they lie on particular alignment boundaries. + */ +} SVGA3dCmdSurfaceDMA; /* SVGA_3D_CMD_SURFACE_DMA */ + +/* + * SVGA3dCmdSurfaceDMASuffix -- + * + * This is a command suffix that will appear after a SurfaceDMA command in + * the FIFO. It contains some extra information that hosts may use to + * optimize performance or protect the guest. This suffix exists to preserve + * backwards compatibility while also allowing for new functionality to be + * implemented. + */ + +typedef +struct { + uint32 suffixSize; + + /* + * The maximum offset is used to determine the maximum offset from the + * guestPtr base address that will be accessed or written to during this + * surfaceDMA. If the suffix is supported, the host will respect this + * boundary while performing surface DMAs. + * + * Defaults to MAX_UINT32 + */ + uint32 maximumOffset; + + /* + * A set of flags that describes optimizations that the host may perform + * while performing this surface DMA operation. The guest should never rely + * on behaviour that is different when these flags are set for correctness. + * + * Defaults to 0 + */ + SVGA3dSurfaceDMAFlags flags; +} SVGA3dCmdSurfaceDMASuffix; + +/* + * SVGA_3D_CMD_DRAW_PRIMITIVES -- + * + * This command is the SVGA3D device's generic drawing entry point. + * It can draw multiple ranges of primitives, optionally using an + * index buffer, using an arbitrary collection of vertex buffers. + * + * Each SVGA3dVertexDecl defines a distinct vertex array to bind + * during this draw call. The declarations specify which surface + * the vertex data lives in, what that vertex data is used for, + * and how to interpret it. + * + * Each SVGA3dPrimitiveRange defines a collection of primitives + * to render using the same vertex arrays. An index buffer is + * optional. + */ + +typedef +struct { + /* + * A range hint is an optional specification for the range of indices + * in an SVGA3dArray that will be used. If 'last' is zero, it is assumed + * that the entire array will be used. + * + * These are only hints. The SVGA3D device may use them for + * performance optimization if possible, but it's also allowed to + * ignore these values. + */ + uint32 first; + uint32 last; +} SVGA3dArrayRangeHint; + +typedef +struct { + /* + * Define the origin and shape of a vertex or index array. Both + * 'offset' and 'stride' are in bytes. The provided surface will be + * reinterpreted as a flat array of bytes in the same format used + * by surface DMA operations. To avoid unnecessary conversions, the + * surface should be created with the SVGA3D_BUFFER format. + * + * Index 0 in the array starts 'offset' bytes into the surface. + * Index 1 begins at byte 'offset + stride', etc. Array indices may + * not be negative. + */ + uint32 surfaceId; + uint32 offset; + uint32 stride; +} SVGA3dArray; + +typedef +struct { + /* + * Describe a vertex array's data type, and define how it is to be + * used by the fixed function pipeline or the vertex shader. It + * isn't useful to have two VertexDecls with the same + * VertexArrayIdentity in one draw call. + */ + SVGA3dDeclType type; + SVGA3dDeclMethod method; + SVGA3dDeclUsage usage; + uint32 usageIndex; +} SVGA3dVertexArrayIdentity; + +typedef +struct { + SVGA3dVertexArrayIdentity identity; + SVGA3dArray array; + SVGA3dArrayRangeHint rangeHint; +} SVGA3dVertexDecl; + +typedef +struct { + /* + * Define a group of primitives to render, from sequential indices. + * + * The value of 'primitiveType' and 'primitiveCount' imply the + * total number of vertices that will be rendered. + */ + SVGA3dPrimitiveType primType; + uint32 primitiveCount; + + /* + * Optional index buffer. If indexArray.surfaceId is + * SVGA3D_INVALID_ID, we render without an index buffer. Rendering + * without an index buffer is identical to rendering with an index + * buffer containing the sequence [0, 1, 2, 3, ...]. + * + * If an index buffer is in use, indexWidth specifies the width in + * bytes of each index value. It must be less than or equal to + * indexArray.stride. + * + * (Currently, the SVGA3D device requires index buffers to be tightly + * packed. In other words, indexWidth == indexArray.stride) + */ + SVGA3dArray indexArray; + uint32 indexWidth; + + /* + * Optional index bias. This number is added to all indices from + * indexArray before they are used as vertex array indices. This + * can be used in multiple ways: + * + * - When not using an indexArray, this bias can be used to + * specify where in the vertex arrays to begin rendering. + * + * - A positive number here is equivalent to increasing the + * offset in each vertex array. + * + * - A negative number can be used to render using a small + * vertex array and an index buffer that contains large + * values. This may be used by some applications that + * crop a vertex buffer without modifying their index + * buffer. + * + * Note that rendering with a negative bias value may be slower and + * use more memory than rendering with a positive or zero bias. + */ + int32 indexBias; +} SVGA3dPrimitiveRange; + +typedef +struct { + uint32 cid; + uint32 numVertexDecls; + uint32 numRanges; + + /* + * There are two variable size arrays after the + * SVGA3dCmdDrawPrimitives structure. In order, + * they are: + * + * 1. SVGA3dVertexDecl, quantity 'numVertexDecls', but no more than + * SVGA3D_MAX_VERTEX_ARRAYS; + * 2. SVGA3dPrimitiveRange, quantity 'numRanges', but no more than + * SVGA3D_MAX_DRAW_PRIMITIVE_RANGES; + * 3. Optionally, SVGA3dVertexDivisor, quantity 'numVertexDecls' (contains + * the frequency divisor for the corresponding vertex decl). + */ +} SVGA3dCmdDrawPrimitives; /* SVGA_3D_CMD_DRAWPRIMITIVES */ + +typedef +struct { + uint32 stage; + SVGA3dTextureStateName name; + union { + uint32 value; + float floatValue; + }; +} SVGA3dTextureState; + +typedef +struct { + uint32 cid; + /* Followed by variable number of SVGA3dTextureState structures */ +} SVGA3dCmdSetTextureState; /* SVGA_3D_CMD_SETTEXTURESTATE */ + +typedef +struct { + uint32 cid; + SVGA3dTransformType type; + float matrix[16]; +} SVGA3dCmdSetTransform; /* SVGA_3D_CMD_SETTRANSFORM */ + +typedef +struct { + float min; + float max; +} SVGA3dZRange; + +typedef +struct { + uint32 cid; + SVGA3dZRange zRange; +} SVGA3dCmdSetZRange; /* SVGA_3D_CMD_SETZRANGE */ + +typedef +struct { + float diffuse[4]; + float ambient[4]; + float specular[4]; + float emissive[4]; + float shininess; +} SVGA3dMaterial; + +typedef +struct { + uint32 cid; + SVGA3dFace face; + SVGA3dMaterial material; +} SVGA3dCmdSetMaterial; /* SVGA_3D_CMD_SETMATERIAL */ + +typedef +struct { + uint32 cid; + uint32 index; + SVGA3dLightData data; +} SVGA3dCmdSetLightData; /* SVGA_3D_CMD_SETLIGHTDATA */ + +typedef +struct { + uint32 cid; + uint32 index; + uint32 enabled; +} SVGA3dCmdSetLightEnabled; /* SVGA_3D_CMD_SETLIGHTENABLED */ + +typedef +struct { + uint32 cid; + SVGA3dRect rect; +} SVGA3dCmdSetViewport; /* SVGA_3D_CMD_SETVIEWPORT */ + +typedef +struct { + uint32 cid; + SVGA3dRect rect; +} SVGA3dCmdSetScissorRect; /* SVGA_3D_CMD_SETSCISSORRECT */ + +typedef +struct { + uint32 cid; + uint32 index; + float plane[4]; +} SVGA3dCmdSetClipPlane; /* SVGA_3D_CMD_SETCLIPPLANE */ + +typedef +struct { + uint32 cid; + uint32 shid; + SVGA3dShaderType type; + /* Followed by variable number of DWORDs for shader bycode */ +} SVGA3dCmdDefineShader; /* SVGA_3D_CMD_SHADER_DEFINE */ + +typedef +struct { + uint32 cid; + uint32 shid; + SVGA3dShaderType type; +} SVGA3dCmdDestroyShader; /* SVGA_3D_CMD_SHADER_DESTROY */ + +typedef +struct { + uint32 cid; + uint32 reg; /* register number */ + SVGA3dShaderType type; + SVGA3dShaderConstType ctype; + uint32 values[4]; +} SVGA3dCmdSetShaderConst; /* SVGA_3D_CMD_SET_SHADER_CONST */ + +typedef +struct { + uint32 cid; + SVGA3dShaderType type; + uint32 shid; +} SVGA3dCmdSetShader; /* SVGA_3D_CMD_SET_SHADER */ + +typedef +struct { + uint32 cid; + SVGA3dQueryType type; +} SVGA3dCmdBeginQuery; /* SVGA_3D_CMD_BEGIN_QUERY */ + +typedef +struct { + uint32 cid; + SVGA3dQueryType type; + SVGAGuestPtr guestResult; /* Points to an SVGA3dQueryResult structure */ +} SVGA3dCmdEndQuery; /* SVGA_3D_CMD_END_QUERY */ + +typedef +struct { + uint32 cid; /* Same parameters passed to END_QUERY */ + SVGA3dQueryType type; + SVGAGuestPtr guestResult; +} SVGA3dCmdWaitForQuery; /* SVGA_3D_CMD_WAIT_FOR_QUERY */ + +typedef +struct { + uint32 totalSize; /* Set by guest before query is ended. */ + SVGA3dQueryState state; /* Set by host or guest. See SVGA3dQueryState. */ + union { /* Set by host on exit from PENDING state */ + uint32 result32; + }; +} SVGA3dQueryResult; + +/* + * SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN -- + * + * This is a blit from an SVGA3D surface to a Screen Object. Just + * like GMR-to-screen blits, this blit may be directed at a + * specific screen or to the virtual coordinate space. + * + * The blit copies from a rectangular region of an SVGA3D surface + * image to a rectangular region of a screen or screens. + * + * This command takes an optional variable-length list of clipping + * rectangles after the body of the command. If no rectangles are + * specified, there is no clipping region. The entire destRect is + * drawn to. If one or more rectangles are included, they describe + * a clipping region. The clip rectangle coordinates are measured + * relative to the top-left corner of destRect. + * + * This clipping region serves multiple purposes: + * + * - It can be used to perform an irregularly shaped blit more + * efficiently than by issuing many separate blit commands. + * + * - It is equivalent to allowing blits with non-integer + * source coordinates. You could blit just one half-pixel + * of a source, for example, by specifying a larger + * destination rectangle than you need, then removing + * part of it using a clip rectangle. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT + * + * Limitations: + * + * - Currently, no backend supports blits from a mipmap or face + * other than the first one. + */ + +typedef +struct { + SVGA3dSurfaceImageId srcImage; + SVGASignedRect srcRect; + uint32 destScreenId; /* Screen ID or SVGA_ID_INVALID for virt. coords */ + SVGASignedRect destRect; /* Supports scaling if src/rest different size */ + /* Clipping: zero or more SVGASignedRects follow */ +} SVGA3dCmdBlitSurfaceToScreen; /* SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN */ + + +/* + * Capability query index. + * + * Notes: + * + * 1. SVGA3D_DEVCAP_MAX_TEXTURES reflects the maximum number of + * fixed-function texture units available. Each of these units + * work in both FFP and Shader modes, and they support texture + * transforms and texture coordinates. The host may have additional + * texture image units that are only usable with shaders. + * + * 2. The BUFFER_FORMAT capabilities are deprecated, and they always + * return TRUE. Even on physical hardware that does not support + * these formats natively, the SVGA3D device will provide an emulation + * which should be invisible to the guest OS. + * + * In general, the SVGA3D device should support any operation on + * any surface format, it just may perform some of these + * operations in software depending on the capabilities of the + * available physical hardware. + * + * XXX: In the future, we will add capabilities that describe in + * detail what formats are supported in hardware for what kinds + * of operations. + */ + +typedef enum { + SVGA3D_DEVCAP_3D = 0, + SVGA3D_DEVCAP_MAX_LIGHTS = 1, + SVGA3D_DEVCAP_MAX_TEXTURES = 2, /* See note (1) */ + SVGA3D_DEVCAP_MAX_CLIP_PLANES = 3, + SVGA3D_DEVCAP_VERTEX_SHADER_VERSION = 4, + SVGA3D_DEVCAP_VERTEX_SHADER = 5, + SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION = 6, + SVGA3D_DEVCAP_FRAGMENT_SHADER = 7, + SVGA3D_DEVCAP_MAX_RENDER_TARGETS = 8, + SVGA3D_DEVCAP_S23E8_TEXTURES = 9, + SVGA3D_DEVCAP_S10E5_TEXTURES = 10, + SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = 11, + SVGA3D_DEVCAP_D16_BUFFER_FORMAT = 12, /* See note (2) */ + SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT = 13, /* See note (2) */ + SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT = 14, /* See note (2) */ + SVGA3D_DEVCAP_QUERY_TYPES = 15, + SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = 16, + SVGA3D_DEVCAP_MAX_POINT_SIZE = 17, + SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = 18, + SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH = 19, + SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT = 20, + SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = 21, + SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = 22, + SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO = 23, + SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = 24, + SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = 25, + SVGA3D_DEVCAP_MAX_VERTEX_INDEX = 26, + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS = 27, + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS = 28, + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS = 29, + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS = 30, + SVGA3D_DEVCAP_TEXTURE_OPS = 31, + SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = 32, + SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = 33, + SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = 34, + SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = 35, + SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = 36, + SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = 37, + SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = 38, + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = 39, + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = 40, + SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = 41, + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = 42, + SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = 43, + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = 44, + SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = 45, + SVGA3D_DEVCAP_SURFACEFMT_DXT1 = 46, + SVGA3D_DEVCAP_SURFACEFMT_DXT2 = 47, + SVGA3D_DEVCAP_SURFACEFMT_DXT3 = 48, + SVGA3D_DEVCAP_SURFACEFMT_DXT4 = 49, + SVGA3D_DEVCAP_SURFACEFMT_DXT5 = 50, + SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = 51, + SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = 52, + SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = 53, + SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = 54, + SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = 55, + SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = 56, + SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = 57, + SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = 58, + SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = 59, + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = 60, + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = 61, + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES = 63, + + /* + * Note that MAX_SIMULTANEOUS_RENDER_TARGETS is a maximum count of color + * render targets. This does no include the depth or stencil targets. + */ + SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS = 64, + + SVGA3D_DEVCAP_SURFACEFMT_V16U16 = 65, + SVGA3D_DEVCAP_SURFACEFMT_G16R16 = 66, + SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = 67, + SVGA3D_DEVCAP_SURFACEFMT_UYVY = 68, + SVGA3D_DEVCAP_SURFACEFMT_YUY2 = 69, + + /* + * Don't add new caps into the previous section; the values in this + * enumeration must not change. You can put new values right before + * SVGA3D_DEVCAP_MAX. + */ + SVGA3D_DEVCAP_MAX /* This must be the last index. */ +} SVGA3dDevCapIndex; + +typedef union { + Bool b; + uint32 u; + int32 i; + float f; +} SVGA3dDevCapResult; + +#endif /* _SVGA3D_REG_H_ */ diff --git a/vmwgfx/vmwgfx_bootstrap.c b/vmwgfx/vmwgfx_bootstrap.c new file mode 100644 index 0000000..5e8e9e1 --- /dev/null +++ b/vmwgfx/vmwgfx_bootstrap.c @@ -0,0 +1,199 @@ +/********************************************************** + * Copyright 2008-2011 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + **********************************************************/ + +/** + * @file + * Bootstrap file for the vmwgfx xorg driver. + * + * @author Alan Hourihane + * @author Jakob Bornecrantz + * @author Thomas Hellstrom + */ + +#include "xorg-server.h" +#include "xf86.h" +#include "pciaccess.h" + +#ifndef XSERVER_LIBPCIACCESS +#error "libpciaccess needed" +#endif + +void xorg_tracker_set_functions(ScrnInfoPtr scrn); +const OptionInfoRec * xorg_tracker_available_options(int chipid, int busid); + + +/* + * Defines and modinfo + */ + +#define VMWGFX_DRIVER_NAME "vmwgfx" + +#define VMW_STRING_INNER(s) #s +#define VMW_STRING(str) VMW_STRING_INNER(str) + +#define VMWGFX_VERSION_MAJOR 11 +#define VMWGFX_VERSION_MINOR 0 +#define VMWGFX_VERSION_PATCH 0 +#define VMWGFX_VERSION_STRING_MAJOR VMW_STRING(VMWGFX_VERSION_MAJOR) +#define VMWGFX_VERSION_STRING_MINOR VMW_STRING(VMWGFX_VERSION_MINOR) +#define VMWGFX_VERSION_STRING_PATCH VMW_STRING(VMWGFX_VERSION_PATCH) + +#define VMWGFX_DRIVER_VERSION \ + (VMWGFX_VERSION_MAJOR * 65536 + VMWGFX_VERSION_MINOR * 256 + VMWGFX_VERSION_PATCH) +#define VMWGFX_DRIVER_VERSION_STRING \ + VMWGFX_VERSION_STRING_MAJOR "." VMWGFX_VERSION_STRING_MINOR \ + "." VMWGFX_VERSION_STRING_PATCH + +/* + * Standard four digit version string expected by VMware Tools installer. + * As the driver's version is only {major, minor, patchlevel}, simply append an + * extra zero for the fourth digit. + */ +#ifdef __GNUC__ +_X_EXPORT const char vmwgfx_drv_modinfo[] __attribute__((section(".modinfo"),unused)) = + "version=" VMWGFX_DRIVER_VERSION_STRING ".0"; +#endif + +static void vmw_xorg_identify(int flags); +_X_EXPORT Bool vmw_xorg_pci_probe(DriverPtr driver, + int entity_num, + struct pci_device *device, + intptr_t match_data); + + +/* + * Tables + */ + +static const struct pci_id_match vmw_xorg_device_match[] = { + {0x15ad, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0}, +}; + +static SymTabRec vmw_xorg_chipsets[] = { + {PCI_MATCH_ANY, "VMware SVGA Device"}, + {-1, NULL} +}; + +static PciChipsets vmw_xorg_pci_devices[] = { + {PCI_MATCH_ANY, PCI_MATCH_ANY, NULL}, + {-1, -1, NULL} +}; + +static XF86ModuleVersionInfo vmw_xorg_version = { + VMWGFX_DRIVER_NAME, + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + VMWGFX_VERSION_MAJOR, VMWGFX_VERSION_MINOR, VMWGFX_VERSION_PATCH, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0, 0, 0, 0} +}; + +/* + * Xorg driver exported structures + */ + +_X_EXPORT DriverRec vmwgfx = { + 1, + VMWGFX_DRIVER_NAME, + vmw_xorg_identify, + NULL, + xorg_tracker_available_options, + NULL, + 0, + NULL, + vmw_xorg_device_match, + vmw_xorg_pci_probe +}; + +static MODULESETUPPROTO(vmw_xorg_setup); + +_X_EXPORT XF86ModuleData vmwgfxModuleData = { + &vmw_xorg_version, + vmw_xorg_setup, + NULL +}; + + +/* + * Xorg driver functions + */ + +static pointer +vmw_xorg_setup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = 0; + + /* This module should be loaded only once, but check to be sure. + */ + if (!setupDone) { + setupDone = 1; + xf86AddDriver(&vmwgfx, module, HaveDriverFuncs); + + /* + * The return value must be non-NULL on success even though there + * is no TearDownProc. + */ + return (pointer) 1; + } else { + if (errmaj) + *errmaj = LDR_ONCEONLY; + return NULL; + } +} + +static void +vmw_xorg_identify(int flags) +{ + xf86PrintChipsets("vmwgfx", "Driver for VMware SVGA device", + vmw_xorg_chipsets); +} + +_X_EXPORT Bool +vmw_xorg_pci_probe(DriverPtr driver, + int entity_num, struct pci_device *device, intptr_t match_data) +{ + ScrnInfoPtr scrn = NULL; + EntityInfoPtr entity; + + scrn = xf86ConfigPciEntity(scrn, 0, entity_num, vmw_xorg_pci_devices, + NULL, NULL, NULL, NULL, NULL); + if (scrn != NULL) { + scrn->driverVersion = 1; + scrn->driverName = "vmwgfx"; + scrn->name = "vmwgfx"; + scrn->Probe = NULL; + + entity = xf86GetEntityInfo(entity_num); + + /* Use all the functions from the xorg tracker */ + xorg_tracker_set_functions(scrn); + } + return scrn != NULL; +} diff --git a/vmwgfx/vmwgfx_crtc.c b/vmwgfx/vmwgfx_crtc.c new file mode 100644 index 0000000..49e84e8 --- /dev/null +++ b/vmwgfx/vmwgfx_crtc.c @@ -0,0 +1,456 @@ +/* + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Author: Alan Hourihane + * Author: Jakob Bornecrantz + * Author: Thomas Hellstrom + */ + +#include +#include +#include +#include +#include +#include + +#include "xorg-server.h" +#include +#include +#include +#include +#include "vmwgfx_driver.h" +#include "xf86Modes.h" +#include "vmwgfx_saa.h" + +#ifdef HAVE_XEXTPROTO_71 +#include +#else +#define DPMS_SERVER +#include +#endif + +struct crtc_private +{ + drmModeCrtcPtr drm_crtc; + + /* hwcursor */ + struct vmwgfx_dmabuf *cursor_bo; + PixmapPtr scanout; + uint32_t scanout_id; + unsigned cursor_handle; +}; + +static void +crtc_dpms(xf86CrtcPtr crtc, int mode) +{ + struct crtc_private *crtcp = crtc->driver_private; + /* ScrnInfoPtr pScrn = crtc->scrn; */ + + switch (mode) { + case DPMSModeOn: + case DPMSModeStandby: + case DPMSModeSuspend: + break; + case DPMSModeOff: + + /* + * The xf86 modesetting code uses DPMS off to turn off + * crtcs that are not enabled. However, the DPMS code does the same. + * We assume, that if we get this call with the crtc not enabled, + * it's a permanent switch off which will only be reversed by a + * major modeset. + * + * If it's a DPMS switch off, (crtc->enabled == TRUE), + * the crtc may be turned on again by + * another dpms call, so don't release the scanout pixmap ref. + */ + if (!crtc->enabled && crtcp->scanout) { + PixmapPtr pixmap = crtcp->scanout; + ScreenPtr pScreen = pixmap->drawable.pScreen; + + vmwgfx_scanout_unref(pixmap); + pScreen->DestroyPixmap(pixmap); + crtcp->scanout = NULL; + crtcp->scanout_id = -1; + } + break; + } +} + +/* + * Disable outputs and crtcs and drop the scanout reference from + * scanout pixmaps. This will essentialy free all kms fb allocations. + */ + +void +vmwgfx_disable_scanout(ScrnInfoPtr pScrn) +{ + int i; + Bool save_enabled; + xf86CrtcPtr crtc; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + + xf86DPMSSet(pScrn, DPMSModeOff, 0); + for (i=0; i < config->num_crtc; ++i) { + crtc = config->crtc[i]; + save_enabled = crtc->enabled; + crtc->enabled = FALSE; + crtc_dpms(crtc, DPMSModeOff); + crtc->enabled = save_enabled; + } + xf86RotateFreeShadow(pScrn); +} + +static Bool +crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, + Rotation rotation, int x, int y) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + modesettingPtr ms = modesettingPTR(crtc->scrn); + ScreenPtr pScreen = crtc->scrn->pScreen; + xf86OutputPtr output = NULL; + struct crtc_private *crtcp = crtc->driver_private; + drmModeCrtcPtr drm_crtc = crtcp->drm_crtc; + drmModeModeInfo drm_mode; + int i, ret; + unsigned int connector_id; + PixmapPtr pixmap; + + for (i = 0; i < config->num_output; output = NULL, i++) { + output = config->output[i]; + + if (output->crtc == crtc) + break; + } + + if (!output) { + LogMessage(X_ERROR, "No output for this crtc.\n"); + return FALSE; + } + + connector_id = xorg_output_get_id(output); + + drm_mode.clock = mode->Clock; + drm_mode.hdisplay = mode->HDisplay; + drm_mode.hsync_start = mode->HSyncStart; + drm_mode.hsync_end = mode->HSyncEnd; + drm_mode.htotal = mode->HTotal; + drm_mode.vdisplay = mode->VDisplay; + drm_mode.vsync_start = mode->VSyncStart; + drm_mode.vsync_end = mode->VSyncEnd; + drm_mode.vtotal = mode->VTotal; + drm_mode.flags = mode->Flags; + drm_mode.hskew = mode->HSkew; + drm_mode.vscan = mode->VScan; + drm_mode.vrefresh = mode->VRefresh; + if (!mode->name) + xf86SetModeDefaultName(mode); + strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN - 1); + drm_mode.name[DRM_DISPLAY_MODE_LEN - 1] = '\0'; + + /* + * Check if we need to scanout from something else than the root + * pixmap. In that case, xf86CrtcRotate will take care of allocating + * new opaque scanout buffer data "crtc->rotatedData". + * However, it will not wrap + * that data into pixmaps until the first rotated damage composite. + * In out case, the buffer data is actually already a pixmap. + */ + + if (!xf86CrtcRotate(crtc)) + return FALSE; + + if (crtc->transform_in_use && crtc->rotatedData) + pixmap = (PixmapPtr) crtc->rotatedData; + else + pixmap = pScreen->GetScreenPixmap(pScreen); + + if (crtcp->scanout != pixmap) { + if (crtcp->scanout) { + vmwgfx_scanout_unref(crtcp->scanout); + pScreen->DestroyPixmap(crtcp->scanout); + } + crtcp->scanout_id = vmwgfx_scanout_ref(pixmap); + if (crtcp->scanout_id != -1) { + pixmap->refcnt += 1; + crtcp->scanout = pixmap; + } else { + crtcp->scanout = NULL; + LogMessage(X_ERROR, "Failed to convert pixmap to scanout.\n"); + return FALSE; + } + } + ret = drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, crtcp->scanout_id, x, y, + &connector_id, 1, &drm_mode); + if (ret) + return FALSE; + + vmwgfx_scanout_refresh(pixmap); + + /* Only set gamma when needed, to avoid unneeded delays. */ +#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3 + if (!crtc->active && crtc->version >= 3) + crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, + crtc->gamma_blue, crtc->gamma_size); + crtc->active = TRUE; +#endif + + return TRUE; +} + +static void +crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, CARD16 * blue, + int size) +{ + modesettingPtr ms = modesettingPTR(crtc->scrn); + struct crtc_private *crtcp = crtc->driver_private; + + drmModeCrtcSetGamma(ms->fd, crtcp->drm_crtc->crtc_id, size, red, green, blue); +} + +static void * +crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) +{ + ScreenPtr pScreen = crtc->scrn->pScreen; + PixmapPtr rootpix = pScreen->GetScreenPixmap(pScreen); + + /* + * Use the same depth as for the root pixmap. + * The associated kms fb will be created on demand once this pixmap + * is used as scanout by a crtc. + */ + + return pScreen->CreatePixmap(pScreen, width, height, + rootpix->drawable.depth, 0); +} + +static PixmapPtr +crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) +{ + return (PixmapPtr) data; +} + +static void +crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) +{ + ScreenPtr pScreen = rotate_pixmap->drawable.pScreen; + + pScreen->DestroyPixmap(rotate_pixmap); +} + + +/* + * Cursor functions + */ + +static void +crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) +{ + /* XXX: See if this one is needed, as we only support ARGB cursors */ +} + +static void +crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) +{ + modesettingPtr ms = modesettingPTR(crtc->scrn); + struct crtc_private *crtcp = crtc->driver_private; + + drmModeMoveCursor(ms->fd, crtcp->drm_crtc->crtc_id, x, y); +} + +static void +crtc_load_cursor_argb_kms(xf86CrtcPtr crtc, CARD32 * image) +{ + modesettingPtr ms = modesettingPTR(crtc->scrn); + struct crtc_private *crtcp = crtc->driver_private; + unsigned char *ptr; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + CursorPtr c = config->cursor; + + if (vmwgfx_cursor_bypass(ms->fd, c->bits->xhot, c->bits->yhot) != 0) { + xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, + "Failed to set VMWare cursor bypass.\n"); + } + + if (!crtcp->cursor_bo) { + size_t size = 64*64*4; + crtcp->cursor_bo = vmwgfx_dmabuf_alloc(ms->fd, size); + if (!crtcp->cursor_bo) + return; + crtcp->cursor_handle = crtcp->cursor_bo->handle; + } + + ptr = vmwgfx_dmabuf_map(crtcp->cursor_bo); + if (ptr) { + memcpy(ptr, image, 64*64*4); + vmwgfx_dmabuf_unmap(crtcp->cursor_bo); + } + + if (crtc->cursor_shown) + drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, + crtcp->cursor_handle, 64, 64); + + return; +} + +static void +crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + modesettingPtr ms = modesettingPTR(crtc->scrn); + + /* Older X servers have cursor reference counting bugs leading to use of + * freed memory and consequently random crashes. Should be fixed as of + * xserver 1.8, but this workaround shouldn't hurt anyway. + */ + if (config->cursor) + config->cursor->refcnt++; + + if (ms->cursor) + FreeCursor(ms->cursor, None); + + ms->cursor = config->cursor; + crtc_load_cursor_argb_kms(crtc, image); +} + +static void +crtc_show_cursor(xf86CrtcPtr crtc) +{ + modesettingPtr ms = modesettingPTR(crtc->scrn); + struct crtc_private *crtcp = crtc->driver_private; + + if (crtcp->cursor_bo) + drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, + crtcp->cursor_handle, 64, 64); +} + +static void +crtc_hide_cursor(xf86CrtcPtr crtc) +{ + modesettingPtr ms = modesettingPTR(crtc->scrn); + struct crtc_private *crtcp = crtc->driver_private; + + drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 0, 0, 0); +} + +/** + * Called at vt leave + */ +void +xorg_crtc_cursor_destroy(xf86CrtcPtr crtc) +{ + struct crtc_private *crtcp = crtc->driver_private; + + if (crtcp->cursor_bo) { + vmwgfx_dmabuf_destroy(crtcp->cursor_bo); + crtcp->cursor_bo = NULL; + } +} + +/* + * Misc functions + */ + +static void +crtc_destroy(xf86CrtcPtr crtc) +{ + struct crtc_private *crtcp = crtc->driver_private; + + xorg_crtc_cursor_destroy(crtc); + + drmModeFreeCrtc(crtcp->drm_crtc); + + free(crtcp); + crtc->driver_private = NULL; +} + +static const xf86CrtcFuncsRec crtc_funcs = { + .dpms = crtc_dpms, + .set_mode_major = crtc_set_mode_major, + + .set_cursor_colors = crtc_set_cursor_colors, + .set_cursor_position = crtc_set_cursor_position, + .show_cursor = crtc_show_cursor, + .hide_cursor = crtc_hide_cursor, + .load_cursor_argb = crtc_load_cursor_argb, + + .shadow_create = crtc_shadow_create, + .shadow_allocate = crtc_shadow_allocate, + .shadow_destroy = crtc_shadow_destroy, + + .gamma_set = crtc_gamma_set, + .destroy = crtc_destroy, +}; + +void +xorg_crtc_init(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + xf86CrtcPtr crtc; + drmModeResPtr res; + drmModeCrtcPtr drm_crtc = NULL; + struct crtc_private *crtcp; + int c; + + res = drmModeGetResources(ms->fd); + if (res == 0) { + ErrorF("Failed drmModeGetResources %d\n", errno); + return; + } + + for (c = 0; c < res->count_crtcs; c++) { + drm_crtc = drmModeGetCrtc(ms->fd, res->crtcs[c]); + + if (!drm_crtc) + continue; + + crtc = xf86CrtcCreate(pScrn, &crtc_funcs); + if (crtc == NULL) + goto out; + + crtcp = calloc(1, sizeof(struct crtc_private)); + if (!crtcp) { + xf86CrtcDestroy(crtc); + goto out; + } + + crtcp->drm_crtc = drm_crtc; + + crtc->driver_private = crtcp; + } + + out: + drmModeFreeResources(res); +} + +PixmapPtr +crtc_get_scanout(xf86CrtcPtr crtc) +{ + struct crtc_private *crtcp = crtc->driver_private; + return crtcp->scanout; +} + +/* vim: set sw=4 ts=8 sts=4: */ diff --git a/vmwgfx/vmwgfx_ctrl.c b/vmwgfx/vmwgfx_ctrl.c new file mode 100644 index 0000000..5157f86 --- /dev/null +++ b/vmwgfx/vmwgfx_ctrl.c @@ -0,0 +1,525 @@ +/* + * Copyright 2006-2011 by VMware, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * vmwarectrl.c -- + * + * The implementation of the VMWARE_CTRL protocol extension that + * allows X clients to communicate with the driver. + */ + +#include +#include "dixstruct.h" +#include "extnsionst.h" +#include +#include + +#include "vmwarectrlproto.h" +#include "xf86drm.h" +#include "vmwgfx_driver.h" + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlQueryVersion -- + * + * Implementation of QueryVersion command handler. Initialises and + * sends a reply. + * + * Results: + * Standard response codes. + * + * Side effects: + * Writes reply to client + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareCtrlQueryVersion(ClientPtr client) +{ + xVMwareCtrlQueryVersionReply rep = { 0, }; + register int n; + + REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = VMWARE_CTRL_MAJOR_VERSION; + rep.minorVersion = VMWARE_CTRL_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xVMwareCtrlQueryVersionReply), (char *)&rep); + + return client->noClientException; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlDoSetRes -- + * + * Set the custom resolution into the mode list. + * + * This is done by alternately updating one of two dynamic modes. It is + * done this way because the server gets upset if you try to switch + * to a new resolution that has the same index as the current one. + * + * Results: + * TRUE on success, FALSE otherwise. + * + * Side effects: + * One dynamic mode will be updated if successful. + * + *---------------------------------------------------------------------------- + */ + +static Bool +VMwareCtrlDoSetRes(ScrnInfoPtr pScrn, + CARD32 x, + CARD32 y) +{ +#if 0 + struct vmw_rect rect; + rect.x = 0; + rect.y = 0; + rect.w = x; + rect.h = y; + + vmw_ioctl_update_layout(vmw, 1, &rect); +#endif + + return TRUE; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlSetRes -- + * + * Implementation of SetRes command handler. Initialises and sends a + * reply. + * + * Results: + * Standard response codes. + * + * Side effects: + * Writes reply to client + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareCtrlSetRes(ClientPtr client) +{ + REQUEST(xVMwareCtrlSetResReq); + xVMwareCtrlSetResReply rep = { 0, }; + ScrnInfoPtr pScrn; + ExtensionEntry *ext; + register int n; + + REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq); + + if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) { + return BadMatch; + } + + pScrn = ext->extPrivate; + if (pScrn->scrnIndex != stuff->screen) { + return BadMatch; + } + + if (!VMwareCtrlDoSetRes(pScrn, stuff->x, stuff->y)) { + return BadValue; + } + + rep.type = X_Reply; + rep.length = (sizeof(xVMwareCtrlSetResReply) - sizeof(xGenericReply)) >> 2; + rep.sequenceNumber = client->sequence; + rep.screen = stuff->screen; + rep.x = stuff->x; + rep.y = stuff->y; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.screen, n); + swapl(&rep.x, n); + swapl(&rep.y, n); + } + WriteToClient(client, sizeof(xVMwareCtrlSetResReply), (char *)&rep); + + return client->noClientException; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlDoSetTopology -- + * + * Set the custom topology and set a dynamic mode to the bounding box + * of the passed topology. If a topology is already pending, then do + * nothing but do not return failure. + * + * Results: + * TRUE on success, FALSE otherwise. + * + * Side effects: + * One dynamic mode and the pending xinerama state will be updated if + * successful. + * + *---------------------------------------------------------------------------- + */ + +static Bool +VMwareCtrlDoSetTopology(ScrnInfoPtr pScrn, + xXineramaScreenInfo *extents, + unsigned long number) +{ +#if 0 + struct vmw_rect *rects; + struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); + int i; + + rects = calloc(number, sizeof(*rects)); + if (!rects) + return FALSE; + + for (i = 0; i < number; i++) { + rects[i].x = extents[i].x_org; + rects[i].y = extents[i].y_org; + rects[i].w = extents[i].width; + rects[i].h = extents[i].height; + } + + vmw_ioctl_update_layout(vmw, number, rects); + + free(rects); +#endif + return TRUE; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlSetTopology -- + * + * Implementation of SetTopology command handler. Initialises and sends a + * reply. + * + * Results: + * Standard response codes. + * + * Side effects: + * Writes reply to client + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareCtrlSetTopology(ClientPtr client) +{ + REQUEST(xVMwareCtrlSetTopologyReq); + xVMwareCtrlSetTopologyReply rep = { 0, }; + ScrnInfoPtr pScrn; + ExtensionEntry *ext; + register int n; + xXineramaScreenInfo *extents; + + REQUEST_AT_LEAST_SIZE(xVMwareCtrlSetTopologyReq); + + if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) { + return BadMatch; + } + + pScrn = ext->extPrivate; + if (pScrn->scrnIndex != stuff->screen) { + return BadMatch; + } + + extents = (xXineramaScreenInfo *)(stuff + 1); + if (!VMwareCtrlDoSetTopology(pScrn, extents, stuff->number)) { + return BadValue; + } + + rep.type = X_Reply; + rep.length = (sizeof(xVMwareCtrlSetTopologyReply) - sizeof(xGenericReply)) >> 2; + rep.sequenceNumber = client->sequence; + rep.screen = stuff->screen; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.screen, n); + } + WriteToClient(client, sizeof(xVMwareCtrlSetTopologyReply), (char *)&rep); + + return client->noClientException; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlDispatch -- + * + * Dispatcher for VMWARE_CTRL commands. Calls the correct handler for + * each command type. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of individual command handlers. + * + *---------------------------------------------------------------------------- + */ + +static int +VMwareCtrlDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch(stuff->data) { + case X_VMwareCtrlQueryVersion: + return VMwareCtrlQueryVersion(client); + case X_VMwareCtrlSetRes: + return VMwareCtrlSetRes(client); + case X_VMwareCtrlSetTopology: + return VMwareCtrlSetTopology(client); + } + return BadRequest; +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareCtrlQueryVersion -- + * + * Wrapper for QueryVersion handler that handles input from other-endian + * clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of unswapped implementation. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareCtrlQueryVersion(ClientPtr client) +{ + register int n; + + REQUEST(xVMwareCtrlQueryVersionReq); + REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq); + + swaps(&stuff->length, n); + + return VMwareCtrlQueryVersion(client); +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareCtrlSetRes -- + * + * Wrapper for SetRes handler that handles input from other-endian + * clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of unswapped implementation. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareCtrlSetRes(ClientPtr client) +{ + register int n; + + REQUEST(xVMwareCtrlSetResReq); + REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq); + + swaps(&stuff->length, n); + swapl(&stuff->screen, n); + swapl(&stuff->x, n); + swapl(&stuff->y, n); + + return VMwareCtrlSetRes(client); +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareCtrlSetTopology -- + * + * Wrapper for SetTopology handler that handles input from other-endian + * clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of unswapped implementation. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareCtrlSetTopology(ClientPtr client) +{ + register int n; + + REQUEST(xVMwareCtrlSetTopologyReq); + REQUEST_SIZE_MATCH(xVMwareCtrlSetTopologyReq); + + swaps(&stuff->length, n); + swapl(&stuff->screen, n); + swapl(&stuff->number, n); + /* Each extent is a struct of shorts. */ + SwapRestS(stuff); + + return VMwareCtrlSetTopology(client); +} + + +/* + *---------------------------------------------------------------------------- + * + * SVMwareCtrlDispatch -- + * + * Wrapper for dispatcher that handles input from other-endian clients. + * + * Results: + * Standard response codes. + * + * Side effects: + * Side effects of individual command handlers. + * + *---------------------------------------------------------------------------- + */ + +static int +SVMwareCtrlDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch(stuff->data) { + case X_VMwareCtrlQueryVersion: + return SVMwareCtrlQueryVersion(client); + case X_VMwareCtrlSetRes: + return SVMwareCtrlSetRes(client); + case X_VMwareCtrlSetTopology: + return SVMwareCtrlSetTopology(client); + } + return BadRequest; +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrlResetProc -- + * + * Cleanup handler called when the extension is removed. + * + * Results: + * None + * + * Side effects: + * None + * + *---------------------------------------------------------------------------- + */ + +static void +VMwareCtrlResetProc(ExtensionEntry* extEntry) +{ + /* Currently, no cleanup is necessary. */ +} + + +/* + *---------------------------------------------------------------------------- + * + * VMwareCtrl_ExitInit -- + * + * Initialiser for the VMWARE_CTRL protocol extension. + * + * Results: + * None. + * + * Side effects: + * Protocol extension will be registered if successful. + * + *---------------------------------------------------------------------------- + */ + +void +vmw_ctrl_ext_init(ScrnInfoPtr pScrn) +{ + ExtensionEntry *myext; + + if (!(myext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) { + if (!(myext = AddExtension(VMWARE_CTRL_PROTOCOL_NAME, 0, 0, + VMwareCtrlDispatch, + SVMwareCtrlDispatch, + VMwareCtrlResetProc, + StandardMinorOpcode))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to add VMWARE_CTRL extension\n"); + return; + } + + /* + * For now, only support one screen as that's all the virtual + * hardware supports. + */ + myext->extPrivate = pScrn; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Initialized VMWARE_CTRL extension version %d.%d\n", + VMWARE_CTRL_MAJOR_VERSION, VMWARE_CTRL_MINOR_VERSION); + } +} diff --git a/vmwgfx/vmwgfx_ctrl.h b/vmwgfx/vmwgfx_ctrl.h new file mode 100644 index 0000000..8fedbce --- /dev/null +++ b/vmwgfx/vmwgfx_ctrl.h @@ -0,0 +1,48 @@ +/* + * Copyright 2006 by VMware, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + +/* + * vmwgfx_ctrl.h -- + * + * The definitions used by the VMWARE_CTRL protocol extension that + * allows X clients to communicate with the driver. + */ + + +#ifndef _VMWGFX_CTRL_H_ +#define _VMWGFX_CTRL_H_ + +#define VMWARE_CTRL_PROTOCOL_NAME "VMWARE_CTRL" + +#define VMWARE_CTRL_MAJOR_VERSION 0 +#define VMWARE_CTRL_MINOR_VERSION 2 + +#define X_VMwareCtrlQueryVersion 0 +#define X_VMwareCtrlSetRes 1 +#define X_VMwareCtrlSetTopology 2 + +#endif /* _VMW_CTRL_H_ */ diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c new file mode 100644 index 0000000..748cbc8 --- /dev/null +++ b/vmwgfx/vmwgfx_dri2.c @@ -0,0 +1,373 @@ +/* + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Author: Alan Hourihane + * Author: Jakob Bornecrantz + * Author: Thomas Hellstrom + * + */ + +#include "xorg-server.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "vmwgfx_driver.h" +#include "../saa/saa.h" + +#include "dri2.h" +#include "gcstruct.h" +#include "gc.h" +#include "vmwgfx_saa.h" + +struct vmwgfx_dri2_priv { + unsigned int srf_count; + struct xa_surface *srf[20]; +}; + +DevPrivateKeyRec dri2_pixmap_index; +DevPrivateKeyRec dri2_window_index; + +typedef struct { + int refcount; + PixmapPtr pPixmap; + struct xa_surface *srf; +} *BufferPrivatePtr; + +static Bool +dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int format) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + modesettingPtr ms = modesettingPTR(pScrn); + BufferPrivatePtr private = buffer->driverPrivate; + PixmapPtr pPixmap; + struct vmwgfx_saa_pixmap *vpix; + struct xa_surface *srf = NULL; + unsigned int cpp = 4; + + if (pDraw->type == DRAWABLE_PIXMAP) + pPixmap = (PixmapPtr) pDraw; + else + pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr) pDraw); + + vpix = vmwgfx_saa_pixmap(pPixmap); + private->refcount = 0; + + switch (buffer->attachment) { + default: + if (buffer->attachment != DRI2BufferFakeFrontLeft || + &pPixmap->drawable != pDraw) { + + pPixmap = (*pScreen->CreatePixmap)(pScreen, + pDraw->width, + pDraw->height, + pDraw->depth, + 0); + if (pPixmap == NullPixmap) + return FALSE; + + private->pPixmap = pPixmap; + vpix = vmwgfx_saa_pixmap(pPixmap); + } + break; + case DRI2BufferFrontLeft: + if (&pPixmap->drawable == pDraw) + break; + buffer->name = 0; + buffer->pitch = 0; + buffer->cpp = cpp; + buffer->driverPrivate = private; + buffer->flags = 0; /* not tiled */ + buffer->format = 0; + if (!private->pPixmap) { + private->pPixmap = pPixmap; + pPixmap->refcnt++; + } + return TRUE; + case DRI2BufferStencil: + case DRI2BufferDepthStencil: + srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height, + 32, xa_type_zs, xa_format_unknown, + XA_FLAG_SHARED ); + if (!srf) + srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height, + 32, xa_type_sz, xa_format_unknown, + XA_FLAG_SHARED ); + if (!srf) + return FALSE; + + break; + case DRI2BufferDepth: + srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height, + (format) ? format: pDraw->depth, + xa_type_z, xa_format_unknown, + XA_FLAG_SHARED); + if (!srf) + return FALSE; + break; + } + + if (!private->pPixmap) { + private->pPixmap = pPixmap; + pPixmap->refcnt++; + } + + if (!srf) { + if (!vmwgfx_pixmap_validate_hw(pPixmap, NULL, + XA_FLAG_SHARED | XA_FLAG_RENDER_TARGET, + 0)) + return FALSE; + + srf = vpix->hw; + + /* + * Compiz workaround. See vmwgfx_dirty(); + */ + + vpix->hw_is_dri2_fronts++; + private->refcount++; + } + + private->srf = srf; + if (xa_surface_handle(srf, &buffer->name, &buffer->pitch) != 0) + return FALSE; + + buffer->cpp = cpp; + buffer->driverPrivate = private; + buffer->flags = 0; /* not tiled */ + buffer->format = format; + private->refcount++; + + return TRUE; +} + +static void +dri2_do_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer) +{ + BufferPrivatePtr private = buffer->driverPrivate; + struct xa_surface *srf = private->srf; + ScreenPtr pScreen = pDraw->pScreen; + + if (--private->refcount == 0 && srf) { + xa_surface_destroy(srf); + } + + /* + * Compiz workaround. See vmwgfx_dirty(); + */ + + if (private->refcount == 1) { + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(private->pPixmap); + if (--vpix->hw_is_dri2_fronts == 0) + vmwgfx_remove_dri2_list(vpix); + } + + private->srf = NULL; + pScreen->DestroyPixmap(private->pPixmap); +} + + +static DRI2Buffer2Ptr +dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, unsigned int format) +{ + DRI2Buffer2Ptr buffer; + BufferPrivatePtr private; + + buffer = calloc(1, sizeof *buffer); + if (!buffer) + return NULL; + + private = calloc(1, sizeof *private); + if (!private) { + goto fail; + } + + buffer->attachment = attachment; + buffer->driverPrivate = private; + + if (dri2_do_create_buffer(pDraw, buffer, format)) + return buffer; + + free(private); +fail: + free(buffer); + return NULL; +} + +static void +dri2_destroy_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer) +{ + /* So far it is safe to downcast a DRI2Buffer2Ptr to DRI2BufferPtr */ + dri2_do_destroy_buffer(pDraw, (DRI2BufferPtr)buffer); + + free(buffer->driverPrivate); + free(buffer); +} + +static void +dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, + DRI2Buffer2Ptr pDestBuffer, DRI2Buffer2Ptr pSrcBuffer) +{ + + + ScreenPtr pScreen = pDraw->pScreen; + BufferPrivatePtr dst_priv = pDestBuffer->driverPrivate; + BufferPrivatePtr src_priv = pSrcBuffer->driverPrivate; + DrawablePtr src_draw; + DrawablePtr dst_draw; + RegionPtr myClip; + GCPtr gc; + + if (pSrcBuffer->attachment == DRI2BufferFrontLeft && + pDestBuffer->attachment == DRI2BufferFakeFrontLeft) + LogMessage(X_ERROR, "glxwaitx\n"); + + /* + * In driCreateBuffers we dewrap windows into the + * backing pixmaps in order to get to the texture. + * We need to use the real drawable in CopyArea + * so that cliprects and offsets are correct. + */ + src_draw = (pSrcBuffer->attachment == DRI2BufferFrontLeft) ? pDraw : + &src_priv->pPixmap->drawable; + dst_draw = (pDestBuffer->attachment == DRI2BufferFrontLeft) ? pDraw : + &dst_priv->pPixmap->drawable; + + /* + * The clients implements glXWaitX with a copy front to fake and then + * waiting on the server to signal its completion of it. While + * glXWaitGL is a client side flush and a copy from fake to front. + * This is how it is done in the DRI2 protocol, how ever depending + * which type of drawables the server does things a bit differently + * then what the protocol says as the fake and front are the same. + * + * for pixmaps glXWaitX is a server flush. + * for pixmaps glXWaitGL is a client flush. + * for windows glXWaitX is a copy from front to fake then a server flush. + * for windows glXWaitGL is a client flush then a copy from fake to front. + * + * XXX in the windows case this code always flushes but that isn't a + * must in the glXWaitGL case but we don't know if this is a glXWaitGL + * or a glFlush/glFinish call. + */ + if (dst_priv->pPixmap == src_priv->pPixmap) { + /* pixmap glXWaitX */ + if (pSrcBuffer->attachment == DRI2BufferFrontLeft && + pDestBuffer->attachment == DRI2BufferFakeFrontLeft) { + LogMessage(X_INFO, "dri2 Validate hw.\n"); + vmwgfx_pixmap_validate_hw(src_priv->pPixmap, NULL, + XA_FLAG_SHARED | XA_FLAG_RENDER_TARGET, + 0); + return; + } + /* pixmap glXWaitGL */ + if (pDestBuffer->attachment == DRI2BufferFrontLeft && + pSrcBuffer->attachment == DRI2BufferFakeFrontLeft) { + return; + } else { + vmwgfx_flush_dri2(pScreen); + return; + } + } + + gc = GetScratchGC(pDraw->depth, pScreen); + myClip = REGION_CREATE(pScreen, REGION_RECTS(pRegion), + REGION_NUM_RECTS(pRegion)); + (*gc->funcs->ChangeClip) (gc, CT_REGION, myClip, 0); + ValidateGC(dst_draw, gc); + + /* + * Damage the src drawable in order for damageCopyArea to pick up + * that something changed. + */ + DamageRegionAppend(src_draw, pRegion); + saa_drawable_dirty(src_draw, TRUE, pRegion); + DamageRegionProcessPending(src_draw); + + /* + * Call CopyArea. This usually means a call to damageCopyArea that + * is wrapping saa_copy_area. The damageCopyArea function will make + * sure the destination drawable is appropriately damaged. + */ + (*gc->ops->CopyArea)(src_draw, dst_draw, gc, + 0, 0, pDraw->width, pDraw->height, 0, 0); + + /* + * FreeScratchGC will free myClip as well. + */ + myClip = NULL; + FreeScratchGC(gc); +} + + +Bool +xorg_dri2_init(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + modesettingPtr ms = modesettingPTR(pScrn); + DRI2InfoRec dri2info; + int major, minor; + + if (xf86LoaderCheckSymbol("DRI2Version")) { + DRI2Version(&major, &minor); + } else { + /* Assume version 1.0 */ + major = 1; + minor = 0; + } + + if (!dixRegisterPrivateKey(&dri2_pixmap_index, PRIVATE_PIXMAP, 0)) { + LogMessage(X_ERROR, "Failed to register vmwgfx dri2 private.\n"); + return FALSE; + } + + if (!dixRegisterPrivateKey(&dri2_window_index, PRIVATE_WINDOW, 0)) { + LogMessage(X_ERROR, "Failed to register vmwgfx dri2 private.\n"); + return FALSE; + } + + dri2info.version = min(DRI2INFOREC_VERSION, 3); + dri2info.fd = ms->fd; + + dri2info.driverName = pScrn->driverName; + dri2info.deviceName = "/dev/dri/card0"; /* FIXME */ + + dri2info.CreateBuffer = dri2_create_buffer; + dri2info.DestroyBuffer = dri2_destroy_buffer; + + dri2info.CopyRegion = dri2_copy_region; + dri2info.Wait = NULL; + + return DRI2ScreenInit(pScreen, &dri2info); +} + +void +xorg_dri2_close(ScreenPtr pScreen) +{ + DRI2CloseScreen(pScreen); +} + +/* vim: set sw=4 ts=8 sts=4: */ diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c new file mode 100644 index 0000000..edf384d --- /dev/null +++ b/vmwgfx/vmwgfx_driver.c @@ -0,0 +1,947 @@ +/* + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Author: Alan Hourihane + * Author: Jakob Bornecrantz + * Author: Thomas Hellstrom + */ + + +#include "xorg-server.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "compiler.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "mipointer.h" +#include "micmap.h" +#include +#include "fb.h" +#include "edid.h" +#include "xf86i2c.h" +#include "xf86Crtc.h" +#include "miscstruct.h" +#include "dixstruct.h" +#include "xf86cmap.h" +#include "xf86xv.h" +#include "xorgVersion.h" +#ifndef XSERVER_LIBPCIACCESS +#error "libpciaccess needed" +#endif + +#include + +#include "vmwgfx_driver.h" + +#include +#include "vmwgfx_saa.h" + +/* + * Some macros to deal with function wrapping. + */ +#define vmwgfx_wrap(priv, real, mem, func) {\ + (priv)->saved_##mem = (real)->mem; \ + (real)->mem = func; \ +} + +#define vmwgfx_unwrap(priv, real, mem) {\ + (real)->mem = (priv)->saved_##mem; \ +} + +#define vmwgfx_swap(priv, real, mem) {\ + void *tmp = (priv)->saved_##mem; \ + (priv)->saved_##mem = (real)->mem; \ + (real)->mem = tmp; \ +} + +/* + * Functions and symbols exported to Xorg via pointers. + */ + +static Bool drv_pre_init(ScrnInfoPtr pScrn, int flags); +static Bool drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, + char **argv); +static Bool drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags); +static void drv_adjust_frame(int scrnIndex, int x, int y, int flags); +static Bool drv_enter_vt(int scrnIndex, int flags); +static void drv_leave_vt(int scrnIndex, int flags); +static void drv_free_screen(int scrnIndex, int flags); +static ModeStatus drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, + int flags); + +extern void xorg_tracker_set_functions(ScrnInfoPtr scrn); +extern const OptionInfoRec * xorg_tracker_available_options(int chipid, + int busid); + + +typedef enum +{ + OPTION_SW_CURSOR, + OPTION_2D_ACCEL, + OPTION_DEBUG_FALLBACK, + OPTION_THROTTLE_SWAP, + OPTION_THROTTLE_DIRTY, + OPTION_3D_ACCEL +} drv_option_enums; + +static const OptionInfoRec drv_options[] = { + {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_2D_ACCEL, "2DAccel", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_DEBUG_FALLBACK, "DebugFallback", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_THROTTLE_SWAP, "SwapThrottling", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_THROTTLE_DIRTY, "DirtyThrottling", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_3D_ACCEL, "3DAccel", OPTV_BOOLEAN, {0}, FALSE}, + {-1, NULL, OPTV_NONE, {0}, FALSE} +}; + + +/* + * Exported Xorg driver functions to winsys + */ + +const OptionInfoRec * +xorg_tracker_available_options(int chipid, int busid) +{ + return drv_options; +} + +void +xorg_tracker_set_functions(ScrnInfoPtr scrn) +{ + scrn->PreInit = drv_pre_init; + scrn->ScreenInit = drv_screen_init; + scrn->SwitchMode = drv_switch_mode; + scrn->FreeScreen = drv_free_screen; + scrn->ValidMode = drv_valid_mode; +} + +/* + * Internal function definitions + */ + +static Bool drv_close_screen(int scrnIndex, ScreenPtr pScreen); + +/* + * Internal functions + */ + +static Bool +drv_get_rec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate) + return TRUE; + + pScrn->driverPrivate = xnfcalloc(1, sizeof(modesettingRec)); + + return TRUE; +} + +static void +drv_free_rec(ScrnInfoPtr pScrn) +{ + if (!pScrn) + return; + + if (!pScrn->driverPrivate) + return; + + free(pScrn->driverPrivate); + + pScrn->driverPrivate = NULL; +} + +static void +drv_probe_ddc(ScrnInfoPtr pScrn, int index) +{ + ConfiguredMonitor = NULL; +} + +static Bool +drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height) +{ + modesettingPtr ms = modesettingPTR(pScrn); + ScreenPtr pScreen = pScrn->pScreen; + int old_width, old_height; + PixmapPtr rootPixmap; + + if (width == pScrn->virtualX && height == pScrn->virtualY) + return TRUE; + + if (ms->check_fb_size) { + size_t size = width*(pScrn->bitsPerPixel / 8) * height + 1024; + + if (size > ms->max_fb_size) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Requested framebuffer size %dx%dx%d will not fit " + "in display memory.\n", + width, height, pScrn->bitsPerPixel); + return FALSE; + } + } + + old_width = pScrn->virtualX; + old_height = pScrn->virtualY; + pScrn->virtualX = width; + pScrn->virtualY = height; + + /* ms->create_front_buffer will remove the old front buffer */ + + rootPixmap = pScreen->GetScreenPixmap(pScreen); + vmwgfx_disable_scanout(pScrn); + if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL)) + goto error_modify; + + pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8); + + xf86SetDesiredModes(pScrn); + return TRUE; + + /* + * FIXME: Try out this error recovery path and fix problems. + + */ + //error_create: + if (!pScreen->ModifyPixmapHeader(rootPixmap, old_width, old_height, -1, -1, -1, NULL)) + FatalError("failed to resize rootPixmap error path\n"); + + pScrn->displayWidth = rootPixmap->devKind / + (rootPixmap->drawable.bitsPerPixel / 8); + + +error_modify: + pScrn->virtualX = old_width; + pScrn->virtualY = old_height; + + if (xf86SetDesiredModes(pScrn)) + return FALSE; + + FatalError("failed to setup old framebuffer\n"); + return FALSE; +} + +static const xf86CrtcConfigFuncsRec crtc_config_funcs = { + .resize = drv_crtc_resize +}; + +static Bool +drv_init_drm(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + + /* deal with server regeneration */ + if (ms->fd < 0) { + char *BusID; + + BusID = malloc(64); + sprintf(BusID, "PCI:%d:%d:%d", + ((ms->PciInfo->domain << 8) | ms->PciInfo->bus), + ms->PciInfo->dev, ms->PciInfo->func + ); + + + ms->fd = drmOpen("vmwgfx", BusID); + ms->isMaster = TRUE; + free(BusID); + + if (ms->fd >= 0) + return TRUE; + + return FALSE; + } + + return TRUE; +} + +static Bool +drv_pre_init(ScrnInfoPtr pScrn, int flags) +{ + xf86CrtcConfigPtr xf86_config; + modesettingPtr ms; + rgb defaultWeight = { 0, 0, 0 }; + EntityInfoPtr pEnt; + EntPtr msEnt = NULL; + Bool use3D; + + if (pScrn->numEntities != 1) + return FALSE; + + pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + + if (flags & PROBE_DETECT) { + drv_probe_ddc(pScrn, pEnt->index); + return TRUE; + } + + pScrn->driverPrivate = NULL; + + /* Allocate driverPrivate */ + if (!drv_get_rec(pScrn)) + return FALSE; + + ms = modesettingPTR(pScrn); + ms->pEnt = pEnt; + + pScrn->displayWidth = 640; /* default it */ + + if (ms->pEnt->location.type != BUS_PCI) + return FALSE; + + ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index); + + /* Allocate an entity private if necessary */ + if (xf86IsEntityShared(pScrn->entityList[0])) { + FatalError("Entity"); +#if 0 + msEnt = xf86GetEntityPrivate(pScrn->entityList[0], + modesettingEntityIndex)->ptr; + ms->entityPrivate = msEnt; +#else + (void)msEnt; +#endif + } else + ms->entityPrivate = NULL; + + if (xf86IsEntityShared(pScrn->entityList[0])) { + if (xf86IsPrimInitDone(pScrn->entityList[0])) { + /* do something */ + } else { + xf86SetPrimInitDone(pScrn->entityList[0]); + } + } + + ms->fd = -1; + if (!drv_init_drm(pScrn)) + return FALSE; + + ms->check_fb_size = (vmwgfx_max_fb_size(ms->fd, &ms->max_fb_size) == 0); + + pScrn->monitor = pScrn->confScreen->monitor; + pScrn->progClock = TRUE; + pScrn->rgbBits = 8; + + if (!xf86SetDepthBpp + (pScrn, 0, 0, 0, + PreferConvert24to32 | SupportConvert24to32 | Support32bppFb)) + return FALSE; + + switch (pScrn->depth) { + case 8: + case 15: + case 16: + case 24: + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by the driver\n", + pScrn->depth); + return FALSE; + } + xf86PrintDepthBpp(pScrn); + + if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) + return FALSE; + if (!xf86SetDefaultVisual(pScrn, -1)) + return FALSE; + + /* Process the options */ + xf86CollectOptions(pScrn, NULL); + if (!(ms->Options = malloc(sizeof(drv_options)))) + return FALSE; + memcpy(ms->Options, drv_options, sizeof(drv_options)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options); + + use3D = TRUE; + ms->from_3D = xf86GetOptValBool(ms->Options, OPTION_3D_ACCEL, + &use3D) ? + X_CONFIG : X_PROBED; + + ms->no3D = !use3D; + + /* Allocate an xf86CrtcConfig */ + xf86CrtcConfigInit(pScrn, &crtc_config_funcs); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + /* get max width and height */ + { + drmModeResPtr res; + int max_width, max_height; + + res = drmModeGetResources(ms->fd); + max_width = res->max_width; + max_height = res->max_height; + +#if 0 /* Gallium fix */ + if (ms->screen) { + int max; + + max = ms->screen->get_param(ms->screen, + PIPE_CAP_MAX_TEXTURE_2D_LEVELS); + max = 1 << (max - 1); + max_width = max < max_width ? max : max_width; + max_height = max < max_height ? max : max_height; + } +#endif + + xf86CrtcSetSizeRange(pScrn, res->min_width, + res->min_height, max_width, max_height); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Min width %d, Max Width %d.\n", + res->min_width, max_width); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Min height %d, Max Height %d.\n", + res->min_height, max_height); + drmModeFreeResources(res); + } + + + if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) { + ms->SWCursor = TRUE; + } + + xorg_crtc_init(pScrn); + xorg_output_init(pScrn); + + if (!xf86InitialConfiguration(pScrn, TRUE)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + return FALSE; + } + + /* + * If the driver can do gamma correction, it should call xf86SetGamma() here. + */ + { + Gamma zeros = { 0.0, 0.0, 0.0 }; + + if (!xf86SetGamma(pScrn, zeros)) { + return FALSE; + } + } + + if (pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); + return FALSE; + } + + pScrn->currentMode = pScrn->modes; + + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); + + /* Load the required sub modules */ + if (!xf86LoadSubModule(pScrn, "fb")) + return FALSE; + +#ifdef DRI2 + if (!xf86LoadSubModule(pScrn, "dri2")) + return FALSE; +#endif + + return TRUE; +} + +static Bool +vmwgfx_scanout_update(int drm_fd, int fb_id, RegionPtr dirty) +{ + unsigned num_cliprects = REGION_NUM_RECTS(dirty); + drmModeClip *clip = alloca(num_cliprects * sizeof(drmModeClip)); + BoxPtr rect = REGION_RECTS(dirty); + int i, ret; + + if (!num_cliprects) + return TRUE; + + for (i = 0; i < num_cliprects; i++, rect++) { + clip[i].x1 = rect->x1; + clip[i].y1 = rect->y1; + clip[i].x2 = rect->x2; + clip[i].y2 = rect->y2; + } + + ret = drmModeDirtyFB(drm_fd, fb_id, clip, num_cliprects); + if (ret) + LogMessage(X_ERROR, "%s: failed to send dirty (%i, %s)\n", + __func__, ret, strerror(-ret)); + return (ret == 0); +} + +static Bool +vmwgfx_scanout_present(ScreenPtr pScreen, int drm_fd, + struct vmwgfx_saa_pixmap *vpix, + RegionPtr dirty) +{ + uint32_t handle; + unsigned int dummy; + + if (!REGION_NOTEMPTY(pScreen, dirty)) + return TRUE; + + if (!vpix->hw) { + LogMessage(X_ERROR, "No surface to present from.\n"); + return FALSE; + } + + if (xa_surface_handle(vpix->hw, &handle, &dummy) != 0) { + LogMessage(X_ERROR, "Could not get present surface handle.\n"); + return FALSE; + } + + if (vmwgfx_present(drm_fd, 0, 0, dirty, handle) != 0) { + LogMessage(X_ERROR, "Could not get present surface handle.\n"); + return FALSE; + } + + return TRUE; +} + +void xorg_flush(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + modesettingPtr ms = modesettingPTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + PixmapPtr pixmap = NULL; + struct vmwgfx_saa_pixmap *vpix; + int i; + xf86CrtcPtr crtc; + PixmapPtr *pixmaps = calloc(config->num_crtc, sizeof(*pixmaps)); + unsigned int num_scanout = 0; + unsigned int j; + + if (!pixmaps) { + LogMessage(X_ERROR, "Failed memory allocation during screen " + "update.\n"); + return; + } + + /* + * Get an array of pixmaps from which we scan out. + */ + for (i=0; inum_crtc; ++i) { + crtc = config->crtc[i]; + if (crtc->enabled) { + pixmap = crtc_get_scanout(crtc); + if (pixmap) { + unsigned int j; + + /* + * Remove duplicates. + */ + for (j=0; jfb_id != -1) { + if (vpix->pending_update) { + (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id, + vpix->pending_update); + REGION_SUBTRACT(pScreen, vpix->dirty_present, + vpix->dirty_present, vpix->pending_update); + REGION_EMPTY(pScreen, vpix->pending_update); + } + if (vpix->pending_present) { + (void) vmwgfx_scanout_present(pScreen, ms->fd, vpix, + vpix->pending_present); + REGION_SUBTRACT(pScreen, vpix->dirty_present, + vpix->dirty_present, vpix->pending_present); + REGION_EMPTY(pScreen, vpix->pending_present); + } + } + } + free(pixmaps); +} + +static void drv_block_handler(int i, pointer blockData, pointer pTimeout, + pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + modesettingPtr ms = modesettingPTR(xf86Screens[pScreen->myNum]); + + vmwgfx_swap(ms, pScreen, BlockHandler); + pScreen->BlockHandler(i, blockData, pTimeout, pReadmask); + vmwgfx_swap(ms, pScreen, BlockHandler); + + xorg_flush(pScreen); +} + +static Bool +drv_create_screen_resources(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + modesettingPtr ms = modesettingPTR(pScrn); + Bool ret; + + vmwgfx_swap(ms, pScreen, CreateScreenResources); + ret = pScreen->CreateScreenResources(pScreen); + vmwgfx_swap(ms, pScreen, CreateScreenResources); + + drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + return drv_enter_vt(pScreen->myNum, 1); +} + +static Bool +drv_set_master(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + + if (!ms->isMaster && drmSetMaster(ms->fd) != 0) { + if (errno == EINVAL) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "drmSetMaster failed: 2.6.29 or newer kernel required for " + "multi-server DRI\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "drmSetMaster failed: %s\n", strerror(errno)); + } + return FALSE; + } + + ms->isMaster = TRUE; + return TRUE; +} + + +static void drv_load_palette(ScrnInfoPtr pScrn, int numColors, + int *indices, LOCO *colors, VisualPtr pVisual) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + modesettingPtr ms = modesettingPTR(pScrn); + int index, j, i; + int c; + + switch(pScrn->depth) { + case 15: + for (i = 0; i < numColors; i++) { + index = indices[i]; + for (j = 0; j < 8; j++) { + ms->lut_r[index * 8 + j] = colors[index].red << 8; + ms->lut_g[index * 8 + j] = colors[index].green << 8; + ms->lut_b[index * 8 + j] = colors[index].blue << 8; + } + } + break; + case 16: + for (i = 0; i < numColors; i++) { + index = indices[i]; + + if (index < 32) { + for (j = 0; j < 8; j++) { + ms->lut_r[index * 8 + j] = colors[index].red << 8; + ms->lut_b[index * 8 + j] = colors[index].blue << 8; + } + } + + for (j = 0; j < 4; j++) { + ms->lut_g[index * 4 + j] = colors[index].green << 8; + } + } + break; + default: + for (i = 0; i < numColors; i++) { + index = indices[i]; + ms->lut_r[index] = colors[index].red << 8; + ms->lut_g[index] = colors[index].green << 8; + ms->lut_b[index] = colors[index].blue << 8; + } + break; + } + + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + /* Make the change through RandR */ +#ifdef RANDR_12_INTERFACE + if (crtc->randr_crtc) + RRCrtcGammaSet(crtc->randr_crtc, ms->lut_r, ms->lut_g, ms->lut_b); + else +#endif + crtc->funcs->gamma_set(crtc, ms->lut_r, ms->lut_g, ms->lut_b, 256); + } +} + + +static Bool +drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + modesettingPtr ms = modesettingPTR(pScrn); + VisualPtr visual; + + if (!drv_set_master(pScrn)) + return FALSE; + + pScrn->pScreen = pScreen; + + /* HW dependent - FIXME */ + pScrn->displayWidth = pScrn->virtualX; + + miClearVisualTypes(); + + if (!miSetVisualTypes(pScrn->depth, + miGetDefaultVisualMask(pScrn->depth), + pScrn->rgbBits, pScrn->defaultVisual)) + return FALSE; + + if (!miSetPixmapDepths()) + return FALSE; + + pScrn->memPhysBase = 0; + pScrn->fbOffset = 0; + + if (!fbScreenInit(pScreen, NULL, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth, pScrn->bitsPerPixel)) + return FALSE; + + if (pScrn->bitsPerPixel > 8) { + /* Fixup RGB ordering */ + visual = pScreen->visuals + pScreen->numVisuals; + while (--visual >= pScreen->visuals) { + 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; + } + } + } + + fbPictureInit(pScreen, NULL, 0); + + vmwgfx_wrap(ms, pScreen, BlockHandler, drv_block_handler); + vmwgfx_wrap(ms, pScreen, CreateScreenResources, + drv_create_screen_resources); + + xf86SetBlackWhitePixels(pScreen); + + ms->accelerate_2d = xf86ReturnOptValBool(ms->Options, OPTION_2D_ACCEL, FALSE); + ms->debug_fallback = xf86ReturnOptValBool(ms->Options, OPTION_DEBUG_FALLBACK, ms->accelerate_2d); + + vmw_ctrl_ext_init(pScrn); + + ms->xat = xa_tracker_create(ms->fd); + if (!ms->xat) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to initialize Gallium3D Xa. No 3D available.\n"); + + if (!vmwgfx_saa_init(pScreen, ms->fd, ms->xat, &xorg_flush)) { + FatalError("Failed to initialize SAA.\n"); + } + +#ifdef DRI2 + ms->dri2_available = FALSE; + if (ms->xat) { + ms->dri2_available = xorg_dri2_init(pScreen); + if (!ms->dri2_available) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to initialize DRI2. " + "No direct rendring available.\n"); + } +#endif + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "#################################\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "# Useful debugging info follows #\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "#################################\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using libkms backend.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D Acceleration is %s.\n", + ms->accelerate_2d ? "enabled" : "disabled"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Fallback debugging is %s.\n", + ms->debug_fallback ? "enabled" : "disabled"); +#ifdef DRI2 + xf86DrvMsg(pScrn->scrnIndex, ms->from_3D, "3D Acceleration is disabled.\n"); +#else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D Acceleration is disabled.\n"); +#endif + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n"); + + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + xf86SetSilkenMouse(pScreen); + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + /* Need to extend HWcursor support to handle mask interleave */ + if (!ms->SWCursor) + xf86_cursors_init(pScreen, 64, 64, + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | + HARDWARE_CURSOR_ARGB | + HARDWARE_CURSOR_UPDATE_UNHIDDEN); + + /* Must force it before EnterVT, so we are in control of VT and + * later memory should be bound when allocating, e.g rotate_mem */ + pScrn->vtSema = TRUE; + + pScreen->SaveScreen = xf86SaveScreen; + vmwgfx_wrap(ms, pScreen, CloseScreen, drv_close_screen); + + if (!xf86CrtcScreenInit(pScreen)) + return FALSE; + + if (!miCreateDefColormap(pScreen)) + return FALSE; + if (!xf86HandleColormaps(pScreen, 256, 8, drv_load_palette, NULL, + CMAP_PALETTED_TRUECOLOR | + CMAP_RELOAD_ON_MODE_SWITCH)) + return FALSE; + + xf86DPMSInit(pScreen, xf86DPMSSet, 0); + + if (serverGeneration == 1) + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + + + vmwgfx_wrap(ms, pScrn, EnterVT, drv_enter_vt); + vmwgfx_wrap(ms, pScrn, LeaveVT, drv_leave_vt); + vmwgfx_wrap(ms, pScrn, AdjustFrame, drv_adjust_frame); + + /* + * Must be called _after_ function wrapping. + */ + xorg_xv_init(pScreen); + + return TRUE; +} + +static void +drv_adjust_frame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output = config->output[config->compat_output]; + xf86CrtcPtr crtc = output->crtc; + + if (crtc && crtc->enabled) { + // crtc->funcs->set_mode_major(crtc, pScrn->currentMode, + // RR_Rotate_0, x, y); + crtc->x = output->initial_x + x; + crtc->y = output->initial_y + y; + } +} + +static void +drv_free_screen(int scrnIndex, int flags) +{ + drv_free_rec(xf86Screens[scrnIndex]); +} + +static void +drv_leave_vt(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + modesettingPtr ms = modesettingPTR(pScrn); + + vmwgfx_cursor_bypass(ms->fd, 0, 0); + vmwgfx_disable_scanout(pScrn); + + if (drmDropMaster(ms->fd)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "drmDropMaster failed: %s\n", strerror(errno)); + + ms->isMaster = FALSE; + pScrn->vtSema = FALSE; +} + +/* + * This gets called when gaining control of the VT, and from ScreenInit(). + */ +static Bool +drv_enter_vt(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + if (!drv_set_master(pScrn)) + return FALSE; + + if (!xf86SetDesiredModes(pScrn)) + return FALSE; + + return TRUE; +} + +static Bool +drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); +} + +static Bool +drv_close_screen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + modesettingPtr ms = modesettingPTR(pScrn); + + if (ms->cursor) { + FreeCursor(ms->cursor, None); + ms->cursor = NULL; + } + +#ifdef DRI2 + if (ms->dri2_available) + xorg_dri2_close(pScreen); +#endif + + if (pScrn->vtSema) + pScrn->LeaveVT(scrnIndex, 0); + + pScrn->vtSema = FALSE; + + vmwgfx_unwrap(ms, pScrn, EnterVT); + vmwgfx_unwrap(ms, pScrn, LeaveVT); + vmwgfx_unwrap(ms, pScrn, AdjustFrame); + vmwgfx_unwrap(ms, pScreen, CloseScreen); + vmwgfx_unwrap(ms, pScreen, BlockHandler); + vmwgfx_unwrap(ms, pScreen, CreateScreenResources); + + if (ms->xat) + xa_tracker_destroy(ms->xat); + + return (*pScreen->CloseScreen) (scrnIndex, pScreen); +} + +static ModeStatus +drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + return MODE_OK; +} + +/* vim: set sw=4 ts=8 sts=4: */ diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h new file mode 100644 index 0000000..4339fb7 --- /dev/null +++ b/vmwgfx/vmwgfx_driver.h @@ -0,0 +1,167 @@ +/* + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright n + * Author: Jakob Bornecrantz + * Author: Thomas Hellstrom + */ + +#ifndef _VMWGFX_DRIVER_H_ +#define _VMWGFX_DRIVER_H_ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg); +#define debug_printf(...) + +typedef struct +{ + int lastInstance; + int refCount; + ScrnInfoPtr pScrn_1; + ScrnInfoPtr pScrn_2; +} EntRec, *EntPtr; + +#define XORG_NR_FENCES 3 + +enum xorg_throttling_reason { + THROTTLE_RENDER, + THROTTLE_SWAP +}; + +typedef struct _modesettingRec +{ + /* drm */ + int fd; + + /* X */ + EntPtr entityPrivate; + + int Chipset; + EntityInfoPtr pEnt; + struct pci_device *PciInfo; + + /* Accel */ + Bool accelerate_2d; + Bool debug_fallback; + + Bool noAccel; + Bool SWCursor; + CursorPtr cursor; + Bool no3D; + Bool from_3D; + Bool isMaster; + + /* Broken-out options. */ + OptionInfoPtr Options; + + ScreenBlockHandlerProcPtr saved_BlockHandler; + CreateScreenResourcesProcPtr saved_CreateScreenResources; + CloseScreenProcPtr saved_CloseScreen; + Bool (*saved_EnterVT)(int, int); + void (*saved_LeaveVT)(int, int); + void (*saved_AdjustFrame)(int, int, int, int); + + uint16_t lut_r[256], lut_g[256], lut_b[256]; + + Bool check_fb_size; + size_t max_fb_size; + + struct xa_tracker *xat; +#ifdef DRI2 + Bool dri2_available; +#endif +} modesettingRec, *modesettingPtr; + +#define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate)) + +void xorg_flush(ScreenPtr pScreen); +/*********************************************************************** + * xorg_dri2.c + */ +Bool +xorg_dri2_init(ScreenPtr pScreen); + +void +xorg_dri2_close(ScreenPtr pScreen); + + +/*********************************************************************** + * xorg_crtc.c + */ +void +xorg_crtc_init(ScrnInfoPtr pScrn); + +void +xorg_crtc_cursor_destroy(xf86CrtcPtr crtc); + +void +vmwgfx_disable_scanout(ScrnInfoPtr pScrn); + +PixmapPtr +crtc_get_scanout(xf86CrtcPtr crtc); + + +/*********************************************************************** + * xorg_output.c + */ +void +xorg_output_init(ScrnInfoPtr pScrn); + +unsigned +xorg_output_get_id(xf86OutputPtr output); + + +/*********************************************************************** + * xorg_xv.c + */ +void +xorg_xv_init(ScreenPtr pScreen); + +XF86VideoAdaptorPtr +vmw_video_init_adaptor(ScrnInfoPtr pScrn); +void +vmw_video_free_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports); + +int +vmwgfx_present(int drm_fd, unsigned int dst_x, unsigned int dst_y, + RegionPtr region, uint32_t handle); + +void +vmw_ctrl_ext_init(ScrnInfoPtr pScrn); + +#endif /* _XORG_TRACKER_H_ */ diff --git a/vmwgfx/vmwgfx_drmi.c b/vmwgfx/vmwgfx_drmi.c new file mode 100644 index 0000000..3add305 --- /dev/null +++ b/vmwgfx/vmwgfx_drmi.c @@ -0,0 +1,507 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Jakob Bornecrantz + * Author: Thomas Hellstrom + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include "vmwgfx_drmi.h" + +#define uint32 uint32_t +#define int32 int32_t +#define uint16 uint16_t +#define uint8 uint8_t + +#include "svga3d_reg.h" +#include "vmwgfx_driver.h" + +static int +vmwgfx_fence_wait(int drm_fd, uint64_t seq) +{ + struct drm_vmw_fence_wait_arg farg; + memset(&farg, 0, sizeof(farg)); + + farg.sequence = seq; + farg.cookie_valid = 0; + + return drmCommandWriteRead(drm_fd, DRM_VMW_FENCE_WAIT, &farg, + sizeof(farg)); +} + +int +vmwgfx_present_readback(int drm_fd, RegionPtr region) +{ + BoxPtr clips = REGION_RECTS(region); + unsigned int num_clips = REGION_NUM_RECTS(region); + struct drm_vmw_execbuf_arg arg; + struct drm_vmw_fence_rep rep; + int ret; + unsigned int size; + unsigned i; + SVGA3dRect *cr; + + struct { + SVGA3dCmdHeader header; + SVGA3dRect cr; + } *cmd; + + if (num_clips == 0) + return 0; + + size = sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr); + cmd = malloc(size); + if (!cmd) + return -1; + + cmd->header.id = SVGA_3D_CMD_PRESENT_READBACK; + cmd->header.size = num_clips * sizeof(cmd->cr); + + for (i=0, cr = &cmd->cr; i < num_clips; i++, cr++, clips++) { + cr->x = (uint16_t) clips->x1; + cr->y = (uint16_t) clips->y1; + cr->w = (uint16_t) (clips->x2 - clips->x1); + cr->h = (uint16_t) (clips->y2 - clips->y1); +#if 0 + LogMessage(X_INFO, + "Readback x: %u y: %u srcx: %u srcy: %u w: %u h: %u\n", + cr->x, cr->y, cr->x, cr->y, cr->w, cr->h); +#endif + } + + + memset(&arg, 0, sizeof(arg)); + memset(&rep, 0, sizeof(rep)); + + rep.error = -EFAULT; + arg.fence_rep = (unsigned long)&rep; + arg.commands = (unsigned long)cmd; + arg.command_size = size; + arg.throttle_us = 0; + + ret = drmCommandWrite(drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg)); + if (ret) + LogMessage(X_ERROR, "Present readback error %s.\n", strerror(-ret)); + + free(cmd); + + /* + * Sync to avoid racing with Xorg SW rendering. + */ + + if (rep.error == 0) { + ret = vmwgfx_fence_wait(drm_fd, rep.fence_seq); + if (ret) + LogMessage(X_ERROR, "Present readback fence wait error %s.\n", + strerror(-ret)); + } + + return 0; +} + +int +vmwgfx_present(int drm_fd, unsigned int dst_x, unsigned int dst_y, + RegionPtr region, uint32_t handle) +{ + BoxPtr clips = REGION_RECTS(region); + unsigned int num_clips = REGION_NUM_RECTS(region); + struct drm_vmw_execbuf_arg arg; + struct drm_vmw_fence_rep rep; + int ret; + unsigned int size; + unsigned i; + SVGA3dCopyRect *cr; + + struct { + SVGA3dCmdHeader header; + SVGA3dCmdPresent body; + SVGA3dCopyRect cr; + } *cmd; + + if (num_clips == 0) + return 0; + + size = sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr); + cmd = malloc(size); + if (!cmd) + return -1; + + cmd->header.id = SVGA_3D_CMD_PRESENT; + cmd->header.size = sizeof(cmd->body) + num_clips * sizeof(cmd->cr); + cmd->body.sid = handle; + + + for (i=0, cr = &cmd->cr; i < num_clips; i++, cr++, clips++) { + cr->x = (uint16_t) clips->x1 + dst_x; + cr->y = (uint16_t) clips->y1 + dst_y; + cr->srcx = (uint16_t) clips->x1; + cr->srcy = (uint16_t) clips->y1; + cr->w = (uint16_t) (clips->x2 - clips->x1); + cr->h = (uint16_t) (clips->y2 - clips->y1); +#if 0 + LogMessage(X_INFO, "Present: x: %u y: %u srcx: %u srcy: %u w: %u h: %u\n", + cr->x, cr->y, cr->srcx, cr->srcy, cr->w, cr->h); +#endif + } + + memset(&arg, 0, sizeof(arg)); + memset(&rep, 0, sizeof(rep)); + + rep.error = -EFAULT; + arg.fence_rep = (unsigned long)&rep; + arg.commands = (unsigned long)cmd; + arg.command_size = size; + arg.throttle_us = 0; + + ret = drmCommandWrite(drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg)); + if (ret) { + LogMessage(X_ERROR, "Present error %s.\n", strerror(-ret)); + } + + free(cmd); + return 0; +} + +struct vmwgfx_int_dmabuf { + struct vmwgfx_dmabuf buf; + uint64_t map_handle; + uint64_t sync_handle; + int sync_valid; + int drm_fd; + uint32_t map_count; + void *addr; +}; + +static inline struct vmwgfx_int_dmabuf * +vmwgfx_int_dmabuf(struct vmwgfx_dmabuf *buf) +{ + return (struct vmwgfx_int_dmabuf *) buf; +} + +struct vmwgfx_dmabuf* +vmwgfx_dmabuf_alloc(int drm_fd, size_t size) +{ + union drm_vmw_alloc_dmabuf_arg arg; + struct vmwgfx_dmabuf *buf; + struct vmwgfx_int_dmabuf *ibuf; + int ret; + + ibuf = calloc(1, sizeof(*ibuf)); + if (!ibuf) + return NULL; + + buf = &ibuf->buf; + memset(&arg, 0, sizeof(arg)); + arg.req.size = size; + + ret = drmCommandWriteRead(drm_fd, DRM_VMW_ALLOC_DMABUF, &arg, + sizeof(arg)); + if (ret) + goto out_kernel_fail; + + ibuf = vmwgfx_int_dmabuf(buf); + ibuf->map_handle = arg.rep.map_handle; + ibuf->drm_fd = drm_fd; + buf->handle = arg.rep.handle; + buf->gmr_id = arg.rep.cur_gmr_id; + buf->gmr_offset = arg.rep.cur_gmr_offset; + buf->size = size; + + return buf; + out_kernel_fail: + free(buf); + return NULL; +} + +void * +vmwgfx_dmabuf_map(struct vmwgfx_dmabuf *buf) +{ + struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf); + + if (ibuf->addr) + return ibuf->addr; + + ibuf->addr = mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, + ibuf->drm_fd, ibuf->map_handle); + + if (ibuf->addr == MAP_FAILED) { + ibuf->addr = NULL; + return NULL; + } + + ibuf->map_count++; + return ibuf->addr; +} + +void +vmwgfx_dmabuf_unmap(struct vmwgfx_dmabuf *buf) +{ + struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf); + + if (--ibuf->map_count) + return; + + /* + * It's a pretty important performance optimzation not to call + * munmap here, although we should watch out for cases where we might fill + * the virtual memory space of the process. + */ +} + +void +vmwgfx_dmabuf_destroy(struct vmwgfx_dmabuf *buf) +{ + struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf); + struct drm_vmw_unref_dmabuf_arg arg; + + if (ibuf->addr) { + munmap(ibuf->addr, buf->size); + ibuf->addr = NULL; + } + + memset(&arg, 0, sizeof(arg)); + arg.handle = buf->handle; + + (void) drmCommandWrite(ibuf->drm_fd, DRM_VMW_UNREF_DMABUF, &arg, + sizeof(arg)); + free(buf); +} + +int +vmwgfx_dma(unsigned int host_x, unsigned int host_y, + RegionPtr region, struct vmwgfx_dmabuf *buf, + uint32_t buf_pitch, uint32_t surface_handle, int to_surface) +{ + BoxPtr clips = REGION_RECTS(region); + unsigned int num_clips = REGION_NUM_RECTS(region); + struct drm_vmw_execbuf_arg arg; + struct drm_vmw_fence_rep rep; + int ret; + unsigned int size; + unsigned i; + SVGA3dCopyBox *cb; + SVGA3dCmdSurfaceDMASuffix *suffix; + SVGA3dCmdSurfaceDMA *body; + struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf); + + struct { + SVGA3dCmdHeader header; + SVGA3dCmdSurfaceDMA body; + SVGA3dCopyBox cb; + } *cmd; + + if (num_clips == 0) + return 0; + + size = sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cb) + + sizeof(*suffix); + cmd = malloc(size); + if (!cmd) + return -1; + + cmd->header.id = SVGA_3D_CMD_SURFACE_DMA; + cmd->header.size = sizeof(cmd->body) + num_clips * sizeof(cmd->cb) + + sizeof(*suffix); + cb = &cmd->cb; + + suffix = (SVGA3dCmdSurfaceDMASuffix *) &cb[num_clips]; + suffix->suffixSize = sizeof(*suffix); + suffix->maximumOffset = (uint32_t) -1; + suffix->flags.discard = 0; + suffix->flags.unsynchronized = 0; + suffix->flags.reserved = 0; + + body = &cmd->body; + body->guest.ptr.gmrId = buf->gmr_id; + body->guest.ptr.offset = buf->gmr_offset; + body->guest.pitch = buf_pitch; + body->host.sid = surface_handle; + body->host.face = 0; + body->host.mipmap = 0; + + body->transfer = (to_surface ? SVGA3D_WRITE_HOST_VRAM : + SVGA3D_READ_HOST_VRAM); + + + for (i=0; i < num_clips; i++, cb++, clips++) { + cb->x = (uint16_t) clips->x1 + host_x; + cb->y = (uint16_t) clips->y1 + host_y; + cb->z = 0; + cb->srcx = (uint16_t) clips->x1; + cb->srcy = (uint16_t) clips->y1; + cb->srcz = 0; + cb->w = (uint16_t) (clips->x2 - clips->x1); + cb->h = (uint16_t) (clips->y2 - clips->y1); + cb->d = 1; +#if 0 + LogMessage(X_INFO, "DMA! x: %u y: %u srcx: %u srcy: %u w: %u h: %u %s\n", + cb->x, cb->y, cb->srcx, cb->srcy, cb->w, cb->h, + to_surface ? "to" : "from"); +#endif + + } + + memset(&arg, 0, sizeof(arg)); + memset(&rep, 0, sizeof(rep)); + + rep.error = -EFAULT; + arg.fence_rep = (unsigned long)&rep; + arg.commands = (unsigned long)cmd; + arg.command_size = size; + arg.throttle_us = 0; + + ret = drmCommandWrite(ibuf->drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg)); + if (ret) { + LogMessage(X_ERROR, "DMA error %s.\n", strerror(-ret)); + } + + free(cmd); + + if (!to_surface && rep.error == 0) { + ret = vmwgfx_fence_wait(ibuf->drm_fd, rep.fence_seq); + if (ret) + LogMessage(X_ERROR, "DMA from host fence wait error %s.\n", + strerror(-ret)); + } + + return 0; +} + +static int +vmwgfx_get_param(int drm_fd, uint32_t param, uint64_t *out) +{ + struct drm_vmw_getparam_arg gp_arg; + int ret; + + memset(&gp_arg, 0, sizeof(gp_arg)); + gp_arg.param = param; + ret = drmCommandWriteRead(drm_fd, DRM_VMW_GET_PARAM, + &gp_arg, sizeof(gp_arg)); + + if (ret == 0) { + *out = gp_arg.value; + } + + return ret; +} + +int +vmwgfx_num_streams(int drm_fd, uint32_t *ntot, uint32_t *nfree) +{ + uint64_t v1, v2; + int ret; + + ret = vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_NUM_STREAMS, &v1); + if (ret) + return ret; + + ret = vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_NUM_FREE_STREAMS, &v2); + if (ret) + return ret; + + *ntot = (uint32_t)v1; + *nfree = (uint32_t)v2; + + return 0; +} + +int +vmwgfx_claim_stream(int drm_fd, uint32_t *out) +{ + struct drm_vmw_stream_arg s_arg; + int ret; + + ret = drmCommandRead(drm_fd, DRM_VMW_CLAIM_STREAM, + &s_arg, sizeof(s_arg)); + + if (ret) + return -1; + + *out = s_arg.stream_id; + return 0; +} + +int +vmwgfx_unref_stream(int drm_fd, uint32_t stream_id) +{ + struct drm_vmw_stream_arg s_arg; + int ret; + + memset(&s_arg, 0, sizeof(s_arg)); + s_arg.stream_id = stream_id; + + ret = drmCommandWrite(drm_fd, DRM_VMW_UNREF_STREAM, + &s_arg, sizeof(s_arg)); + + return 0; +} + +int +vmwgfx_cursor_bypass(int drm_fd, int xhot, int yhot) +{ + struct drm_vmw_cursor_bypass_arg arg; + int ret; + + memset(&arg, 0, sizeof(arg)); + arg.flags = DRM_VMW_CURSOR_BYPASS_ALL; + arg.xhot = xhot; + arg.yhot = yhot; + + ret = drmCommandWrite(drm_fd, DRM_VMW_CURSOR_BYPASS, + &arg, sizeof(arg)); + + return ret; +} + +int +vmwgfx_max_fb_size(int drm_fd, size_t *size) +{ + drmVersionPtr ver; + int ret = -1; + uint64_t tmp_size; + + ver = drmGetVersion(drm_fd); + if (ver == NULL || + !(ver->version_major > 1 || + (ver->version_major == 1 && ver->version_minor >= 3))) + goto out; + + if (vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_MAX_FB_SIZE, &tmp_size) != 0) + goto out; + + *size = tmp_size; + ret = 0; + + out: + drmFreeVersion(ver); + return ret; +} diff --git a/vmwgfx/vmwgfx_drmi.h b/vmwgfx/vmwgfx_drmi.h new file mode 100644 index 0000000..0c92719 --- /dev/null +++ b/vmwgfx/vmwgfx_drmi.h @@ -0,0 +1,81 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Jakob Bornecrantz + * Author: Thomas Hellstrom + */ + +#ifndef _VMWGFX_DRMI_H_ +#define _VMWGFX_DRMI_H_ + +#include +#include +#include + +struct vmwgfx_dma_ctx; + +extern int +vmwgfx_present_readback(int drm_fd, RegionPtr region); + +extern int +vmwgfx_present(int drm_fd, unsigned int dst_x, unsigned int dst_y, + RegionPtr region, uint32_t handle); + +struct vmwgfx_dmabuf { + uint32_t handle; + uint32_t gmr_id; + uint32_t gmr_offset; + size_t size; +}; + +extern struct vmwgfx_dmabuf* +vmwgfx_dmabuf_alloc(int drm_fd, size_t size); +extern void +vmwgfx_dmabuf_destroy(struct vmwgfx_dmabuf *buf); +extern void * +vmwgfx_dmabuf_map(struct vmwgfx_dmabuf *buf); +extern void +vmwgfx_dmabuf_unmap(struct vmwgfx_dmabuf *buf); + +extern int +vmwgfx_dma(unsigned int host_x, unsigned int host_y, + RegionPtr region, struct vmwgfx_dmabuf *buf, + uint32_t buf_pitch, uint32_t surface_handle, int to_surface); + +extern int +vmwgfx_num_streams(int drm_fd, uint32_t *ntot, uint32_t *nfree); + +extern int +vmwgfx_claim_stream(int drm_fd, uint32_t *out); + +extern int +vmwgfx_unref_stream(int drm_fd, uint32_t stream_id); + +int +vmwgfx_cursor_bypass(int drm_fd, int xhot, int yhot); + +int +vmwgfx_max_fb_size(int drm_fd, size_t *size); + +#endif diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c new file mode 100644 index 0000000..2081f2a --- /dev/null +++ b/vmwgfx/vmwgfx_output.c @@ -0,0 +1,304 @@ +/* + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + * Author: Alan Hourihane + * Author: Jakob Bornecrantz + * + */ + +#include "xorg-server.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_XEXTPROTO_71 +#include +#else +#define DPMS_SERVER +#include +#endif + +#include "vmwgfx_driver.h" + +struct output_private +{ + drmModeConnectorPtr drm_connector; + + int c; +}; + +static char *output_enum_list[] = { + "Unknown", + "VGA", + "DVI", + "DVI", + "DVI", + "Composite", + "SVIDEO", + "LVDS", + "CTV", + "DIN", + "DP", + "HDMI", + "HDMI", +}; + +static void +output_create_resources(xf86OutputPtr output) +{ +#ifdef RANDR_12_INTERFACE +#endif /* RANDR_12_INTERFACE */ +} + +static void +output_dpms(xf86OutputPtr output, int mode) +{ +} + +static xf86OutputStatus +output_detect(xf86OutputPtr output) +{ + modesettingPtr ms = modesettingPTR(output->scrn); + struct output_private *priv = output->driver_private; + drmModeConnectorPtr drm_connector; + xf86OutputStatus status; + + drm_connector = drmModeGetConnector(ms->fd, priv->drm_connector->connector_id); + if (drm_connector) { + drmModeFreeConnector(priv->drm_connector); + priv->drm_connector = drm_connector; + } else { + drm_connector = priv->drm_connector; + } + + switch (drm_connector->connection) { + case DRM_MODE_CONNECTED: + status = XF86OutputStatusConnected; + break; + case DRM_MODE_DISCONNECTED: + status = XF86OutputStatusDisconnected; + break; + default: + status = XF86OutputStatusUnknown; + } + + return status; +} + +static DisplayModePtr +output_get_modes(xf86OutputPtr output) +{ + struct output_private *priv = output->driver_private; + drmModeConnectorPtr drm_connector = priv->drm_connector; + drmModeModeInfoPtr drm_mode = NULL; + DisplayModePtr modes = NULL, mode = NULL; + int i; + + for (i = 0; i < drm_connector->count_modes; i++) { + drm_mode = &drm_connector->modes[i]; + if (drm_mode) { + mode = calloc(1, sizeof(DisplayModeRec)); + if (!mode) + continue; + mode->Clock = drm_mode->clock; + mode->HDisplay = drm_mode->hdisplay; + mode->HSyncStart = drm_mode->hsync_start; + mode->HSyncEnd = drm_mode->hsync_end; + mode->HTotal = drm_mode->htotal; + mode->VDisplay = drm_mode->vdisplay; + mode->VSyncStart = drm_mode->vsync_start; + mode->VSyncEnd = drm_mode->vsync_end; + mode->VTotal = drm_mode->vtotal; + mode->Flags = drm_mode->flags; + mode->HSkew = drm_mode->hskew; + mode->VScan = drm_mode->vscan; + mode->VRefresh = xf86ModeVRefresh(mode); + mode->Private = (void *)drm_mode; + mode->type = 0; + if (drm_mode->type & DRM_MODE_TYPE_PREFERRED) + mode->type |= M_T_PREFERRED; + if (drm_mode->type & DRM_MODE_TYPE_DRIVER) + mode->type |= M_T_DRIVER; + xf86SetModeDefaultName(mode); + modes = xf86ModesAdd(modes, mode); + xf86PrintModeline(0, mode); + } + } + + return modes; +} + +static int +output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) +{ + // modesettingPtr ms = modesettingPTR(output->scrn); + // CustomizerPtr cust = ms->cust; + +#if 0 + if (cust && cust->winsys_check_fb_size && + !cust->winsys_check_fb_size(cust, pMode->HDisplay * + output->scrn->bitsPerPixel / 8, + pMode->VDisplay)) + return MODE_BAD; +#endif + return MODE_OK; +} + +#ifdef RANDR_12_INTERFACE +static Bool +output_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr value) +{ + return TRUE; +} +#endif /* RANDR_12_INTERFACE */ + +#ifdef RANDR_13_INTERFACE +static Bool +output_get_property(xf86OutputPtr output, Atom property) +{ + return TRUE; +} +#endif /* RANDR_13_INTERFACE */ + +static void +output_destroy(xf86OutputPtr output) +{ + struct output_private *priv = output->driver_private; + drmModeFreeConnector(priv->drm_connector); + free(priv); + output->driver_private = NULL; +} + +static const xf86OutputFuncsRec output_funcs = { + .create_resources = output_create_resources, +#ifdef RANDR_12_INTERFACE + .set_property = output_set_property, +#endif +#ifdef RANDR_13_INTERFACE + .get_property = output_get_property, +#endif + .dpms = output_dpms, + .detect = output_detect, + + .get_modes = output_get_modes, + .mode_valid = output_mode_valid, + .destroy = output_destroy, +}; + +void +xorg_output_init(ScrnInfoPtr pScrn) +{ + modesettingPtr ms = modesettingPTR(pScrn); + xf86OutputPtr output; + drmModeResPtr res; + drmModeConnectorPtr drm_connector = NULL; + drmModeEncoderPtr drm_encoder = NULL; + struct output_private *priv; + char name[32]; + int c, v, p; + + res = drmModeGetResources(ms->fd); + if (res == 0) { + DRV_ERROR("Failed drmModeGetResources\n"); + return; + } + + for (c = 0; c < res->count_connectors; c++) { + drm_connector = drmModeGetConnector(ms->fd, res->connectors[c]); + if (!drm_connector) + goto out; + +#if 0 + for (p = 0; p < drm_connector->count_props; p++) { + drmModePropertyPtr prop; + + prop = drmModeGetProperty(ms->fd, drm_connector->props[p]); + + name = NULL; + if (prop) { + ErrorF("VALUES %d\n", prop->count_values); + + for (v = 0; v < prop->count_values; v++) + ErrorF("%s %lld\n", prop->name, prop->values[v]); + } + } +#else + (void)p; + (void)v; +#endif + + snprintf(name, 32, "%s%d", + output_enum_list[drm_connector->connector_type], + drm_connector->connector_type_id); + + + priv = calloc(sizeof(*priv), 1); + if (!priv) { + continue; + } + + output = xf86OutputCreate(pScrn, &output_funcs, name); + if (!output) { + free(priv); + continue; + } + + drm_encoder = drmModeGetEncoder(ms->fd, drm_connector->encoders[0]); + if (drm_encoder) { + output->possible_crtcs = drm_encoder->possible_crtcs; + output->possible_clones = drm_encoder->possible_clones; + } else { + output->possible_crtcs = 0; + output->possible_clones = 0; + } + priv->c = c; + priv->drm_connector = drm_connector; + output->driver_private = priv; + output->subpixel_order = SubPixelHorizontalRGB; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; + } + + out: + drmModeFreeResources(res); +} + +unsigned +xorg_output_get_id(xf86OutputPtr output) +{ + struct output_private *priv = output->driver_private; + return priv->drm_connector->connector_id; +} + +/* vim: set sw=4 ts=8 sts=4: */ diff --git a/vmwgfx/vmwgfx_overlay.c b/vmwgfx/vmwgfx_overlay.c new file mode 100644 index 0000000..d161023 --- /dev/null +++ b/vmwgfx/vmwgfx_overlay.c @@ -0,0 +1,893 @@ +/* + * Copyright 2007-2011 by VMware, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + * + */ + +/* + * vmwarevideo.c -- + * + * Xv extension support. + * See http://www.xfree86.org/current/DESIGN16.html + * + */ + + +#include "xf86xv.h" +#include "fourcc.h" +#define debug_printf(...) + +/* + * We can't incude svga_types.h due to conflicting types for Bool. + */ +typedef int64_t int64; +typedef uint64_t uint64; + +typedef int32_t int32; +typedef uint32_t uint32; + +typedef int16_t int16; +typedef uint16_t uint16; + +typedef int8_t int8; +typedef uint8_t uint8; + +#include "../src/svga_reg.h" +#include "../src/svga_escape.h" +#include "../src/svga_overlay.h" + +#include + +#include "xf86drm.h" +#include +#include "vmwgfx_drmi.h" +#include "vmwgfx_driver.h" + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +/* + * Number of videos that can be played simultaneously + */ +#define VMWARE_VID_NUM_PORTS 1 + +/* + * Using a dark shade as the default colorKey + */ +#define VMWARE_VIDEO_COLORKEY 0x100701 + +/* + * Maximum dimensions + */ +#define VMWARE_VID_MAX_WIDTH 2048 +#define VMWARE_VID_MAX_HEIGHT 2048 + +#define VMWARE_VID_NUM_ENCODINGS 1 +static XF86VideoEncodingRec vmwareVideoEncodings[] = +{ + { + 0, + "XV_IMAGE", + VMWARE_VID_MAX_WIDTH, VMWARE_VID_MAX_HEIGHT, + {1, 1} + } +}; + +#define VMWARE_VID_NUM_FORMATS 2 +static XF86VideoFormatRec vmwareVideoFormats[] = +{ + { 16, TrueColor}, + { 24, TrueColor} +}; + +#define VMWARE_VID_NUM_IMAGES 3 +static XF86ImageRec vmwareVideoImages[] = +{ + XVIMAGE_YV12, + XVIMAGE_YUY2, + XVIMAGE_UYVY +}; + +#define VMWARE_VID_NUM_ATTRIBUTES 2 +static XF86AttributeRec vmwareVideoAttributes[] = +{ + { + XvGettable | XvSettable, + 0x000000, + 0xffffff, + "XV_COLORKEY" + }, + { + XvGettable | XvSettable, + 0, + 1, + "XV_AUTOPAINT_COLORKEY" + } +}; + +/* + * Video frames are stored in a circular list of buffers. + * Must be power or two, See vmw_video_port_play. + */ +#define VMWARE_VID_NUM_BUFFERS 1 + +/* + * Defines the structure used to hold and pass video data to the host + */ +struct vmw_video_buffer +{ + int size; + void *data; + struct vmwgfx_dmabuf *buf; +}; + + +/** + * Structure representing a single video stream, aka port. + * + * Ports maps one to one to a SVGA stream. Port is just + * what Xv calls a SVGA stream. + */ +struct vmwgfx_overlay_port +{ + /* + * Function prototype same as XvPutImage. + * + * This is either set to vmw_video_port_init or vmw_video_port_play. + * At init this function is set to port_init. In port_init we set it + * to port_play and call it, after initializing the struct. + */ + int (*play)(ScrnInfoPtr, struct vmwgfx_overlay_port *, + short, short, short, short, short, + short, short, short, int, unsigned char*, + short, short, RegionPtr); + + /* values to go into the SVGAOverlayUnit */ + uint32 streamId; + uint32 colorKey; + uint32 flags; + + /* round robin of buffers */ + unsigned currBuf; + struct vmw_video_buffer bufs[VMWARE_VID_NUM_BUFFERS]; + + /* properties that applies to all buffers */ + int size; + int pitches[3]; + int offsets[3]; + + /* things for X */ + RegionRec clipBoxes; + Bool isAutoPaintColorkey; + int drm_fd; +}; + +/* + * Callback functions exported to Xv, prefixed with vmw_xv_*. + */ +static int vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y, + short drw_x, short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int image, + unsigned char *buf, short width, short height, + Bool sync, RegionPtr clipBoxes, pointer data, + DrawablePtr dst); +static void vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool Cleanup); +static int vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format, + unsigned short *width, + unsigned short *height, int *pitches, + int *offsets); +static int vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 value, pointer data); +static int vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 *value, pointer data); +static void vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion, + short vid_w, short vid_h, short drw_w, + short drw_h, unsigned int *p_w, + unsigned int *p_h, pointer data); + + +/* + * Local functions. + */ +static int vmw_video_port_init(ScrnInfoPtr pScrn, + struct vmwgfx_overlay_port *port, + short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, + short height, RegionPtr clipBoxes); +static int vmw_video_port_play(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port, + short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, + short height, RegionPtr clipBoxes); +static void vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port); + +static int vmw_video_buffer_alloc(int drm_fd, int size, + struct vmw_video_buffer *out); +static int vmw_video_buffer_free(struct vmw_video_buffer *out); + + +static struct vmwgfx_overlay_port * +vmwgfx_overlay_port_create(int drm_fd, ScreenPtr pScreen) +{ + struct vmwgfx_overlay_port *port = calloc(1, sizeof(*port)); + + if (!port) + return NULL; + + port->drm_fd = drm_fd; + port->play = vmw_video_port_init; + port->flags = SVGA_VIDEO_FLAG_COLORKEY; + port->colorKey = VMWARE_VIDEO_COLORKEY; + port->isAutoPaintColorkey = TRUE; + return port; +} + +void +vmw_video_free_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports) +{ + if (free_ports) { + int i; + + for(i=0; inPorts; ++i) { + free(adaptor->pPortPrivates[i].ptr); + } + } + + free(adaptor->pPortPrivates); + xf86XVFreeVideoAdaptorRec(adaptor); +} + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_init_adaptor -- + * + * Initializes a XF86VideoAdaptor structure with the capabilities and + * functions supported by this video driver. + * + * Results: + * On success initialized XF86VideoAdaptor struct or NULL on error + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +XF86VideoAdaptorPtr +vmw_video_init_adaptor(ScrnInfoPtr pScrn) +{ + XF86VideoAdaptorPtr adaptor; + modesettingPtr ms = modesettingPTR(pScrn); + int i; + DevUnion *dev_unions; + uint32_t ntot, nfree; + + if (vmwgfx_num_streams(ms->fd, &ntot, &nfree) != 0) { + debug_printf("No stream ioctl support\n"); + return NULL; + } + if (nfree == 0) { + debug_printf("No free streams\n"); + return NULL; + } + adaptor = xf86XVAllocateVideoAdaptorRec(pScrn); + dev_unions = calloc(VMWARE_VID_NUM_PORTS, sizeof(DevUnion)); + if (adaptor == NULL || dev_unions == NULL) { + xf86XVFreeVideoAdaptorRec(adaptor); + free(dev_unions); + return NULL; + } + + adaptor->type = XvInputMask | XvImageMask | XvWindowMask; + + /** + * Note: CLIP_TO_VIEWPORT was removed from the flags, since with the + * crtc/output based modesetting, the viewport is not updated on + * RandR modeswitches. Hence the video may incorrectly be clipped away. + * The correct approach, (if needed) would be to clip against the + * scanout area union of all active crtcs. Revisit if needed. + */ + + adaptor->flags = VIDEO_OVERLAID_IMAGES; + adaptor->name = "VMware Overlay Video Engine"; + adaptor->nEncodings = VMWARE_VID_NUM_ENCODINGS; + adaptor->pEncodings = vmwareVideoEncodings; + adaptor->nFormats = VMWARE_VID_NUM_FORMATS; + adaptor->pFormats = vmwareVideoFormats; + adaptor->nPorts = VMWARE_VID_NUM_PORTS; + adaptor->pPortPrivates = dev_unions; + + for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) { + struct vmwgfx_overlay_port *priv = + vmwgfx_overlay_port_create(ms->fd, pScrn->pScreen); + + adaptor->pPortPrivates[i].ptr = (pointer) priv; + } + + adaptor->nAttributes = VMWARE_VID_NUM_ATTRIBUTES; + adaptor->pAttributes = vmwareVideoAttributes; + adaptor->nImages = VMWARE_VID_NUM_IMAGES; + adaptor->pImages = vmwareVideoImages; + + adaptor->PutVideo = NULL; + adaptor->PutStill = NULL; + adaptor->GetVideo = NULL; + adaptor->GetStill = NULL; + adaptor->StopVideo = vmw_xv_stop_video; + adaptor->SetPortAttribute = vmw_xv_set_port_attribute; + adaptor->GetPortAttribute = vmw_xv_get_port_attribute; + adaptor->QueryBestSize = vmw_xv_query_best_size; + adaptor->PutImage = vmw_xv_put_image; + adaptor->QueryImageAttributes = vmw_xv_query_image_attributes; + + return adaptor; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_port_init -- + * + * Initializes a video stream in response to the first PutImage() on a + * video stream. The process goes as follows: + * - Figure out characteristics according to format + * - Allocate offscreen memory + * - Pass on video to Play() functions + * + * Results: + * Success or XvBadAlloc on failure. + * + * Side effects: + * Video stream is initialized and its first frame sent to the host + * (done by VideoPlay() function called at the end) + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_video_port_init(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port, + short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, + short height, RegionPtr clipBoxes) +{ + unsigned short w, h; + int i, ret; + + debug_printf("\t%s: id %d, format %d\n", __func__, port->streamId, format); + + ret = vmwgfx_claim_stream(port->drm_fd, &port->streamId); + if (ret != 0) + return XvBadAlloc; + + w = width; + h = height; + /* init all the format attributes, used for buffers */ + port->size = vmw_xv_query_image_attributes(pScrn, format, &w, &h, + port->pitches, port->offsets); + + if (port->size == -1) { + ret = XvBadAlloc; + goto out_bad_size; + } + + for (i = 0; i < VMWARE_VID_NUM_BUFFERS; ++i) { + ret = vmw_video_buffer_alloc(port->drm_fd, port->size, &port->bufs[i]); + if (ret != Success) + goto out_no_buffer; + } + + port->currBuf = 0; + REGION_NULL(pScrn->pScreen, &port->clipBoxes); + port->play = vmw_video_port_play; + return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h, + drw_w, drw_h, format, buf, width, height, clipBoxes); + + out_bad_size: + (void) vmwgfx_unref_stream(port->drm_fd, port->streamId); + + out_no_buffer: + while(i-- != 0) { + vmw_video_buffer_free(&port->bufs[i]); + } + return ret; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_port_play -- + * + * Sends all the attributes associated with the video frame using the + * FIFO ESCAPE mechanism to the host. + * + * Results: + * Always returns Success. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_video_port_play(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port, + short src_x, short src_y, short drw_x, + short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, + short height, RegionPtr clipBoxes) +{ + struct drm_vmw_control_stream_arg arg; + unsigned short w, h; + int size; + int ret; + + debug_printf("\t%s: enter\n", __func__); + + w = width; + h = height; + + /* we don't update the ports size */ + size = vmw_xv_query_image_attributes(pScrn, format, &w, &h, + port->pitches, port->offsets); + + if (size != port->size) { + vmw_xv_stop_video(pScrn, port, TRUE); + return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, + src_h, drw_w, drw_h, format, buf, width, height, + clipBoxes); + } + + memcpy(port->bufs[port->currBuf].data, buf, port->size); + + memset(&arg, 0, sizeof(arg)); + + arg.stream_id = port->streamId; + arg.enabled = TRUE; + arg.flags = port->flags; + arg.color_key = port->colorKey; + arg.handle = port->bufs[port->currBuf].buf->handle; + arg.format = format; + arg.size = port->size; + arg.width = w; + arg.height = h; + arg.src.x = src_x; + arg.src.y = src_y; + arg.src.w = src_w; + arg.src.h = src_h; + arg.dst.x = drw_x; + arg.dst.y = drw_y; + arg.dst.w = drw_w; + arg.dst.h = drw_h; + arg.pitch[0] = port->pitches[0]; + arg.pitch[1] = port->pitches[1]; + arg.pitch[2] = port->pitches[2]; + arg.offset = 0; + + /* + * Update the clipList and paint the colorkey, if required. + */ + if (!REGION_EQUAL(pScrn->pScreen, &port->clipBoxes, clipBoxes)) { + REGION_COPY(pScrn->pScreen, &port->clipBoxes, clipBoxes); + if (port->isAutoPaintColorkey) + xf86XVFillKeyHelper(pScrn->pScreen, port->colorKey, clipBoxes); + } + + xorg_flush(pScrn->pScreen); + ret = drmCommandWrite(port->drm_fd, DRM_VMW_CONTROL_STREAM, &arg, sizeof(arg)); + if (ret) { + vmw_video_port_cleanup(pScrn, port); + return XvBadAlloc; + } + + if (++(port->currBuf) >= VMWARE_VID_NUM_BUFFERS) + port->currBuf = 0; + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_port_cleanup -- + * + * Frees up all resources (if any) taken by a video stream. + * + * Results: + * None. + * + * Side effects: + * Same as above. + * + *----------------------------------------------------------------------------- + */ + +static void +vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port) +{ + int i; + + debug_printf("\t%s: enter\n", __func__); + + if (port->play == vmw_video_port_init) + return; + + port->play = vmw_video_port_init; + (void) vmwgfx_unref_stream(port->drm_fd, port->streamId); + + for (i = 0; i < VMWARE_VID_NUM_BUFFERS; i++) { + vmw_video_buffer_free(&port->bufs[i]); + } + + REGION_UNINIT(pScreen->pScreen, &port->clipBoxes); +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_buffer_alloc -- + * + * Allocates and map a kernel buffer to be used as data storage. + * + * Results: + * XvBadAlloc on failure, otherwise Success. + * + * Side effects: + * Calls into the kernel, sets members of out. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_video_buffer_alloc(int drm_fd, int size, + struct vmw_video_buffer *out) +{ + out->buf = vmwgfx_dmabuf_alloc(drm_fd, size); + if (!out->buf) + return XvBadAlloc; + + out->data = vmwgfx_dmabuf_map(out->buf); + if (!out->data) { + vmwgfx_dmabuf_destroy(out->buf); + out->buf = NULL; + return XvBadAlloc; + } + + out->size = size; + debug_printf("\t\t%s: allocated buffer %p of size %i\n", __func__, out, size); + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_video_buffer_free -- + * + * Frees and unmaps an allocated kernel buffer. + * + * Results: + * Success. + * + * Side effects: + * Calls into the kernel, sets members of out to 0. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_video_buffer_free(struct vmw_video_buffer *out) +{ + if (out->size == 0) + return Success; + + vmwgfx_dmabuf_unmap(out->buf); + vmwgfx_dmabuf_destroy(out->buf); + + out->buf = NULL; + out->data = NULL; + out->size = 0; + + debug_printf("\t\t%s: freed buffer %p\n", __func__, out); + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_xv_put_image -- + * + * Main video playback function. It copies the passed data which is in + * the specified format (e.g. FOURCC_YV12) into the overlay. + * + * If sync is TRUE the driver should not return from this + * function until it is through reading the data from buf. + * + * Results: + * Success or XvBadAlloc on failure + * + * Side effects: + * Video port will be played(initialized if 1st frame) on success + * or will fail on error. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y, + short drw_x, short drw_y, short src_w, short src_h, + short drw_w, short drw_h, int format, + unsigned char *buf, short width, short height, + Bool sync, RegionPtr clipBoxes, pointer data, + DrawablePtr dst) +{ + struct vmwgfx_overlay_port *port = data; + + debug_printf("%s: enter (%u, %u) (%ux%u) (%u, %u) (%ux%u) (%ux%u)\n", __func__, + src_x, src_y, src_w, src_h, + drw_x, drw_y, drw_w, drw_h, + width, height); + + return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h, + drw_w, drw_h, format, buf, width, height, clipBoxes); +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_xv_stop_video -- + * + * Called when we should stop playing video for a particular stream. If + * Cleanup is FALSE, the "stop" operation is only temporary, and thus we + * don't do anything. If Cleanup is TRUE we kill the video port by + * sending a message to the host and freeing up the stream. + * + * Results: + * None. + * + * Side effects: + * See above. + * + *----------------------------------------------------------------------------- + */ + +static void +vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup) +{ + struct vmwgfx_overlay_port *port = data; + + debug_printf("%s: cleanup is %s\n", __func__, cleanup ? "TRUE" : "FALSE"); + REGION_EMPTY(pScrn->pScreen, &port->clipBoxes); + + if (!cleanup) + return; + + vmw_video_port_cleanup(pScrn, port); +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_xv_query_image_attributes -- + * + * From the spec: This function is called to let the driver specify how data + * for a particular image of size width by height should be stored. + * Sometimes only the size and corrected width and height are needed. In + * that case pitches and offsets are NULL. + * + * Results: + * The size of the memory required for the image, or -1 on error. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format, + unsigned short *width, unsigned short *height, + int *pitches, int *offsets) +{ + INT32 size, tmp; + + if (*width > VMWARE_VID_MAX_WIDTH) { + *width = VMWARE_VID_MAX_WIDTH; + } + if (*height > VMWARE_VID_MAX_HEIGHT) { + *height = VMWARE_VID_MAX_HEIGHT; + } + + *width = (*width + 1) & ~1; + if (offsets != NULL) { + offsets[0] = 0; + } + + switch (format) { + case FOURCC_YV12: + *height = (*height + 1) & ~1; + size = (*width + 3) & ~3; + if (pitches) { + pitches[0] = size; + } + size *= *height; + if (offsets) { + offsets[1] = size; + } + tmp = ((*width >> 1) + 3) & ~3; + if (pitches) { + pitches[1] = pitches[2] = tmp; + } + tmp *= (*height >> 1); + size += tmp; + if (offsets) { + offsets[2] = size; + } + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + size = *width * 2; + if (pitches) { + pitches[0] = size; + } + size *= *height; + break; + default: + debug_printf("Query for invalid video format %d\n", format); + return -1; + } + return size; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_xv_set_port_attribute -- + * + * From the spec: A port may have particular attributes such as colorKey, hue, + * saturation, brightness or contrast. Xv clients set these + * attribute values by sending attribute strings (Atoms) to the server. + * + * Results: + * Success if the attribute exists and XvBadAlloc otherwise. + * + * Side effects: + * The respective attribute gets the new value. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 value, pointer data) +{ + struct vmwgfx_overlay_port *port = data; + Atom xvColorKey = MAKE_ATOM("XV_COLORKEY"); + Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); + + if (attribute == xvColorKey) { + debug_printf("%s: Set colorkey:0x%x\n", __func__, (unsigned)value); + port->colorKey = value; + } else if (attribute == xvAutoPaint) { + debug_printf("%s: Set autoPaint: %s\n", __func__, value? "TRUE": "FALSE"); + port->isAutoPaintColorkey = value; + } else { + return XvBadAlloc; + } + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_xv_get_port_attribute -- + * + * From the spec: A port may have particular attributes such as hue, + * saturation, brightness or contrast. Xv clients get these + * attribute values by sending attribute strings (Atoms) to the server + * + * Results: + * Success if the attribute exists and XvBadAlloc otherwise. + * + * Side effects: + * "value" contains the requested attribute on success. + * + *----------------------------------------------------------------------------- + */ + +static int +vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 *value, pointer data) +{ + struct vmwgfx_overlay_port *port = data; + Atom xvColorKey = MAKE_ATOM("XV_COLORKEY"); + Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); + + if (attribute == xvColorKey) { + *value = port->colorKey; + } else if (attribute == xvAutoPaint) { + *value = port->isAutoPaintColorkey; + } else { + return XvBadAlloc; + } + + return Success; +} + + +/* + *----------------------------------------------------------------------------- + * + * vmw_xv_query_best_size -- + * + * From the spec: QueryBestSize provides the client with a way to query what + * the destination dimensions would end up being if they were to request + * that an area vid_w by vid_h from the video stream be scaled to rectangle + * of drw_w by drw_h on the screen. Since it is not expected that all + * hardware will be able to get the target dimensions exactly, it is + * important that the driver provide this function. + * + * This function seems to never be called, but to be on the safe side + * we apply the same logic that QueryImageAttributes has for width + * and height. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static void +vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion, + short vid_w, short vid_h, short drw_w, + short drw_h, unsigned int *p_w, + unsigned int *p_h, pointer data) +{ + *p_w = (drw_w + 1) & ~1; + *p_h = drw_h; + + return; +} diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c new file mode 100644 index 0000000..3122353 --- /dev/null +++ b/vmwgfx/vmwgfx_saa.c @@ -0,0 +1,1208 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Thomas Hellstrom + */ + +#include +#include +#include +#include +#include +#include "vmwgfx_saa.h" +#include "vmwgfx_drmi.h" + + +#define VMWGFX_PIX_MALLOC (1 << 0) +#define VMWGFX_PIX_GMR (1 << 1) +#define VMWGFX_PIX_SURFACE (1 << 2) + +struct vmwgfx_saa { + struct saa_driver driver; + struct vmwgfx_dma_ctx *ctx; + struct xa_tracker *xat; + struct xa_context *xa_ctx; + ScreenPtr pScreen; + int drm_fd; + struct vmwgfx_saa_pixmap *src_vpix; + struct vmwgfx_saa_pixmap *dst_vpix; + Bool present_copy; + Bool diff_valid; + int xdiff; + int ydiff; + RegionRec present_region; + uint32_t src_handle; + Bool can_optimize_dma; + void (*present_flush) (ScreenPtr pScreen); + struct vmwgfx_saa_pixmap *dri2_flush_list; +}; + +static inline struct vmwgfx_saa * +to_vmwgfx_saa(struct saa_driver *driver) { + return (struct vmwgfx_saa *) driver; +} + +static Bool +vmwgfx_pixmap_add_damage(PixmapPtr pixmap) +{ + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + DrawablePtr draw = &pixmap->drawable; + BoxRec box; + + if (spix->damage) + return TRUE; + + if (!saa_add_damage(pixmap)) + return FALSE; + + box.x1 = 0; + box.x2 = draw->width; + box.y1 = 0; + box.y2 = draw->height; + + if (vpix->hw) + REGION_INIT(draw->pScreen, &spix->dirty_hw, &box, 1); + else + REGION_INIT(draw->pScreen, &spix->dirty_shadow, &box, 1); + + return TRUE; +} + +static void +vmwgfx_pixmap_remove_damage(PixmapPtr pixmap) +{ + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + + if (!spix->damage || (vpix->hw && vpix->gmr)) + return; + + DamageUnregister(&pixmap->drawable, spix->damage); + DamageDestroy(spix->damage); + spix->damage = NULL; +} + +static void +vmwgfx_pixmap_remove_present(struct vmwgfx_saa_pixmap *vpix) +{ + if (vpix->dirty_present) + REGION_DESTROY(pixmap->drawable.pScreen, vpix->dirty_present); + if (vpix->present_damage) + REGION_DESTROY(pixmap->drawable.pScreen, vpix->present_damage); + if (vpix->pending_update) + REGION_DESTROY(pixmap->drawable.pScreen, vpix->pending_update); + if (vpix->pending_present) + REGION_DESTROY(pixmap->drawable.pScreen, vpix->pending_present); + vpix->dirty_present = NULL; + vpix->present_damage = NULL; + vpix->pending_update = NULL; + vpix->pending_present = NULL; +} + +static Bool +vmwgfx_pixmap_add_present(PixmapPtr pixmap) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + ScreenPtr pScreen = pixmap->drawable.pScreen; + (void) pScreen; + + vpix->dirty_present = REGION_CREATE(pScreen, NULL, 0); + if (!vpix->dirty_present) + return FALSE; + vpix->present_damage = REGION_CREATE(pScreen, NULL, 0); + if (!vpix->present_damage) + goto out_no_present_damage; + vpix->pending_update = REGION_CREATE(pScreen, NULL, 0); + if (!vpix->pending_update) + goto out_no_pending_update; + vpix->pending_present = REGION_CREATE(pScreen, NULL, 0); + if (!vpix->pending_present) + goto out_no_pending_present; + if (!vmwgfx_pixmap_add_damage(pixmap)) + goto out_no_damage; + + return TRUE; + out_no_damage: + REGION_DESTROY(pScreen, vpix->pending_present); + out_no_pending_present: + REGION_DESTROY(pScreen, vpix->pending_update); + out_no_pending_update: + REGION_DESTROY(pScreen, vpix->present_damage); + out_no_present_damage: + REGION_DESTROY(pScreen, vpix->dirty_present); + return FALSE; +} + +static void +vmwgfx_pixmap_free_storage(struct vmwgfx_saa_pixmap *vpix) +{ + if (!(vpix->backing & VMWGFX_PIX_MALLOC) && vpix->malloc) { + free(vpix->malloc); + vpix->malloc = NULL; + } + if (!(vpix->backing & VMWGFX_PIX_SURFACE) && vpix->hw) { + xa_surface_destroy(vpix->hw); + vpix->hw = NULL; + } + if (!(vpix->backing & VMWGFX_PIX_GMR) && vpix->gmr) { + vmwgfx_dmabuf_destroy(vpix->gmr); + vpix->gmr = NULL; + } +} + +static Bool +vmwgfx_pixmap_create_gmr(struct vmwgfx_saa *vsaa, PixmapPtr pixmap) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + size_t size; + struct vmwgfx_dmabuf *gmr; + void *addr; + + if (vpix->gmr) + return TRUE; + + size = pixmap->devKind * pixmap->drawable.height; + gmr = vmwgfx_dmabuf_alloc(vsaa->drm_fd, size); + if (!gmr) + return FALSE; + + if (vpix->malloc) { + + addr = vmwgfx_dmabuf_map(gmr); + if (!addr) + goto out_no_transfer; + memcpy(addr, vpix->malloc, size); + vmwgfx_dmabuf_unmap(gmr); + + } else if (vpix->hw && !vmwgfx_pixmap_add_damage(pixmap)) + goto out_no_transfer; + + vpix->backing |= VMWGFX_PIX_GMR; + vpix->backing &= ~VMWGFX_PIX_MALLOC; + vpix->gmr = gmr; + + vmwgfx_pixmap_free_storage(vpix); + + return TRUE; + + out_no_transfer: + vmwgfx_dmabuf_destroy(gmr); + return FALSE; +} + +static Bool +vmwgfx_pixmap_create_sw(struct vmwgfx_saa *vsaa, PixmapPtr pixmap) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + + if (!(vpix->backing & (VMWGFX_PIX_MALLOC | VMWGFX_PIX_GMR))) + return FALSE; + + if (!vpix->malloc && (vpix->backing & VMWGFX_PIX_MALLOC)) { + vpix->malloc = malloc(pixmap->devKind * pixmap->drawable.height); + return (vpix->malloc != NULL); + } else if (vpix->backing & VMWGFX_PIX_GMR) + return vmwgfx_pixmap_create_gmr(vsaa, pixmap); + + return TRUE; +} + + +/** + * + * Makes sure all presented contents covered by @region are read + * back and are present in a valid GMR. + */ + +static Bool +vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa, + PixmapPtr pixmap, + RegionPtr region) +{ + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + RegionRec intersection; + + + if (!spix->damage || !REGION_NOTEMPTY(vsaa->pScreen, &spix->dirty_hw) || + !vpix->dirty_present) + return TRUE; + + REGION_NULL(vsaa->pScreen, &intersection); + REGION_COPY(vsaa->pScreen, &intersection, &spix->dirty_hw); + REGION_INTERSECT(vsaa->pScreen, &intersection, &intersection, + vpix->dirty_present); + + if (region) + REGION_INTERSECT(vsaa->pScreen, &intersection, &intersection, region); + + if (!REGION_NOTEMPTY(vsaa->pScreen, &intersection)) + goto out; + + vsaa->present_flush(vsaa->pScreen); + if (!vmwgfx_pixmap_create_gmr(vsaa, pixmap)) + goto out_err; + + /* + * FIXME: Cliprects may not overlap screen boundaries. + */ + + if (vmwgfx_present_readback(vsaa->drm_fd, &intersection) != 0) + goto out_err; + + REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_hw, + &spix->dirty_hw, &intersection); + out: + REGION_UNINIT(vsaa->pScreen, &intersection); + return TRUE; + + out_err: + REGION_UNINIT(vsaa->pScreen, &intersection); + return FALSE; +} + +static Bool +vmwgfx_saa_dma(struct vmwgfx_saa *vsaa, + PixmapPtr pixmap, + RegionPtr reg, + Bool to_hw) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + + if (!vpix->hw || (!vpix->gmr && !vpix->malloc)) + return TRUE; + + if (vpix->gmr && vsaa->can_optimize_dma) { + uint32_t handle, dummy; + + if (xa_surface_handle(vpix->hw, &handle, &dummy) != 0) + goto out_err; + if (vmwgfx_dma(0, 0, reg, vpix->gmr, pixmap->devKind, handle, + to_hw) != 0) + goto out_err; + } else { + void *data = vpix->malloc; + int ret; + + if (vpix->gmr) { + data = vmwgfx_dmabuf_map(vpix->gmr); + if (!data) + goto out_err; + } + + ret = xa_surface_dma(vsaa->xa_ctx, vpix->hw, data, pixmap->devKind, + (int) to_hw, + (struct xa_box *) REGION_RECTS(reg), + REGION_NUM_RECTS(reg)); + if (vpix->gmr) + vmwgfx_dmabuf_unmap(vpix->gmr); + if (ret) + goto out_err; + } + return TRUE; + out_err: + LogMessage(X_ERROR, "DMA %s surface failed.\n", + to_hw ? "to" : "from"); + return FALSE; +} + + +static Bool +vmwgfx_download_from_hw(struct saa_driver *driver, PixmapPtr pixmap, + RegionPtr readback) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + + RegionRec intersection; + + if (!vmwgfx_pixmap_present_readback(vsaa, pixmap, readback)) + return FALSE; + + if (!REGION_NOTEMPTY(vsaa->pScreen, &spix->dirty_hw)) + return TRUE; + + if (!vpix->hw) + return TRUE; + + REGION_NULL(vsaa->pScreen, &intersection); + REGION_INTERSECT(vsaa->pScreen, &intersection, readback, + &spix->dirty_hw); + readback = &intersection; + + if (!vmwgfx_pixmap_create_sw(vsaa, pixmap)) + goto out_err; + + if (!vmwgfx_saa_dma(vsaa, pixmap, readback, FALSE)) + goto out_err; + REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_hw, &spix->dirty_hw, readback); + REGION_UNINIT(vsaa->pScreen, &intersection); + return TRUE; + out_err: + REGION_UNINIT(vsaa->pScreen, &intersection); + return FALSE; +} + + +static Bool +vmwgfx_upload_to_hw(struct saa_driver *driver, PixmapPtr pixmap, + RegionPtr upload) +{ + return vmwgfx_saa_dma(to_vmwgfx_saa(driver), pixmap, upload, TRUE); +} + +static void +vmwgfx_release_from_cpu(struct saa_driver *driver, PixmapPtr pixmap, saa_access_t access) +{ + // LogMessage(X_INFO, "Release 0x%08lx access 0x%08x\n", + // (unsigned long) pixmap, (unsigned) access); +} + +static void * +vmwgfx_sync_for_cpu(struct saa_driver *driver, PixmapPtr pixmap, saa_access_t access) +{ + /* + * Errors in this functions will turn up in subsequent map + * calls. + */ + + (void) vmwgfx_pixmap_create_sw(to_vmwgfx_saa(driver), pixmap); + + return NULL; +} + +static void * +vmwgfx_map(struct saa_driver *driver, PixmapPtr pixmap, saa_access_t access) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + + if (vpix->malloc) + return vpix->malloc; + else if (vpix->gmr) + return vmwgfx_dmabuf_map(vpix->gmr); + else + return NULL; +} + +static void +vmwgfx_unmap(struct saa_driver *driver, PixmapPtr pixmap, saa_access_t access) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + + if (vpix->gmr) + return vmwgfx_dmabuf_unmap(vpix->gmr); + +// LogMessage(X_INFO, "Unmap 0x%08lx access 0x%08x\n", + // (unsigned long) pixmap, (unsigned) access); + ; +} + +static Bool +vmwgfx_create_pixmap(struct saa_driver *driver, struct saa_pixmap *spix, + int w, int h, int depth, + unsigned int usage_hint, int bpp, int *new_pitch) +{ + *new_pitch = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); + + + return TRUE; +} + + +static void +vmwgfx_add_dri2_list(struct vmwgfx_saa *vsaa, + struct vmwgfx_saa_pixmap *vpix) +{ + vpix->next_dri2 = vsaa->dri2_flush_list; + vpix->prevnext_dri2 = &vsaa->dri2_flush_list; + vsaa->dri2_flush_list = vpix; + if (vpix->next_dri2) + vpix->next_dri2->prevnext_dri2 = &vpix->next_dri2; +} + +void +vmwgfx_remove_dri2_list(struct vmwgfx_saa_pixmap *vpix) +{ + if (vpix->next_dri2) + vpix->next_dri2->prevnext_dri2 = vpix->prevnext_dri2; + + if (vpix->prevnext_dri2) + *vpix->prevnext_dri2 = vpix->next_dri2; + + vpix->next_dri2 = NULL; + vpix->prevnext_dri2 = NULL; +} + + +void +vmwgfx_flush_dri2(ScreenPtr pScreen) +{ + struct vmwgfx_saa *vsaa = + to_vmwgfx_saa(saa_get_driver(pScreen)); + struct vmwgfx_saa_pixmap *next = vsaa->dri2_flush_list; + struct vmwgfx_saa_pixmap *cur; + + while(next) { + struct saa_pixmap *spix = &next->base; + PixmapPtr pixmap = spix->pixmap; + + if (vmwgfx_upload_to_hw(&vsaa->driver, pixmap, &spix->dirty_shadow)) { + REGION_EMPTY(vsaa->pScreen, &spix->dirty_shadow); + cur = next; + next = next->next_dri2; + vmwgfx_remove_dri2_list(cur); + } else + next = next->next_dri2; + } +} + + +static void +vmwgfx_destroy_pixmap(struct saa_driver *driver, PixmapPtr pixmap) +{ + ScreenPtr pScreen = to_vmwgfx_saa(driver)->pScreen; + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + (void) pScreen; + + vpix->backing = 0; + vmwgfx_pixmap_free_storage(vpix); + + /* + * Any damage we've registered has already been removed by the server + * at this point. Any attempt to unregister / destroy it will result + * in a double free. + */ + + vmwgfx_pixmap_remove_present(vpix); + vmwgfx_remove_dri2_list(vpix); + + if (vpix->hw_is_dri2_fronts) + LogMessage(X_ERROR, "Incorrect dri2 front count.\n"); +} + +static Bool +vmwgfx_pixmap_create_hw(struct vmwgfx_saa *vsaa, + PixmapPtr pixmap, unsigned int flags) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + struct xa_surface *hw; + + if (!vsaa->xat) + return FALSE; + + if (vpix->hw) + return TRUE; + + hw = xa_surface_create(vsaa->xat, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.depth, + xa_type_argb, xa_format_unknown, + XA_FLAG_RENDER_TARGET | flags); + if (hw == NULL) + return FALSE; + + if ((vpix->gmr || vpix->malloc) && !vmwgfx_pixmap_add_damage(pixmap)) + goto out_no_damage; + + /* + * Even if we don't have a GMR yet, indicate that when needed it + * should be created. + */ + + vpix->hw = hw; + vpix->backing |= VMWGFX_PIX_SURFACE; + vmwgfx_pixmap_free_storage(vpix); + + return TRUE; + +out_no_damage: + xa_surface_destroy(hw); + return FALSE; +} + + +/** + * + * Makes sure we have a surface with valid contents. + */ + +Bool +vmwgfx_pixmap_validate_hw(PixmapPtr pixmap, RegionPtr region, + unsigned int add_flags, + unsigned int remove_flags) +{ + struct vmwgfx_saa *vsaa = + to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + RegionRec intersection; + + if (!vsaa->xat) + return FALSE; + + if (vpix->hw) { + if (xa_surface_redefine(vpix->hw, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.depth, + xa_type_argb, xa_format_unknown, + XA_FLAG_RENDER_TARGET | add_flags, + remove_flags, 1) != 0) + return FALSE; + } else if (!vmwgfx_pixmap_create_hw(vsaa, pixmap, add_flags)) + return FALSE; + + + if (!vmwgfx_pixmap_present_readback(vsaa, pixmap, region)) + return FALSE; + + REGION_NULL(vsaa->pScreen, &intersection); + REGION_COPY(vsaa->pScreen, &intersection, &spix->dirty_shadow); + + if (vpix->dirty_present) + REGION_UNION(vsaa->pScreen, &intersection, vpix->dirty_present, + &spix->dirty_shadow); + + if (spix->damage && REGION_NOTEMPTY(vsaa->pScreen, &intersection)) { + RegionPtr upload = &intersection; + + /* + * Check whether we need to upload from GMR. + */ + + if (region) { + REGION_INTERSECT(vsaa->pScreen, &intersection, region, + &intersection); + upload = &intersection; + } + + if (REGION_NOTEMPTY(vsaa->pScreen, upload)) { + Bool ret = vmwgfx_upload_to_hw(&vsaa->driver, pixmap, upload); + if (ret) { + REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_shadow, + &spix->dirty_shadow, upload); + if (vpix->dirty_present) + REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present, + vpix->dirty_present, upload); + } else { + REGION_UNINIT(vsaa->pScreen, &intersection); + return FALSE; + } + } + } + REGION_UNINIT(vsaa->pScreen, &intersection); + return TRUE; +} + +static void +vmwgfx_copy_stride(uint8_t *dst, uint8_t *src, unsigned int dst_pitch, + unsigned int src_pitch, unsigned int dst_height, + unsigned int src_height) +{ + unsigned int i; + unsigned int height = (dst_height < src_height) ? dst_height : src_height; + unsigned int pitch = (dst_pitch < src_pitch) ? dst_pitch : src_pitch; + + for(i=0; idrawable.pScreen; + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pScreen)); + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + DrawablePtr draw = &pixmap->drawable; + unsigned int size = pixmap->devKind * draw->height; + + /* + * Ignore copying errors. At worst they will show up as rendering + * artefacts. + */ + + if (vpix->malloc) { + + void *new_malloc = malloc(size); + if (!new_malloc) + return FALSE; + + vmwgfx_copy_stride(new_malloc, vpix->malloc, pixmap->devKind, + old_pitch, draw->height, + old_height); + free(vpix->malloc); + vpix->malloc = new_malloc; + } + + if (vpix->gmr) { + struct vmwgfx_dmabuf *gmr; + void *new_addr; + void *old_addr; + + gmr = vmwgfx_dmabuf_alloc(vsaa->drm_fd, size); + if (!gmr) + return FALSE; + + new_addr = vmwgfx_dmabuf_map(gmr); + old_addr = vmwgfx_dmabuf_map(vpix->gmr); + + if (new_addr && old_addr) + vmwgfx_copy_stride(new_addr, old_addr, pixmap->devKind, + old_pitch, draw->height, + old_height); + else + LogMessage(X_ERROR, "Failed pixmap resize copy.\n"); + + if (old_addr) + vmwgfx_dmabuf_unmap(vpix->gmr); + if (new_addr) + vmwgfx_dmabuf_unmap(gmr); + vmwgfx_dmabuf_destroy(vpix->gmr); + vpix->gmr = gmr; + } + + if (vpix->hw) { + if (xa_surface_redefine(vpix->hw, draw->width, draw->height, + draw->depth, xa_type_argb, + xa_format_unknown, 0, 0, 1) != 0) + return FALSE; + } + return TRUE; +} + + +static Bool +vmwgfx_modify_pixmap_header (PixmapPtr pixmap, int w, int h, int depth, + int bpp, int devkind, void *pixdata) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + unsigned int old_height; + unsigned int old_width; + unsigned int old_pitch; + + if (!vpix) { + LogMessage(X_ERROR, "Not an SAA pixmap.\n"); + return FALSE; + } + + if (pixdata) { + vpix->backing = 0; + vmwgfx_pixmap_free_storage(vpix); + return FALSE; + } + + if (depth <= 0) + depth = pixmap->drawable.depth; + + if (bpp <= 0) + bpp = pixmap->drawable.bitsPerPixel; + + if (w <= 0) + w = pixmap->drawable.width; + + if (h <= 0) + h = pixmap->drawable.height; + + if (w <= 0 || h <= 0 || depth <= 0) + return FALSE; + + old_height = pixmap->drawable.height; + old_width = pixmap->drawable.width; + old_pitch = pixmap->devKind; + + if (!miModifyPixmapHeader(pixmap, w, h, depth, + bpp, devkind, NULL)) + goto out_no_modify; + + if (!vpix->backing) + vpix->backing = VMWGFX_PIX_MALLOC; + + vmwgfx_pix_resize(pixmap, old_pitch, old_height, old_width); + vmwgfx_pixmap_add_damage(pixmap); + vmwgfx_pixmap_free_storage(vpix); + return TRUE; + + out_no_modify: + return FALSE; +} + +static Bool +vmwgfx_present_prepare(struct vmwgfx_saa *vsaa, + struct vmwgfx_saa_pixmap *src_vpix, + struct vmwgfx_saa_pixmap *dst_vpix) +{ + ScreenPtr pScreen = vsaa->pScreen; + unsigned int dummy; + + (void) pScreen; + if (src_vpix == dst_vpix || !src_vpix->hw || + xa_surface_handle(src_vpix->hw, &vsaa->src_handle, &dummy) != 0) + return FALSE; + + REGION_NULL(pScreen, &vsaa->present_region); + vsaa->diff_valid = FALSE; + vsaa->dst_vpix = dst_vpix; + vsaa->present_flush(pScreen); + + return TRUE; +} + +/** + * Determine whether we should try present copies on this pixmap. + */ + +static Bool +vmwgfx_is_present_hw(PixmapPtr pixmap) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + return (vpix->dirty_present != NULL); +} + +static void +vmwgfx_check_hw_contents(struct vmwgfx_saa *vsaa, + struct vmwgfx_saa_pixmap *vpix, + RegionPtr region, + Bool *has_dirty_hw, + Bool *has_valid_hw) +{ + RegionRec intersection; + + + if (!vpix->hw) { + *has_dirty_hw = FALSE; + *has_valid_hw = FALSE; + return; + } + + if (!region) { + *has_dirty_hw = REGION_NOTEMPTY(vsaa->pScreen, + &vpix->base.dirty_hw); + *has_valid_hw = !REGION_NOTEMPTY(vsaa->pScreen, + &vpix->base.dirty_shadow); + return; + } + + REGION_NULL(vsaa->pScreen, &intersection); + REGION_INTERSECT(vsaa->pScreen, &intersection, &vpix->base.dirty_hw, + region); + *has_dirty_hw = REGION_NOTEMPTY(vsaa->pScreen, &intersection); + REGION_INTERSECT(vsaa->pScreen, &intersection, &vpix->base.dirty_shadow, + region); + *has_valid_hw = !REGION_NOTEMPTY(vsaa->pScreen, &intersection); + REGION_UNINIT(vsaa->pScreen, &intersection); +} + +static Bool +vmwgfx_copy_prepare(struct saa_driver *driver, + PixmapPtr src_pixmap, + PixmapPtr dst_pixmap, + int dx, + int dy, + int alu, + RegionPtr src_reg, + uint32_t plane_mask) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + struct vmwgfx_saa_pixmap *src_vpix; + struct vmwgfx_saa_pixmap *dst_vpix; + Bool has_dirty_hw; + Bool has_valid_hw; + + if (!vsaa->xat || !SAA_PM_IS_SOLID(&dst_pixmap->drawable, plane_mask) || + alu != GXcopy) + return FALSE; + + src_vpix = vmwgfx_saa_pixmap(src_pixmap); + dst_vpix = vmwgfx_saa_pixmap(dst_pixmap); + + vmwgfx_check_hw_contents(vsaa, src_vpix, src_reg, + &has_dirty_hw, &has_valid_hw); + + if (vmwgfx_is_present_hw(dst_pixmap) && + src_vpix->backing & VMWGFX_PIX_SURFACE) { + + if (!has_dirty_hw && !has_valid_hw) + return FALSE; + + if (vmwgfx_present_prepare(vsaa, src_vpix, dst_vpix)) { + if (!vmwgfx_pixmap_validate_hw(src_pixmap, src_reg, 0, 0)) + return FALSE; + vsaa->present_copy = TRUE; + return TRUE; + } + return FALSE; + } + + vsaa->present_copy = FALSE; + if (src_vpix->hw != NULL && src_vpix != dst_vpix) { + + /* + * Use hardware acceleration either if source is partially only + * in hardware, or if source is entirely in hardware and destination + * has a hardware surface. + */ + + if (!has_dirty_hw && !(has_valid_hw && (dst_vpix->hw != NULL))) + return FALSE; + if (!vmwgfx_pixmap_validate_hw(src_pixmap, src_reg, 0, 0)) + return FALSE; + if (!vmwgfx_pixmap_create_hw(vsaa, dst_pixmap, XA_FLAG_RENDER_TARGET)) + return FALSE; + + if (xa_copy_prepare(vsaa->xa_ctx, dst_vpix->hw, src_vpix->hw) == 0) + return TRUE; + } + + return FALSE; +} + + +static void +vmwgfx_present_done(struct vmwgfx_saa *vsaa) +{ + ScreenPtr pScreen = vsaa->pScreen; + struct vmwgfx_saa_pixmap *dst_vpix = vsaa->dst_vpix; + + (void) pScreen; + if (!vsaa->diff_valid) + return; + + (void) vmwgfx_present(vsaa->drm_fd, vsaa->xdiff, vsaa->ydiff, + &vsaa->present_region, vsaa->src_handle); + + REGION_TRANSLATE(pScreen, &vsaa->present_region, vsaa->xdiff, vsaa->ydiff); + REGION_UNION(pScreen, dst_vpix->present_damage, dst_vpix->present_damage, + &vsaa->present_region); + vsaa->diff_valid = FALSE; + REGION_UNINIT(pScreen, &vsaa->present_region); +} + +static void +vmwgfx_present_copy(struct vmwgfx_saa *vsaa, + int src_x, + int src_y, + int dst_x, + int dst_y, + int w, + int h) +{ + int xdiff = dst_x - src_x; + int ydiff = dst_y - src_y; + BoxRec box; + RegionRec reg; + + if (vsaa->diff_valid && ((xdiff != vsaa->xdiff) || (ydiff != vsaa->ydiff))) + (void) vmwgfx_present_done(vsaa); + + if (!vsaa->diff_valid) { + vsaa->xdiff = xdiff; + vsaa->ydiff = ydiff; + vsaa->diff_valid = TRUE; + } + + box.x1 = src_x; + box.x2 = src_x + w; + box.y1 = src_y; + box.y2 = src_y + h; + + REGION_INIT(pScreen, ®, &box, 1); + REGION_UNION(pScreen, &vsaa->present_region, &vsaa->present_region, ®); + REGION_UNINIT(pScreen, ®); +} + +static void +vmwgfx_copy(struct saa_driver *driver, + int src_x, + int src_y, + int dst_x, + int dst_y, + int w, + int h) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + + if (vsaa->present_copy) { + vmwgfx_present_copy(vsaa, src_x, src_y, dst_x, dst_y, w, h); + return; + } + xa_copy(vsaa->xa_ctx, dst_x, dst_y, src_x, src_y, w, h); +} + +static void +vmwgfx_copy_done(struct saa_driver *driver) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + + if (vsaa->present_copy) { + vmwgfx_present_done(vsaa); + } + xa_copy_done(vsaa->xa_ctx); +} + +static void +vmwgfx_takedown(struct saa_driver *driver) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + + free(vsaa); +} + +static void +vmwgfx_operation_complete(struct saa_driver *driver, + PixmapPtr pixmap) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + + /* + * Make dri2 drawables up to date, or add them to the flush list + * executed at glxWaitX(). + */ + + if (vpix->hw && vpix->hw_is_dri2_fronts) { + if (1) { + if (!vmwgfx_upload_to_hw(driver, pixmap, &spix->dirty_shadow)) + return; + REGION_EMPTY(vsaa->pScreen, &spix->dirty_shadow); + } else { + if (!vpix->prevnext_dri2) + vmwgfx_add_dri2_list(vsaa, vpix); + } + } +} + + +static Bool +vmwgfx_dirty(struct saa_driver *driver, PixmapPtr pixmap, + Bool hw, RegionPtr damage) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + BoxPtr rects; + int num_rects; + + if (!vmwgfx_is_present_hw(pixmap)) + return TRUE; + + rects = REGION_RECTS(damage); + num_rects = REGION_NUM_RECTS(damage); + + /* + * Is the new scanout damage hw or sw? + */ + + if (hw) { + /* + * Dump pending present into present tracking region. + */ + if (REGION_NOTEMPTY(vsaa->pScreen, vpix->present_damage)) { + REGION_UNION(vsaa->pScreen, vpix->dirty_present, + vpix->dirty_present, damage); + REGION_EMPTY(vsaa->pScreen, vpix->present_damage); + } else { + if (REGION_NOTEMPTY(vsaa->pScreen, vpix->pending_update)) { + RegionRec reg; + + REGION_NULL(vsaa->pScreen, ®); + REGION_INTERSECT(vsaa->pScreen, ®, vpix->pending_update, + damage); + if (REGION_NOTEMPTY(vsaa->pScreen, ®)) + vsaa->present_flush(vsaa->pScreen); + REGION_UNINIT(pScreen, ®); + } + REGION_UNION(vsaa->pScreen, vpix->pending_present, + vpix->pending_present, damage); + } + } else { + if (REGION_NOTEMPTY(vsaa->pScreen, vpix->pending_present)) { + RegionRec reg; + + REGION_NULL(vsaa->pScreen, ®); + REGION_INTERSECT(vsaa->pScreen, ®, vpix->pending_present, + damage); + if (REGION_NOTEMPTY(vsaa->pScreen, ®)) + vsaa->present_flush(vsaa->pScreen); + REGION_UNINIT(pScreen, ®); + } + REGION_UNION(vsaa->pScreen, vpix->pending_update, + vpix->pending_update, damage); + } + + return TRUE; +} + + +static const struct saa_driver vmwgfx_saa_driver = { + .saa_major = SAA_VERSION_MAJOR, + .saa_minor = SAA_VERSION_MINOR, + .pixmap_size = sizeof(struct vmwgfx_saa_pixmap), + .damage = vmwgfx_dirty, + .operation_complete = vmwgfx_operation_complete, + .download_from_hw = vmwgfx_download_from_hw, + .release_from_cpu = vmwgfx_release_from_cpu, + .sync_for_cpu = vmwgfx_sync_for_cpu, + .map = vmwgfx_map, + .unmap = vmwgfx_unmap, + .create_pixmap = vmwgfx_create_pixmap, + .destroy_pixmap = vmwgfx_destroy_pixmap, + .modify_pixmap_header = vmwgfx_modify_pixmap_header, + .copy_prepare = vmwgfx_copy_prepare, + .copy = vmwgfx_copy, + .copy_done = vmwgfx_copy_done, + .takedown = vmwgfx_takedown, +}; + + +Bool +vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, + void (*present_flush)(ScreenPtr pScreen)) +{ + struct vmwgfx_saa *vsaa; + + vsaa = calloc(1, sizeof(*vsaa)); + if (!vsaa) + return FALSE; + + vsaa->pScreen = pScreen; + vsaa->xat = xat; + if (xat) + vsaa->xa_ctx = xa_context_default(xat); + vsaa->drm_fd = drm_fd; + vsaa->present_flush = present_flush; + vsaa->can_optimize_dma = FALSE; + + vsaa->driver = vmwgfx_saa_driver; + if (!saa_driver_init(pScreen, &vsaa->driver)) + goto out_no_saa; + + return TRUE; + out_no_saa: + free(vsaa); + return FALSE; +} + +/* + * ************************************************************************* + * Scanout functions. + * These do not strictly belong here, but we choose to hide the scanout + * pixmap private data in the saa pixmaps. Might want to revisit this. + */ + +/* + * Make sure we flush / update this scanout on next update run. + */ + +void +vmwgfx_scanout_refresh(PixmapPtr pixmap) +{ + ScreenPtr pScreen = pixmap->drawable.pScreen; + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + BoxRec box; + + (void) pScreen; + box.x1 = 0; + box.y1 = 0; + box.x2 = pixmap->drawable.width; + box.y2 = pixmap->drawable.height; + + REGION_RESET(vsaa->pScreen, vpix->pending_update, &box); + REGION_SUBTRACT(vsaa->pScreen, vpix->pending_present, + &vpix->base.dirty_hw, vpix->dirty_present); + REGION_SUBTRACT(vsaa->pScreen, vpix->pending_update, + vpix->pending_update, &vpix->base.dirty_hw); +} + +/* + * Take a "scanout reference" on a pixmap. If this is the first scanout + * reference, allocate resources needed for scanout, like proper + * damage tracking and kms fbs. + */ + +uint32_t +vmwgfx_scanout_ref(PixmapPtr pixmap) +{ + struct vmwgfx_saa *vsaa = + to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + int ret; + + if (vpix->scanout_refcnt++ == 0) { + ret = !vmwgfx_pixmap_create_gmr(vsaa, pixmap); + if (!ret) + ret = !vmwgfx_pixmap_add_present(pixmap); + if (!ret) + ret = drmModeAddFB(vsaa->drm_fd, + pixmap->drawable.width, + pixmap->drawable.height, + pixmap->drawable.depth, + pixmap->drawable.bitsPerPixel, + pixmap->devKind, + vpix->gmr->handle, + &vpix->fb_id); + if (!ret) { +// vmwgfx_scanout_refresh(pixmap); + } + if (ret) { + vpix->fb_id = -1; + --vpix->scanout_refcnt; + } + } + return vpix->fb_id; +} + +/* + * Free a "scanout reference" on a pixmap. If this was the last scanout + * reference, free pixmap resources needed for scanout, like + * damage tracking and kms fbs. + */ +void +vmwgfx_scanout_unref(PixmapPtr pixmap) +{ + struct vmwgfx_saa *vsaa; + struct vmwgfx_saa_pixmap *vpix; + + if (!pixmap) + return; + + vsaa = to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); + vpix = vmwgfx_saa_pixmap(pixmap); + if (--vpix->scanout_refcnt == 0) { + REGION_EMPTY(vsaa->pScreen, vpix->pending_update); + drmModeRmFB(vsaa->drm_fd, vpix->fb_id); + vpix->fb_id = -1; + vmwgfx_pixmap_present_readback(vsaa, pixmap, NULL); + vmwgfx_pixmap_remove_present(vpix); + vmwgfx_pixmap_remove_damage(pixmap); + } +} diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h new file mode 100644 index 0000000..1a42cac --- /dev/null +++ b/vmwgfx/vmwgfx_saa.h @@ -0,0 +1,94 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Thomas Hellstrom + */ + +#ifndef _VMWGFX_SAA_H_ +#define _VMWGFX_SAA_H_ + +#include "saa.h" +#include +#include "vmwgfx_drmi.h" + +#define VMWGFX_FLAG_FORCE_GMR (1 << 0) /* Create with GMR as backing store */ +#define VMWGFX_FLAG_FORCE_SURFACE (1 << 1) /* Create with surface as backing store */ +#define VMWGFX_FLAG_AVOID_HWACCEL (1 << 2) /* Avoid Hardware acceleration on this pixmap */ +#define VMWGFX_FLAG_USE_PRESENT (1 << 3) /* Use presents when copying to this pixmap */ + +struct vmwgfx_saa_pixmap { + struct saa_pixmap base; + RegionPtr dirty_present; + RegionPtr present_damage; + RegionPtr pending_update; + RegionPtr pending_present; + uint32_t usage_flags; + uint32_t backing; + void *malloc; + struct vmwgfx_dmabuf *gmr; + struct xa_surface *hw; + int scanout_refcnt; + uint32_t fb_id; + int hw_is_dri2_fronts; + struct vmwgfx_saa_pixmap *next_dri2; + struct vmwgfx_saa_pixmap **prevnext_dri2; +}; + +static inline struct vmwgfx_saa_pixmap * +to_vmwgfx_saa_pixmap(struct saa_pixmap *spix) +{ + return (struct vmwgfx_saa_pixmap *) spix; +} + +extern Bool +vmwgfx_pixmap_validate_hw(PixmapPtr pixmap, RegionPtr region, + unsigned int add_flags, + unsigned int remove_flags); + +static inline struct vmwgfx_saa_pixmap* +vmwgfx_saa_pixmap(PixmapPtr pix) +{ + return to_vmwgfx_saa_pixmap(saa_get_saa_pixmap(pix)); +} + +extern Bool +vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, + void (*present_flush)(ScreenPtr pScreen)); + +extern uint32_t +vmwgfx_scanout_ref(PixmapPtr pixmap); + +extern void +vmwgfx_scanout_unref(PixmapPtr pixmap); + +extern void +vmwgfx_scanout_refresh(PixmapPtr pixmap); + +extern void +vmwgfx_remove_dri2_list(struct vmwgfx_saa_pixmap *vpix); + +extern void +vmwgfx_flush_dri2(ScreenPtr pScreen); + +#endif diff --git a/vmwgfx/vmwgfx_tex_video.c b/vmwgfx/vmwgfx_tex_video.c new file mode 100644 index 0000000..fb8f41e --- /dev/null +++ b/vmwgfx/vmwgfx_tex_video.c @@ -0,0 +1,723 @@ +/* + * Copyright 2009-2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Thomas Hellstrom + * Author: Zack Rusin + */ + +#include "vmwgfx_driver.h" +#include "vmwgfx_drmi.h" +#include "vmwgfx_saa.h" + +#include +#include +#include +#include +#include + + +/*XXX get these from pipe's texture limits */ +#define IMAGE_MAX_WIDTH 2048 +#define IMAGE_MAX_HEIGHT 2048 + +#define RES_720P_X 1280 +#define RES_720P_Y 720 + + +/* The ITU-R BT.601 conversion matrix for SDTV. */ +/* original, matrix, but we transpose it to + * make the shader easier +static const float bt_601[] = { + 1.0, 0.0, 1.4075, , + 1.0, -0.3455, -0.7169, 0, + 1.0, 1.7790, 0., 0, +};*/ +static const float bt_601[] = { + 1.0, 1.0, 1.0, 0.5, + 0.0, -0.3455, 1.7790, 0, + 1.4075, -0.7169, 0., 0, +}; + +/* The ITU-R BT.709 conversion matrix for HDTV. */ +/* original, but we transpose to make the conversion + * in the shader easier +static const float bt_709[] = { + 1.0, 0.0, 1.581, 0, + 1.0, -0.1881, -0.47, 0, + 1.0, 1.8629, 0., 0, +};*/ +static const float bt_709[] = { + 1.0, 1.0, 1.0, 0.5, + 0.0, -0.1881, 1.8629, 0, + 1.581,-0.47 , 0.0, 0, +}; + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvBrightness, xvContrast; + +#define NUM_TEXTURED_ATTRIBUTES 2 +static XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = { + {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} +}; + +#define NUM_FORMATS 3 +static XF86VideoFormatRec Formats[NUM_FORMATS] = { + {15, TrueColor}, {16, TrueColor}, {24, TrueColor} +}; + +static XF86VideoEncodingRec DummyEncoding[1] = { + { + 0, + "XV_IMAGE", + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + {1, 1} + } +}; + +#define NUM_IMAGES 3 +static XF86ImageRec Images[NUM_IMAGES] = { + XVIMAGE_UYVY, + XVIMAGE_YUY2, + XVIMAGE_YV12, +}; + +struct xorg_xv_port_priv { + struct xa_tracker *xat; + struct xa_context *r; + struct xa_fence *fence; + + RegionRec clip; + + int brightness; + int contrast; + + int current_set; + struct vmwgfx_dmabuf *bounce[2][3]; + struct xa_surface *yuv[3]; + + int drm_fd; +}; + + +static void +stop_video(ScrnInfoPtr pScrn, pointer data, Bool shutdown) +{ + struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; + int i, j; + + REGION_EMPTY(pScrn->pScreen, &priv->clip); + if (shutdown) { + + /* + * No need to destroy the xa context or xa tracker since + * they are copied from the screen resources. + */ + + xa_fence_destroy(priv->fence); + priv->fence = NULL; + + for (i=0; i<3; ++i) { + if (priv->yuv[i]) { + xa_surface_destroy(priv->yuv[i]); + priv->yuv[i] = NULL; + } + for (j=0; j<2; ++j) { + if (priv->bounce[j][i]) { + vmwgfx_dmabuf_destroy(priv->bounce[j][i]); + priv->bounce[0][i] = NULL; + } + } + } + } +} + +static int +set_port_attribute(ScrnInfoPtr pScrn, + Atom attribute, INT32 value, pointer data) +{ + struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; + + if (attribute == xvBrightness) { + if ((value < -128) || (value > 127)) + return BadValue; + priv->brightness = value; + } else if (attribute == xvContrast) { + if ((value < 0) || (value > 255)) + return BadValue; + priv->contrast = value; + } else + return BadMatch; + + return Success; +} + +static int +get_port_attribute(ScrnInfoPtr pScrn, + Atom attribute, INT32 * value, pointer data) +{ + struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; + + if (attribute == xvBrightness) + *value = priv->brightness; + else if (attribute == xvContrast) + *value = priv->contrast; + else + return BadMatch; + + return Success; +} + +static void +query_best_size(ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, pointer data) +{ + if (vid_w > (drw_w << 1)) + drw_w = vid_w >> 1; + if (vid_h > (drw_h << 1)) + drw_h = vid_h >> 1; + + *p_w = drw_w; + *p_h = drw_h; +} + +static int +check_yuv_surfaces(struct xorg_xv_port_priv *priv, int width, int height) +{ + struct xa_surface **yuv = priv->yuv; + struct vmwgfx_dmabuf **bounce = priv->bounce[priv->current_set]; + int ret = 0; + int i; + size_t size; + + for (i=0; i<3; ++i) { + if (!yuv[i]) + yuv[i] = xa_surface_create(priv->xat, width, height, 8, + xa_type_yuv_component, + xa_format_unknown, 0); + else + ret = xa_surface_redefine(yuv[i], width, height, 8, + xa_type_yuv_component, + xa_format_unknown, 0, 0, 0); + if (ret || !yuv[i]) + return BadAlloc; + + size = width * height; + + if (bounce[i] && (bounce[i]->size < size || + bounce[i]->size > 2*size)) { + vmwgfx_dmabuf_destroy(bounce[i]); + bounce[i] = NULL; + } + + if (!bounce[i]) { + bounce[i] = vmwgfx_dmabuf_alloc(priv->drm_fd, size); + if (!bounce[i]) + return BadAlloc; + } + } + return Success; +} + +static int +query_image_attributes(ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets) +{ + int size, tmp; + + if (*w > IMAGE_MAX_WIDTH) + *w = IMAGE_MAX_WIDTH; + if (*h > IMAGE_MAX_HEIGHT) + *h = IMAGE_MAX_HEIGHT; + + *w = (*w + 1) & ~1; + if (offsets) + offsets[0] = 0; + + switch (id) { + case FOURCC_YV12: + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if (pitches) { + pitches[0] = size; + } + size *= *h; + if (offsets) { + offsets[1] = size; + } + tmp = ((*w >> 1) + 3) & ~3; + if (pitches) { + pitches[1] = pitches[2] = tmp; + } + tmp *= (*h >> 1); + size += tmp; + if (offsets) { + offsets[2] = size; + } + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + size = *w << 1; + if (pitches) + pitches[0] = size; + size *= *h; + break; + } + + return size; +} + +static int +copy_packed_data(ScrnInfoPtr pScrn, + struct xorg_xv_port_priv *port, + int id, + unsigned char *buf, + int left, + int top, + unsigned short w, unsigned short h) +{ + int i, j; + struct vmwgfx_dmabuf **bounce = port->bounce[port->current_set]; + char *ymap, *vmap, *umap; + unsigned char y1, y2, u, v; + int yidx, uidx, vidx; + int y_array_size = w * h; + int ret = BadAlloc; + + /* + * Here, we could use xa_surface_[map|unmap], but given the size of + * the yuv textures, that could stress the xa tracker dma buffer pool, + * particularaly with multiple videos rendering simultaneously. + * + * Instead, cheat and allocate vmwgfx dma buffers directly. + */ + + ymap = (char *)vmwgfx_dmabuf_map(bounce[0]); + if (!ymap) + return BadAlloc; + umap = (char *)vmwgfx_dmabuf_map(bounce[1]); + if (!umap) + goto out_no_umap; + vmap = (char *)vmwgfx_dmabuf_map(bounce[2]); + if (!vmap) + goto out_no_vmap; + + + yidx = uidx = vidx = 0; + + switch (id) { + case FOURCC_YV12: { + int pitches[3], offsets[3]; + unsigned char *y, *u, *v; + query_image_attributes(pScrn, FOURCC_YV12, + &w, &h, pitches, offsets); + + y = buf + offsets[0]; + v = buf + offsets[1]; + u = buf + offsets[2]; + for (i = 0; i < h; ++i) { + for (j = 0; j < w; ++j) { + int yoffset = (w*i+j); + int ii = (i|1), jj = (j|1); + int vuoffset = (w/2)*(ii/2) + (jj/2); + ymap[yidx++] = y[yoffset]; + umap[uidx++] = u[vuoffset]; + vmap[vidx++] = v[vuoffset]; + } + } + } + break; + case FOURCC_UYVY: + for (i = 0; i < y_array_size; i +=2 ) { + /* extracting two pixels */ + u = buf[0]; + y1 = buf[1]; + v = buf[2]; + y2 = buf[3]; + buf += 4; + + ymap[yidx++] = y1; + ymap[yidx++] = y2; + umap[uidx++] = u; + umap[uidx++] = u; + vmap[vidx++] = v; + vmap[vidx++] = v; + } + break; + case FOURCC_YUY2: + for (i = 0; i < y_array_size; i +=2 ) { + /* extracting two pixels */ + y1 = buf[0]; + u = buf[1]; + y2 = buf[2]; + v = buf[3]; + + buf += 4; + + ymap[yidx++] = y1; + ymap[yidx++] = y2; + umap[uidx++] = u; + umap[uidx++] = u; + vmap[vidx++] = v; + vmap[vidx++] = v; + } + break; + default: + ret = BadAlloc; + break; + } + + ret = Success; + vmwgfx_dmabuf_unmap(bounce[2]); + out_no_vmap: + vmwgfx_dmabuf_unmap(bounce[1]); + out_no_umap: + vmwgfx_dmabuf_unmap(bounce[0]); + + if (ret == Success) { + struct xa_surface *srf; + struct vmwgfx_dmabuf *buf; + uint32_t handle; + unsigned int stride; + BoxRec box; + RegionRec reg; + + box.x1 = 0; + box.x2 = w; + box.y1 = 0; + box.y2 = h; + + REGION_INIT(pScrn->pScreen, ®, &box, 1); + + for (i=0; i<3; ++i) { + srf = port->yuv[i]; + buf = bounce[i]; + + if (xa_surface_handle(srf, &handle, &stride) != 0) { + ret = BadAlloc; + break; + } + + if (vmwgfx_dma(0, 0, ®, buf, w, handle, 1) != 0) { + ret = BadAlloc; + break; + } + } + REGION_UNINIT(pScrn->pScreen, ®); + } + + return ret; +} + + +static int +display_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id, + RegionPtr dstRegion, + int src_x, int src_y, int src_w, int src_h, + int dst_x, int dst_y, int dst_w, int dst_h, + PixmapPtr pPixmap) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pPixmap); + Bool hdtv; + RegionRec reg; + int ret = BadAlloc; + int blit_ret; + const float *conv_matrix; + + REGION_NULL(pScreen, ®); + + if (!vmwgfx_pixmap_validate_hw(pPixmap, ®, XA_FLAG_RENDER_TARGET, 0)) + goto out_no_dst; + + hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y)); + conv_matrix = (hdtv ? bt_709 : bt_601); + +#ifdef COMPOSITE + + /* + * For redirected windows, we need to fix up the destination coordinates. + */ + + REGION_TRANSLATE(pScreen, dstRegion, -pPixmap->screen_x, + -pPixmap->screen_y); + dst_x -= pPixmap->screen_x; + dst_y -= pPixmap->screen_y; +#endif + + /* + * Throttle on previous blit. + */ + + if (pPriv->fence) { + (void) xa_fence_wait(pPriv->fence, 1000000000ULL); + xa_fence_destroy(pPriv->fence); + pPriv->fence = NULL; + } + + DamageRegionAppend(&pPixmap->drawable, dstRegion); + + blit_ret = xa_yuv_planar_blit(pPriv->r, src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h, + (struct xa_box *)REGION_RECTS(dstRegion), + REGION_NUM_RECTS(dstRegion), + conv_matrix, + vpix->hw, pPriv->yuv); + + saa_pixmap_dirty(pPixmap, TRUE, dstRegion); + DamageRegionProcessPending(&pPixmap->drawable); + ret = Success; + + if (!blit_ret) { + ret = Success; + pPriv->fence = xa_fence_get(pPriv->r); + } else + ret = BadAlloc; + + out_no_dst: + REGION_UNINIT(pScreen, ®); + return ret; +} + +static int +put_image(ScrnInfoPtr pScrn, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + int id, unsigned char *buf, + short width, short height, + Bool sync, RegionPtr clipBoxes, pointer data, + DrawablePtr pDraw) +{ + struct xorg_xv_port_priv *pPriv = (struct xorg_xv_port_priv *) data; + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + PixmapPtr pPixmap; + INT32 x1, x2, y1, y2; + BoxRec dstBox; + int ret; + + /* Clip */ + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, + width, height)) + return Success; + + ret = check_yuv_surfaces(pPriv, width, height); + if (ret) + return ret; + + ret = copy_packed_data(pScrn, pPriv, id, buf, + src_x, src_y, width, height); + if (ret) + return ret; + + if (pDraw->type == DRAWABLE_WINDOW) { + pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw); + } else { + pPixmap = (PixmapPtr)pDraw; + } + + display_video(pScrn->pScreen, pPriv, id, clipBoxes, + src_x, src_y, src_w, src_h, + drw_x, drw_y, + drw_w, drw_h, pPixmap); + + pPriv->current_set = (pPriv->current_set + 1) & 1; + return Success; +} + +static struct xorg_xv_port_priv * +port_priv_create(struct xa_tracker *xat, struct xa_context *r, + int drm_fd) +{ + struct xorg_xv_port_priv *priv = NULL; + + priv = calloc(1, sizeof(struct xorg_xv_port_priv)); + + if (!priv) + return NULL; + + priv->r = r; + priv->xat = xat; + priv->drm_fd = drm_fd; + REGION_NULL(pScreen, &priv->clip); + + return priv; +} + +static void +vmwgfx_free_textured_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports) +{ + if (free_ports) { + int i; + + for(i=0; inPorts; ++i) { + free(adaptor->pPortPrivates[i].ptr); + } + } + + free(adaptor->pAttributes); + free(adaptor->pPortPrivates); + xf86XVFreeVideoAdaptorRec(adaptor); +} + +static XF86VideoAdaptorPtr +xorg_setup_textured_adapter(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + modesettingPtr ms = modesettingPTR(pScrn); + XF86VideoAdaptorPtr adapt; + XF86AttributePtr attrs; + DevUnion *dev_unions; + int nports = 16, i; + int nattributes; + struct xa_context *xar; + + /* + * Use the XA default context since we don't expect the X server + * to render from multiple threads. + */ + + xar = xa_context_default(ms->xat); + nattributes = NUM_TEXTURED_ATTRIBUTES; + + adapt = calloc(1, sizeof(XF86VideoAdaptorRec)); + dev_unions = calloc(nports, sizeof(DevUnion)); + attrs = calloc(nattributes, sizeof(XF86AttributeRec)); + if (adapt == NULL || dev_unions == NULL || attrs == NULL) { + free(adapt); + free(dev_unions); + free(attrs); + return NULL; + } + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = 0; + adapt->name = "XA G3D Textured Video"; + adapt->nEncodings = 1; + adapt->pEncodings = DummyEncoding; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = 0; + adapt->pPortPrivates = dev_unions; + adapt->nAttributes = nattributes; + adapt->pAttributes = attrs; + memcpy(attrs, TexturedAttributes, nattributes * sizeof(XF86AttributeRec)); + adapt->nImages = NUM_IMAGES; + adapt->pImages = Images; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = stop_video; + adapt->SetPortAttribute = set_port_attribute; + adapt->GetPortAttribute = get_port_attribute; + adapt->QueryBestSize = query_best_size; + adapt->PutImage = put_image; + adapt->QueryImageAttributes = query_image_attributes; + + + for (i = 0; i < nports; i++) { + struct xorg_xv_port_priv *priv = + port_priv_create(ms->xat, xar, ms->fd); + + adapt->pPortPrivates[i].ptr = (pointer) (priv); + adapt->nPorts++; + } + + return adapt; +} + +void +xorg_xv_init(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + modesettingPtr ms = modesettingPTR(pScrn); + XF86VideoAdaptorPtr *adaptors, *new_adaptors = NULL; + XF86VideoAdaptorPtr textured_adapter = NULL, overlay_adaptor = NULL; + int num_adaptors; + + num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); + new_adaptors = malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *)); + if (new_adaptors == NULL) + return; + + memcpy(new_adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); + adaptors = new_adaptors; + + /* Add the adaptors supported by our hardware. First, set up the atoms + * that will be used by both output adaptors. + */ + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + + if (ms->xat) { + textured_adapter = xorg_setup_textured_adapter(pScreen); + if (textured_adapter) + adaptors[num_adaptors++] = textured_adapter; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No 3D acceleration. Not setting up textured video.\n"); + } + + overlay_adaptor = vmw_video_init_adaptor(pScrn); + if (overlay_adaptor) + adaptors[num_adaptors++] = overlay_adaptor; + + if (num_adaptors) { + Bool ret; + ret = xf86XVScreenInit(pScreen, adaptors, num_adaptors); + if (textured_adapter) + vmwgfx_free_textured_adaptor(textured_adapter, !ret); + if (overlay_adaptor) + vmw_video_free_adaptor(overlay_adaptor, !ret); + if (!ret) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to initialize Xv.\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling Xv because no adaptors could be initialized.\n"); + } + + + out_err_mem: + free(adaptors); +} -- cgit v1.2.3 From d28613e557fcdc4fc69f9a138a8c5fc909a719f5 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 16 Jun 2011 21:21:25 +0200 Subject: vmwgfx: Fix up driver build process for Xserver >= 1.7. Signed-off-by: Thomas Hellstrom --- Makefile.am | 2 +- configure.ac | 24 +++++++++++++++++++++--- saa/saa.c | 1 + saa/saa_accel.c | 7 +++++++ saa/saa_priv.h | 4 ++-- saa/saa_render.c | 6 +++--- vmwgfx/Makefile.am | 5 +++-- vmwgfx/vmwgfx_dri2.c | 21 ++------------------- vmwgfx/vmwgfx_driver.c | 3 +++ vmwgfx/vmwgfx_driver.h | 7 +++++++ vmwgfx/vmwgfx_overlay.c | 6 +++--- vmwgfx/vmwgfx_saa.c | 5 +++-- 12 files changed, 56 insertions(+), 35 deletions(-) diff --git a/Makefile.am b/Makefile.am index fff57f6..3208a23 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -SUBDIRS = src man vmwarectrl saa vmwgfx +SUBDIRS = src man vmwarectrl @VMWGFX_DIRS@ MAINTAINERCLEANFILES = ChangeLog INSTALL .PHONY: ChangeLog INSTALL diff --git a/configure.ac b/configure.ac index bbb530a..d4580ee 100644 --- a/configure.ac +++ b/configure.ac @@ -91,7 +91,8 @@ PKG_CHECK_EXISTS([xorg-server >= 1.4.99], PKG_CHECK_EXISTS([xorg-server >= 1.7.0], [AC_DEFINE([HAVE_XORG_SERVER_1_7_0], 1, - [Has version 1.7.0 or greater of the Xserver])]) + [Has version 1.7.0 or greater of the Xserver]) + BUILD_VMWGFX=yes],[BUILD_VMWGFX=yes]) # Obtain compiler/linker options for the vmwarectrl client tool PKG_CHECK_MODULES(X11, x11 xext) @@ -113,15 +114,32 @@ AM_CONDITIONAL(XSERVER_LIBPCIACCESS, test "x$XSERVER_LIBPCIACCESS" = xyes) AC_SUBST([moduledir]) +if test x$BUILD_VMWGFX = xyes; then + PKG_CHECK_MODULES([XATRACKER], [xatracker >= 0.1.0],[],[BUILD_VMWGFX=no]) +fi + DRIVER_NAME=vmware AC_SUBST([DRIVER_NAME]) + +VMWGFX_DIRS= +if test x$BUILD_VMWGFX = xyes; then + VMWGFX_DIRS="vmwgfx saa" + AC_CONFIG_FILES([ + saa/Makefile + vmwgfx/Makefile + ]) + echo "Will build the vmwgfx driver." +else + echo "Will not build the vmwgfx driver." +fi + +AC_SUBST([VMWGFX_DIRS]) AC_CONFIG_FILES([ Makefile src/Makefile vmwarectrl/Makefile man/Makefile - saa/Makefile - vmwgfx/Makefile ]) + AC_OUTPUT diff --git a/saa/saa.c b/saa/saa.c index e9567e3..9d7436b 100644 --- a/saa/saa.c +++ b/saa/saa.c @@ -39,6 +39,7 @@ #include "dixfontstr.h" #include "regionstr.h" #include "saa.h" +#include "saa_priv.h" #ifdef SAA_DEVPRIVATEKEYREC DevPrivateKeyRec saa_screen_index; diff --git a/saa/saa_accel.c b/saa/saa_accel.c index be33170..7bd5d61 100644 --- a/saa/saa_accel.c +++ b/saa/saa_accel.c @@ -30,6 +30,7 @@ #include "saa.h" #include "saa_priv.h" +#include Bool saa_hw_copy_nton(DrawablePtr pSrcDrawable, @@ -135,7 +136,13 @@ saa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, srcx, srcy, width, height, dstx, dsty); } +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 6) return miDoCopy(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, saa_copy_nton, 0, NULL); +#else + return fbDoCopy(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, + dstx, dsty, saa_copy_nton, 0, NULL); +#endif } diff --git a/saa/saa_priv.h b/saa/saa_priv.h index f86f196..c961345 100644 --- a/saa/saa_priv.h +++ b/saa/saa_priv.h @@ -181,10 +181,10 @@ saa_gc(GCPtr gc) &saa_gc_index); } -static inline struct saa_pixmap_priv * +static inline struct saa_pixmap * saa_pixmap(PixmapPtr pix) { - return (struct saa_pixmap_priv *)dixLookupPrivateAddr(&pix->devPrivates, + return (struct saa_pixmap *)dixLookupPrivateAddr(&pix->devPrivates, &saa_pixmap_index); } diff --git a/saa/saa_render.c b/saa/saa_render.c index 1df0dff..8c6e1e6 100644 --- a/saa/saa_render.c +++ b/saa/saa_render.c @@ -259,10 +259,10 @@ saa_copy_composite(CARD8 op, } ret = saa_hw_copy_nton(pSrc->pDrawable, pDst->pDrawable, NULL, - RegionRects(®ion), - RegionNumRects(®ion), + REGION_RECTS(®ion), + REGION_NUM_RECTS(®ion), xSrc - xDst, ySrc - yDst, FALSE, FALSE); - RegionUninit(®ion); + REGION_UNINIT(pDst->pDrwable.pScreen, ®ion); if (ret) return TRUE; } diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am index 5efa8cd..db58405 100644 --- a/vmwgfx/Makefile.am +++ b/vmwgfx/Makefile.am @@ -1,7 +1,8 @@ vmwgfx_drv_la_LTLIBRARIES = vmwgfx_drv.la vmwgfx_drv_la_LDFLAGS = -module -avoid-version -vmwgfx_drv_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) @LIBDRM_CFLAGS@ -I$(top_srcdir)/src -I$(top_srcdir)/saa -vmwgfx_drv_la_LIBADD = @LIBDRM_LIBS@ $(top_srcdir)/saa/.libs/libsaa.la -lxatracker +vmwgfx_drv_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) @LIBDRM_CFLAGS@ @XATRACKER_CFLAGS@ -I$(top_srcdir)/src -I$(top_srcdir)/saa +vmwgfx_drv_la_LIBADD = @LIBDRM_LIBS@ $(top_srcdir)/saa/.libs/libsaa.la\ + @XATRACKER_LIBS@ vmwgfx_drv_ladir = @moduledir@/drivers vmwgfx_drv_la_SOURCES = \ diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index 748cbc8..b80c813 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -42,14 +42,7 @@ #include "gc.h" #include "vmwgfx_saa.h" -struct vmwgfx_dri2_priv { - unsigned int srf_count; - struct xa_surface *srf[20]; -}; - -DevPrivateKeyRec dri2_pixmap_index; -DevPrivateKeyRec dri2_window_index; - +#ifdef DRI2 typedef struct { int refcount; PixmapPtr pPixmap; @@ -322,7 +315,6 @@ dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, FreeScratchGC(gc); } - Bool xorg_dri2_init(ScreenPtr pScreen) { @@ -339,16 +331,6 @@ xorg_dri2_init(ScreenPtr pScreen) minor = 0; } - if (!dixRegisterPrivateKey(&dri2_pixmap_index, PRIVATE_PIXMAP, 0)) { - LogMessage(X_ERROR, "Failed to register vmwgfx dri2 private.\n"); - return FALSE; - } - - if (!dixRegisterPrivateKey(&dri2_window_index, PRIVATE_WINDOW, 0)) { - LogMessage(X_ERROR, "Failed to register vmwgfx dri2 private.\n"); - return FALSE; - } - dri2info.version = min(DRI2INFOREC_VERSION, 3); dri2info.fd = ms->fd; @@ -369,5 +351,6 @@ xorg_dri2_close(ScreenPtr pScreen) { DRI2CloseScreen(pScreen); } +#endif /* vim: set sw=4 ts=8 sts=4: */ diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index edf384d..048534e 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -457,6 +457,9 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) #ifdef DRI2 if (!xf86LoadSubModule(pScrn, "dri2")) return FALSE; +#else + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Driver compiled without dri2 support." #endif return TRUE; diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h index 4339fb7..cb92bc9 100644 --- a/vmwgfx/vmwgfx_driver.h +++ b/vmwgfx/vmwgfx_driver.h @@ -45,6 +45,13 @@ #include #include +#ifdef DRI2 +#include +#if (!defined(DRI2INFOREC_VERSION) || (DRI2INFOREC_VERSION < 3)) +#undef DRI2 +#endif +#endif + #define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg); #define debug_printf(...) diff --git a/vmwgfx/vmwgfx_overlay.c b/vmwgfx/vmwgfx_overlay.c index d161023..28df983 100644 --- a/vmwgfx/vmwgfx_overlay.c +++ b/vmwgfx/vmwgfx_overlay.c @@ -410,13 +410,13 @@ vmw_video_port_init(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port, return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h, drw_w, drw_h, format, buf, width, height, clipBoxes); - out_bad_size: - (void) vmwgfx_unref_stream(port->drm_fd, port->streamId); - out_no_buffer: while(i-- != 0) { vmw_video_buffer_free(&port->bufs[i]); } + out_bad_size: + (void) vmwgfx_unref_stream(port->drm_fd, port->streamId); + return ret; } diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 3122353..5b84409 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -82,10 +82,11 @@ vmwgfx_pixmap_add_damage(PixmapPtr pixmap) box.y1 = 0; box.y2 = draw->height; - if (vpix->hw) + if (vpix->hw) { REGION_INIT(draw->pScreen, &spix->dirty_hw, &box, 1); - else + } else { REGION_INIT(draw->pScreen, &spix->dirty_shadow, &box, 1); + } return TRUE; } -- cgit v1.2.3 From 7966dfa47c4d2b022ebf0f25a2db3901376e6cbd Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 17 Jun 2011 08:18:13 +0200 Subject: vmwgfx, saa: Build saa as a convenience library instead of as a shared object. Signed-off-by: Thomas Hellstrom --- configure.ac | 2 +- saa/Makefile.am | 4 ++-- vmwgfx/Makefile.am | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index d4580ee..8deae86 100644 --- a/configure.ac +++ b/configure.ac @@ -124,7 +124,7 @@ AC_SUBST([DRIVER_NAME]) VMWGFX_DIRS= if test x$BUILD_VMWGFX = xyes; then - VMWGFX_DIRS="vmwgfx saa" + VMWGFX_DIRS="saa vmwgfx" AC_CONFIG_FILES([ saa/Makefile vmwgfx/Makefile diff --git a/saa/Makefile.am b/saa/Makefile.am index 4f56d3f..849ced9 100644 --- a/saa/Makefile.am +++ b/saa/Makefile.am @@ -1,7 +1,7 @@ -libsaa_la_LTLIBRARIES = libsaa.la -libsaa_ladir = @libdir@ +noinst_LTLIBRARIES = libsaa.la libsaa_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) +libsaa_la_LDFLAGS = -static libsaa_la_SOURCES = \ saa.c \ saa_pixmap.c \ diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am index db58405..ce4b115 100644 --- a/vmwgfx/Makefile.am +++ b/vmwgfx/Makefile.am @@ -1,7 +1,7 @@ vmwgfx_drv_la_LTLIBRARIES = vmwgfx_drv.la vmwgfx_drv_la_LDFLAGS = -module -avoid-version vmwgfx_drv_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) @LIBDRM_CFLAGS@ @XATRACKER_CFLAGS@ -I$(top_srcdir)/src -I$(top_srcdir)/saa -vmwgfx_drv_la_LIBADD = @LIBDRM_LIBS@ $(top_srcdir)/saa/.libs/libsaa.la\ +vmwgfx_drv_la_LIBADD = @LIBDRM_LIBS@ $(top_srcdir)/saa/libsaa.la\ @XATRACKER_LIBS@ vmwgfx_drv_ladir = @moduledir@/drivers -- cgit v1.2.3 From eabf82fad8ad72aab071cd4e3bc9063022b0aeb3 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 17 Jun 2011 11:25:53 +0200 Subject: vmwgfx: Check for large files Fixes segfault on 32-bit servers. Signed-off-by: Thomas Hellstrom --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 8deae86..1f060ae 100644 --- a/configure.ac +++ b/configure.ac @@ -124,6 +124,7 @@ AC_SUBST([DRIVER_NAME]) VMWGFX_DIRS= if test x$BUILD_VMWGFX = xyes; then + AC_SYS_LARGEFILE VMWGFX_DIRS="saa vmwgfx" AC_CONFIG_FILES([ saa/Makefile -- cgit v1.2.3 From eea0e6e242a604b1f4d85d947cf2b3f9f4977533 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 20 Jun 2011 09:05:48 +0200 Subject: vmwgfx: Import the WSBM list macros Use WSBM list handling macros for the glxWaitX flush list. Signed-off-by: Thomas Hellstrom --- vmwgfx/Makefile.am | 3 +- vmwgfx/vmwgfx_dri2.c | 3 +- vmwgfx/vmwgfx_saa.c | 55 ++++++++++-------------------------- vmwgfx/vmwgfx_saa.h | 4 +-- vmwgfx/wsbm_util.h | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 44 deletions(-) create mode 100644 vmwgfx/wsbm_util.h diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am index ce4b115..3c31543 100644 --- a/vmwgfx/Makefile.am +++ b/vmwgfx/Makefile.am @@ -19,7 +19,8 @@ vmwgfx_drv_la_SOURCES = \ vmwgfx_bootstrap.c \ vmwgfx_overlay.c \ vmwgfx_ctrl.c \ - vmwgfx_ctrl.h + vmwgfx_ctrl.h \ + wsbm_util.h diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index b80c813..1529cdb 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -41,6 +41,7 @@ #include "gcstruct.h" #include "gc.h" #include "vmwgfx_saa.h" +#include "wsbm_util.h" #ifdef DRI2 typedef struct { @@ -175,7 +176,7 @@ dri2_do_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer) if (private->refcount == 1) { struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(private->pPixmap); if (--vpix->hw_is_dri2_fronts == 0) - vmwgfx_remove_dri2_list(vpix); + WSBMLISTDELINIT(&vpix->sync_x_head); } private->srf = NULL; diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 5b84409..f733328 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -55,7 +55,7 @@ struct vmwgfx_saa { uint32_t src_handle; Bool can_optimize_dma; void (*present_flush) (ScreenPtr pScreen); - struct vmwgfx_saa_pixmap *dri2_flush_list; + struct _WsbmListHead sync_x_list; }; static inline struct vmwgfx_saa * @@ -426,57 +426,31 @@ vmwgfx_create_pixmap(struct saa_driver *driver, struct saa_pixmap *spix, int w, int h, int depth, unsigned int usage_hint, int bpp, int *new_pitch) { - *new_pitch = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + *new_pitch = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); + WSBMINITLISTHEAD(&vpix->sync_x_head); return TRUE; } - -static void -vmwgfx_add_dri2_list(struct vmwgfx_saa *vsaa, - struct vmwgfx_saa_pixmap *vpix) -{ - vpix->next_dri2 = vsaa->dri2_flush_list; - vpix->prevnext_dri2 = &vsaa->dri2_flush_list; - vsaa->dri2_flush_list = vpix; - if (vpix->next_dri2) - vpix->next_dri2->prevnext_dri2 = &vpix->next_dri2; -} - -void -vmwgfx_remove_dri2_list(struct vmwgfx_saa_pixmap *vpix) -{ - if (vpix->next_dri2) - vpix->next_dri2->prevnext_dri2 = vpix->prevnext_dri2; - - if (vpix->prevnext_dri2) - *vpix->prevnext_dri2 = vpix->next_dri2; - - vpix->next_dri2 = NULL; - vpix->prevnext_dri2 = NULL; -} - - void vmwgfx_flush_dri2(ScreenPtr pScreen) { struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pScreen)); - struct vmwgfx_saa_pixmap *next = vsaa->dri2_flush_list; - struct vmwgfx_saa_pixmap *cur; + struct _WsbmListHead *list, *next; - while(next) { - struct saa_pixmap *spix = &next->base; + WSBMLISTFOREACHSAFE(list, next, &vsaa->sync_x_list) { + struct vmwgfx_saa_pixmap *vpix = + WSBMLISTENTRY(list, struct vmwgfx_saa_pixmap, sync_x_head); + struct saa_pixmap *spix = &vpix->base; PixmapPtr pixmap = spix->pixmap; if (vmwgfx_upload_to_hw(&vsaa->driver, pixmap, &spix->dirty_shadow)) { REGION_EMPTY(vsaa->pScreen, &spix->dirty_shadow); - cur = next; - next = next->next_dri2; - vmwgfx_remove_dri2_list(cur); - } else - next = next->next_dri2; + WSBMLISTDELINIT(list); + } } } @@ -498,7 +472,7 @@ vmwgfx_destroy_pixmap(struct saa_driver *driver, PixmapPtr pixmap) */ vmwgfx_pixmap_remove_present(vpix); - vmwgfx_remove_dri2_list(vpix); + WSBMLISTDELINIT(&vpix->sync_x_head); if (vpix->hw_is_dri2_fronts) LogMessage(X_ERROR, "Incorrect dri2 front count.\n"); @@ -996,8 +970,8 @@ vmwgfx_operation_complete(struct saa_driver *driver, return; REGION_EMPTY(vsaa->pScreen, &spix->dirty_shadow); } else { - if (!vpix->prevnext_dri2) - vmwgfx_add_dri2_list(vsaa, vpix); + if (WSBMLISTEMPTY(&vpix->sync_x_head)) + WSBMLISTADDTAIL(&vpix->sync_x_head, &vsaa->sync_x_list); } } } @@ -1102,6 +1076,7 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, vsaa->drm_fd = drm_fd; vsaa->present_flush = present_flush; vsaa->can_optimize_dma = FALSE; + WSBMINITLISTHEAD(&vsaa->sync_x_list); vsaa->driver = vmwgfx_saa_driver; if (!saa_driver_init(pScreen, &vsaa->driver)) diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h index 1a42cac..c7aae79 100644 --- a/vmwgfx/vmwgfx_saa.h +++ b/vmwgfx/vmwgfx_saa.h @@ -31,6 +31,7 @@ #include "saa.h" #include #include "vmwgfx_drmi.h" +#include "wsbm_util.h" #define VMWGFX_FLAG_FORCE_GMR (1 << 0) /* Create with GMR as backing store */ #define VMWGFX_FLAG_FORCE_SURFACE (1 << 1) /* Create with surface as backing store */ @@ -51,8 +52,7 @@ struct vmwgfx_saa_pixmap { int scanout_refcnt; uint32_t fb_id; int hw_is_dri2_fronts; - struct vmwgfx_saa_pixmap *next_dri2; - struct vmwgfx_saa_pixmap **prevnext_dri2; + struct _WsbmListHead sync_x_head; }; static inline struct vmwgfx_saa_pixmap * diff --git a/vmwgfx/wsbm_util.h b/vmwgfx/wsbm_util.h new file mode 100644 index 0000000..2a2613b --- /dev/null +++ b/vmwgfx/wsbm_util.h @@ -0,0 +1,79 @@ +/* + * This file is not copyrighted. + */ + +#ifndef _WSBM_UTIL_H_ +#define _WSBM_UTIL_H_ + +#include + +#ifndef containerOf +#define containerOf(__item, __type, __field) \ + ((__type *)(((char *) (__item)) - offsetof(__type, __field))) +#endif + +struct _WsbmListHead +{ + struct _WsbmListHead *prev; + struct _WsbmListHead *next; +}; + +#define WSBMINITLISTHEAD(__item) \ + do{ \ + (__item)->prev = (__item); \ + (__item)->next = (__item); \ + } while (0) + +#define WSBMLISTADD(__item, __list) \ + do { \ + (__item)->prev = (__list); \ + (__item)->next = (__list)->next; \ + (__list)->next->prev = (__item); \ + (__list)->next = (__item); \ + } while (0) + +#define WSBMLISTADDTAIL(__item, __list) \ + do { \ + (__item)->next = (__list); \ + (__item)->prev = (__list)->prev; \ + (__list)->prev->next = (__item); \ + (__list)->prev = (__item); \ + } while(0) + +#define WSBMLISTDEL(__item) \ + do { \ + (__item)->prev->next = (__item)->next; \ + (__item)->next->prev = (__item)->prev; \ + } while(0) + +#define WSBMLISTDELINIT(__item) \ + do { \ + (__item)->prev->next = (__item)->next; \ + (__item)->next->prev = (__item)->prev; \ + (__item)->next = (__item); \ + (__item)->prev = (__item); \ + } while(0) + +#define WSBMLISTFOREACH(__item, __list) \ + for((__item) = (__list)->next; (__item) != (__list); (__item) = (__item)->next) + +#define WSBMLISTFOREACHPREV(__item, __list) \ + for((__item) = (__list)->prev; (__item) != (__list); (__item) = (__item)->prev) + +#define WSBMLISTFOREACHSAFE(__item, __next, __list) \ + for((__item) = (__list)->next, (__next) = (__item)->next; \ + (__item) != (__list); \ + (__item) = (__next), (__next) = (__item)->next) + +#define WSBMLISTFOREACHPREVSAFE(__item, __prev, __list) \ + for((__item) = (__list)->prev, (__prev) = (__item->prev); \ + (__item) != (__list); \ + (__item) = (__prev), (__prev) = (__item)->prev) + +#define WSBMLISTENTRY(__item, __type, __field) \ + containerOf(__item, __type, __field) + +#define WSBMLISTEMPTY(__item) \ + ((__item)->next == (__item)) + +#endif -- cgit v1.2.3 From f6a4690832143b01d419b52a4cb74350cdfa38bf Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 20 Jun 2011 09:58:44 +0200 Subject: vmwgfx: Make a list of scanout bounding boxes available to each scanout pixmap This info is needed for present readback. Signed-off-by: Thomas Hellstrom --- vmwgfx/vmwgfx_crtc.c | 46 +++++++++++++++++++++++++--------------------- vmwgfx/vmwgfx_saa.c | 30 +++++++++++++++++++++--------- vmwgfx/vmwgfx_saa.h | 12 +++++++++--- 3 files changed, 55 insertions(+), 33 deletions(-) diff --git a/vmwgfx/vmwgfx_crtc.c b/vmwgfx/vmwgfx_crtc.c index 49e84e8..8f8ced4 100644 --- a/vmwgfx/vmwgfx_crtc.c +++ b/vmwgfx/vmwgfx_crtc.c @@ -58,9 +58,11 @@ struct crtc_private /* hwcursor */ struct vmwgfx_dmabuf *cursor_bo; - PixmapPtr scanout; uint32_t scanout_id; unsigned cursor_handle; + + /* Scanout info for pixmaps */ + struct vmwgfx_screen_box box; }; static void @@ -87,14 +89,8 @@ crtc_dpms(xf86CrtcPtr crtc, int mode) * the crtc may be turned on again by * another dpms call, so don't release the scanout pixmap ref. */ - if (!crtc->enabled && crtcp->scanout) { - PixmapPtr pixmap = crtcp->scanout; - ScreenPtr pScreen = pixmap->drawable.pScreen; - - vmwgfx_scanout_unref(pixmap); - pScreen->DestroyPixmap(pixmap); - crtcp->scanout = NULL; - crtcp->scanout_id = -1; + if (!crtc->enabled && crtcp->box.pixmap) { + vmwgfx_scanout_unref(&crtcp->box); } break; } @@ -138,6 +134,7 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, int i, ret; unsigned int connector_id; PixmapPtr pixmap; + BoxPtr screen_box; for (i = 0; i < config->num_output; output = NULL, i++) { output = config->output[i]; @@ -188,17 +185,13 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, else pixmap = pScreen->GetScreenPixmap(pScreen); - if (crtcp->scanout != pixmap) { - if (crtcp->scanout) { - vmwgfx_scanout_unref(crtcp->scanout); - pScreen->DestroyPixmap(crtcp->scanout); - } - crtcp->scanout_id = vmwgfx_scanout_ref(pixmap); - if (crtcp->scanout_id != -1) { - pixmap->refcnt += 1; - crtcp->scanout = pixmap; - } else { - crtcp->scanout = NULL; + if (crtcp->box.pixmap != pixmap) { + if (crtcp->box.pixmap) + vmwgfx_scanout_unref(&crtcp->box); + + crtcp->box.pixmap = pixmap; + crtcp->scanout_id = vmwgfx_scanout_ref(&crtcp->box); + if (crtcp->scanout_id == -1) { LogMessage(X_ERROR, "Failed to convert pixmap to scanout.\n"); return FALSE; } @@ -208,6 +201,12 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, if (ret) return FALSE; + screen_box = &crtcp->box.box; + screen_box->x1 = crtc->x; + screen_box->y1 = crtc->y; + screen_box->x2 = screen_box->x1 + mode->HDisplay; + screen_box->y2 = screen_box->y1 + mode->VDisplay; + vmwgfx_scanout_refresh(pixmap); /* Only set gamma when needed, to avoid unneeded delays. */ @@ -379,6 +378,9 @@ crtc_destroy(xf86CrtcPtr crtc) { struct crtc_private *crtcp = crtc->driver_private; + if (!WSBMLISTEMPTY(&crtcp->box.scanout_head)) + vmwgfx_scanout_unref(&crtcp->box); + xorg_crtc_cursor_destroy(crtc); drmModeFreeCrtc(crtcp->drm_crtc); @@ -438,6 +440,8 @@ xorg_crtc_init(ScrnInfoPtr pScrn) } crtcp->drm_crtc = drm_crtc; + crtcp->box.pixmap = NULL; + WSBMINITLISTHEAD(&crtcp->box.scanout_head); crtc->driver_private = crtcp; } @@ -450,7 +454,7 @@ PixmapPtr crtc_get_scanout(xf86CrtcPtr crtc) { struct crtc_private *crtcp = crtc->driver_private; - return crtcp->scanout; + return crtcp->box.pixmap; } /* vim: set sw=4 ts=8 sts=4: */ diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index f733328..55b5fea 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -246,7 +246,6 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa, struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); RegionRec intersection; - if (!spix->damage || !REGION_NOTEMPTY(vsaa->pScreen, &spix->dirty_hw) || !vpix->dirty_present) return TRUE; @@ -266,6 +265,7 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa, if (!vmwgfx_pixmap_create_gmr(vsaa, pixmap)) goto out_err; + /* * FIXME: Cliprects may not overlap screen boundaries. */ @@ -431,6 +431,8 @@ vmwgfx_create_pixmap(struct saa_driver *driver, struct saa_pixmap *spix, *new_pitch = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); WSBMINITLISTHEAD(&vpix->sync_x_head); + WSBMINITLISTHEAD(&vpix->scanout_list); + return TRUE; } @@ -1126,14 +1128,15 @@ vmwgfx_scanout_refresh(PixmapPtr pixmap) */ uint32_t -vmwgfx_scanout_ref(PixmapPtr pixmap) +vmwgfx_scanout_ref(struct vmwgfx_screen_box *box) { + PixmapPtr pixmap = box->pixmap; struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); int ret; - if (vpix->scanout_refcnt++ == 0) { + if (WSBMLISTEMPTY(&vpix->scanout_list)) { ret = !vmwgfx_pixmap_create_gmr(vsaa, pixmap); if (!ret) ret = !vmwgfx_pixmap_add_present(pixmap); @@ -1146,14 +1149,17 @@ vmwgfx_scanout_ref(PixmapPtr pixmap) pixmap->devKind, vpix->gmr->handle, &vpix->fb_id); - if (!ret) { -// vmwgfx_scanout_refresh(pixmap); - } if (ret) { + box->pixmap = NULL; vpix->fb_id = -1; - --vpix->scanout_refcnt; + goto out_err; } + } + pixmap->refcnt += 1; + WSBMLISTADDTAIL(&box->scanout_head, &vpix->scanout_list); + + out_err: return vpix->fb_id; } @@ -1163,17 +1169,20 @@ vmwgfx_scanout_ref(PixmapPtr pixmap) * damage tracking and kms fbs. */ void -vmwgfx_scanout_unref(PixmapPtr pixmap) +vmwgfx_scanout_unref(struct vmwgfx_screen_box *box) { struct vmwgfx_saa *vsaa; struct vmwgfx_saa_pixmap *vpix; + PixmapPtr pixmap = box->pixmap; if (!pixmap) return; vsaa = to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); vpix = vmwgfx_saa_pixmap(pixmap); - if (--vpix->scanout_refcnt == 0) { + WSBMLISTDELINIT(&box->scanout_head); + + if (WSBMLISTEMPTY(&vpix->scanout_list)) { REGION_EMPTY(vsaa->pScreen, vpix->pending_update); drmModeRmFB(vsaa->drm_fd, vpix->fb_id); vpix->fb_id = -1; @@ -1181,4 +1190,7 @@ vmwgfx_scanout_unref(PixmapPtr pixmap) vmwgfx_pixmap_remove_present(vpix); vmwgfx_pixmap_remove_damage(pixmap); } + + box->pixmap = NULL; + pixmap->drawable.pScreen->DestroyPixmap(pixmap); } diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h index c7aae79..90fa728 100644 --- a/vmwgfx/vmwgfx_saa.h +++ b/vmwgfx/vmwgfx_saa.h @@ -49,10 +49,16 @@ struct vmwgfx_saa_pixmap { void *malloc; struct vmwgfx_dmabuf *gmr; struct xa_surface *hw; - int scanout_refcnt; uint32_t fb_id; int hw_is_dri2_fronts; struct _WsbmListHead sync_x_head; + struct _WsbmListHead scanout_list; +}; + +struct vmwgfx_screen_box { + BoxRec box; + struct _WsbmListHead scanout_head; + PixmapPtr pixmap; }; static inline struct vmwgfx_saa_pixmap * @@ -77,10 +83,10 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, void (*present_flush)(ScreenPtr pScreen)); extern uint32_t -vmwgfx_scanout_ref(PixmapPtr pixmap); +vmwgfx_scanout_ref(struct vmwgfx_screen_box *box); extern void -vmwgfx_scanout_unref(PixmapPtr pixmap); +vmwgfx_scanout_unref(struct vmwgfx_screen_box *box); extern void vmwgfx_scanout_refresh(PixmapPtr pixmap); -- cgit v1.2.3 From 4d5aec4a7e4512145c76014591488cb5a98ff0ea Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 20 Jun 2011 14:13:46 +0200 Subject: vmwgfx: Make present readbacks not cross scanout bounding box boundaries Signed-off-by: Thomas Hellstrom --- vmwgfx/vmwgfx_saa.c | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 55b5fea..f095b9f 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -245,11 +245,24 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa, struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); RegionRec intersection; + RegionRec screen_intersection; + struct _WsbmListHead *list; if (!spix->damage || !REGION_NOTEMPTY(vsaa->pScreen, &spix->dirty_hw) || !vpix->dirty_present) return TRUE; + /* + * Flush dirty stuff to screen. + */ + + + vsaa->present_flush(vsaa->pScreen); + + /* + * Intersect dirty region with region to be read back, if any. + */ + REGION_NULL(vsaa->pScreen, &intersection); REGION_COPY(vsaa->pScreen, &intersection, &spix->dirty_hw); REGION_INTERSECT(vsaa->pScreen, &intersection, &intersection, @@ -261,24 +274,44 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa, if (!REGION_NOTEMPTY(vsaa->pScreen, &intersection)) goto out; - vsaa->present_flush(vsaa->pScreen); + /* + * Make really sure there is a GMR to read back to. + */ + if (!vmwgfx_pixmap_create_gmr(vsaa, pixmap)) goto out_err; - /* - * FIXME: Cliprects may not overlap screen boundaries. + * Readback regions are not allowed to cross screen boundaries, so + * loop over all scanouts and make sure all readback calls are completely + * contained within a scanout bounding box. */ - if (vmwgfx_present_readback(vsaa->drm_fd, &intersection) != 0) - goto out_err; + REGION_NULL(vsaa->pScreen, &screen_intersection); + WSBMLISTFOREACH(list, &vpix->scanout_list) { + struct vmwgfx_screen_box *box = + WSBMLISTENTRY(list, struct vmwgfx_screen_box, scanout_head); + + REGION_RESET(vsaa->pScreen, &screen_intersection, &box->box); + REGION_INTERSECT(vsaa->pScreen, &screen_intersection, + &screen_intersection, &intersection); + + if (vmwgfx_present_readback(vsaa->drm_fd, &intersection) != 0) + goto out_readback_err; + + REGION_SUBTRACT(vsaa->pScreen, &intersection, &intersection, + &screen_intersection); + REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_hw, + &spix->dirty_hw, &screen_intersection); + } - REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_hw, - &spix->dirty_hw, &intersection); + REGION_UNINIT(vsaa->pScreen, &screen_intersection); out: REGION_UNINIT(vsaa->pScreen, &intersection); return TRUE; + out_readback_err: + REGION_UNINIT(vsaa->pScreen, &screen_intersection); out_err: REGION_UNINIT(vsaa->pScreen, &intersection); return FALSE; -- cgit v1.2.3 From f71928d3f78d9f9e5a0fd240069b9035d4ccac75 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 20 Jun 2011 21:48:23 +0200 Subject: vmwgfx: Don't call xa_copy_done after a present. Signed-off-by: Thomas Hellstrom --- vmwgfx/vmwgfx_saa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index f095b9f..83b1698 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -974,6 +974,7 @@ vmwgfx_copy_done(struct saa_driver *driver) if (vsaa->present_copy) { vmwgfx_present_done(vsaa); + return; } xa_copy_done(vsaa->xa_ctx); } -- cgit v1.2.3 From 63d7ddb35fe8b6743de182b73e6967f97f6a7eba Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 20 Jun 2011 21:57:38 +0200 Subject: vmwgfx: Fix dirty present bug Clear dirty present areas when new contents are drawn to the backing pixmap. Not when it is actually pushed to the screen. Signed-off-by: Thomas Hellstrom --- vmwgfx/vmwgfx_driver.c | 4 ---- vmwgfx/vmwgfx_saa.c | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index 048534e..17d93eb 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -573,15 +573,11 @@ void xorg_flush(ScreenPtr pScreen) if (vpix->pending_update) { (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id, vpix->pending_update); - REGION_SUBTRACT(pScreen, vpix->dirty_present, - vpix->dirty_present, vpix->pending_update); REGION_EMPTY(pScreen, vpix->pending_update); } if (vpix->pending_present) { (void) vmwgfx_scanout_present(pScreen, ms->fd, vpix, vpix->pending_present); - REGION_SUBTRACT(pScreen, vpix->dirty_present, - vpix->dirty_present, vpix->pending_present); REGION_EMPTY(pScreen, vpix->pending_present); } } diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 83b1698..ad7f8b1 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -1054,6 +1054,8 @@ vmwgfx_dirty(struct saa_driver *driver, PixmapPtr pixmap, } REGION_UNION(vsaa->pScreen, vpix->pending_present, vpix->pending_present, damage); + REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present, + vpix->dirty_present, damage); } } else { if (REGION_NOTEMPTY(vsaa->pScreen, vpix->pending_present)) { @@ -1068,6 +1070,8 @@ vmwgfx_dirty(struct saa_driver *driver, PixmapPtr pixmap, } REGION_UNION(vsaa->pScreen, vpix->pending_update, vpix->pending_update, damage); + REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present, + vpix->dirty_present, damage); } return TRUE; -- cgit v1.2.3 From 3650be74d5da602653b2b1d3cf3a6bb5a9cb3539 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 21 Jun 2011 00:13:32 +0200 Subject: vmwgfx: Try to match created hardware formats with the dri state tracker. --- configure.ac | 2 +- vmwgfx/vmwgfx_dri2.c | 64 +++++++++++++++++++++++++++++++++++++---------- vmwgfx/vmwgfx_saa.c | 53 ++++++++++++++++++++++++++++++++------- vmwgfx/vmwgfx_saa.h | 1 + vmwgfx/vmwgfx_tex_video.c | 2 +- 5 files changed, 98 insertions(+), 24 deletions(-) diff --git a/configure.ac b/configure.ac index 1f060ae..da140bf 100644 --- a/configure.ac +++ b/configure.ac @@ -115,7 +115,7 @@ AM_CONDITIONAL(XSERVER_LIBPCIACCESS, test "x$XSERVER_LIBPCIACCESS" = xyes) AC_SUBST([moduledir]) if test x$BUILD_VMWGFX = xyes; then - PKG_CHECK_MODULES([XATRACKER], [xatracker >= 0.1.0],[],[BUILD_VMWGFX=no]) + PKG_CHECK_MODULES([XATRACKER], [xatracker >= 0.2.0],[],[BUILD_VMWGFX=no]) fi DRIVER_NAME=vmware diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index 1529cdb..07d538f 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -50,6 +50,32 @@ typedef struct { struct xa_surface *srf; } *BufferPrivatePtr; + +/* + * Attempt to guess what the dri state tracker is up to. + * Currently it sends only bpp as format. + */ + +static unsigned int +vmwgfx_color_format_to_depth(unsigned int format) +{ + return format; +} + +static unsigned int +vmwgfx_zs_format_to_depth(unsigned int format) +{ + if (format == 24) + return 32; + return format; +} + +static unsigned int +vmwgfx_z_format_to_depth(unsigned int format) +{ + return format; +} + static Bool dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int format) { @@ -60,7 +86,8 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for PixmapPtr pPixmap; struct vmwgfx_saa_pixmap *vpix; struct xa_surface *srf = NULL; - unsigned int cpp = 4; + unsigned int depth; + if (pDraw->type == DRAWABLE_PIXMAP) pPixmap = (PixmapPtr) pDraw; @@ -72,13 +99,16 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for switch (buffer->attachment) { default: + depth = (format) ? vmwgfx_color_format_to_depth(format) : + pDraw->depth; + if (buffer->attachment != DRI2BufferFakeFrontLeft || &pPixmap->drawable != pDraw) { pPixmap = (*pScreen->CreatePixmap)(pScreen, pDraw->width, pDraw->height, - pDraw->depth, + depth, 0); if (pPixmap == NullPixmap) return FALSE; @@ -92,10 +122,10 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for break; buffer->name = 0; buffer->pitch = 0; - buffer->cpp = cpp; + buffer->cpp = pDraw->bitsPerPixel / 8; buffer->driverPrivate = private; buffer->flags = 0; /* not tiled */ - buffer->format = 0; + buffer->format = pDraw->bitsPerPixel; if (!private->pPixmap) { private->pPixmap = pPixmap; pPixmap->refcnt++; @@ -103,20 +133,25 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for return TRUE; case DRI2BufferStencil: case DRI2BufferDepthStencil: + + depth = (format) ? vmwgfx_zs_format_to_depth(format) : 32; + + /* + * The SVGA device uses the zs ordering. + */ + srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height, - 32, xa_type_zs, xa_format_unknown, + depth, xa_type_zs, xa_format_unknown, XA_FLAG_SHARED ); - if (!srf) - srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height, - 32, xa_type_sz, xa_format_unknown, - XA_FLAG_SHARED ); if (!srf) return FALSE; - break; + break; case DRI2BufferDepth: + depth = (format) ? vmwgfx_z_format_to_depth(format) : + pDraw->bitsPerPixel; srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height, - (format) ? format: pDraw->depth, + depth, xa_type_z, xa_format_unknown, XA_FLAG_SHARED); if (!srf) @@ -130,7 +165,9 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for } if (!srf) { - if (!vmwgfx_pixmap_validate_hw(pPixmap, NULL, + depth = (format) ? vmwgfx_color_format_to_depth(format) : + pDraw->depth; + if (!vmwgfx_pixmap_validate_hw(pPixmap, NULL, depth, XA_FLAG_SHARED | XA_FLAG_RENDER_TARGET, 0)) return FALSE; @@ -149,7 +186,7 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for if (xa_surface_handle(srf, &buffer->name, &buffer->pitch) != 0) return FALSE; - buffer->cpp = cpp; + buffer->cpp = xa_format_depth(xa_surface_format(srf)) / 8; buffer->driverPrivate = private; buffer->flags = 0; /* not tiled */ buffer->format = format; @@ -273,6 +310,7 @@ dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, pDestBuffer->attachment == DRI2BufferFakeFrontLeft) { LogMessage(X_INFO, "dri2 Validate hw.\n"); vmwgfx_pixmap_validate_hw(src_priv->pPixmap, NULL, + 0, XA_FLAG_SHARED | XA_FLAG_RENDER_TARGET, 0); return; diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index ad7f8b1..297e1f3 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -63,6 +63,30 @@ to_vmwgfx_saa(struct saa_driver *driver) { return (struct vmwgfx_saa *) driver; } +static enum xa_formats +vmwgfx_choose_xa_format(unsigned int depth) +{ + /* + * For a given depth, choose the same format as the + * dri state tracker. + */ + + switch(depth) { + case 32: + case 24: /* The dri state tracker never uses 24. */ + return xa_format_a8r8g8b8; + case 16: + return xa_format_r5g6b5; + case 15: /* No dri. */ + return xa_format_x1r5g5b5; + default: + break; + } + + return xa_format_unknown; +} + + static Bool vmwgfx_pixmap_add_damage(PixmapPtr pixmap) { @@ -515,7 +539,8 @@ vmwgfx_destroy_pixmap(struct saa_driver *driver, PixmapPtr pixmap) static Bool vmwgfx_pixmap_create_hw(struct vmwgfx_saa *vsaa, - PixmapPtr pixmap, unsigned int flags) + PixmapPtr pixmap, unsigned int depth, + unsigned int flags) { struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); struct xa_surface *hw; @@ -526,11 +551,15 @@ vmwgfx_pixmap_create_hw(struct vmwgfx_saa *vsaa, if (vpix->hw) return TRUE; + if (!depth) + depth = pixmap->drawable.depth; + hw = xa_surface_create(vsaa->xat, pixmap->drawable.width, pixmap->drawable.height, - pixmap->drawable.depth, - xa_type_argb, xa_format_unknown, + depth, + xa_type_argb, + vmwgfx_choose_xa_format(depth), XA_FLAG_RENDER_TARGET | flags); if (hw == NULL) return FALSE; @@ -562,6 +591,7 @@ out_no_damage: Bool vmwgfx_pixmap_validate_hw(PixmapPtr pixmap, RegionPtr region, + unsigned int depth, unsigned int add_flags, unsigned int remove_flags) { @@ -575,15 +605,19 @@ vmwgfx_pixmap_validate_hw(PixmapPtr pixmap, RegionPtr region, return FALSE; if (vpix->hw) { + if (!depth) + depth = pixmap->drawable.depth; + if (xa_surface_redefine(vpix->hw, pixmap->drawable.width, pixmap->drawable.height, - pixmap->drawable.depth, - xa_type_argb, xa_format_unknown, + depth, + xa_type_argb, + vmwgfx_choose_xa_format(depth), XA_FLAG_RENDER_TARGET | add_flags, remove_flags, 1) != 0) return FALSE; - } else if (!vmwgfx_pixmap_create_hw(vsaa, pixmap, add_flags)) + } else if (!vmwgfx_pixmap_create_hw(vsaa, pixmap, depth, add_flags)) return FALSE; @@ -864,7 +898,7 @@ vmwgfx_copy_prepare(struct saa_driver *driver, return FALSE; if (vmwgfx_present_prepare(vsaa, src_vpix, dst_vpix)) { - if (!vmwgfx_pixmap_validate_hw(src_pixmap, src_reg, 0, 0)) + if (!vmwgfx_pixmap_validate_hw(src_pixmap, src_reg, 0, 0, 0)) return FALSE; vsaa->present_copy = TRUE; return TRUE; @@ -883,9 +917,10 @@ vmwgfx_copy_prepare(struct saa_driver *driver, if (!has_dirty_hw && !(has_valid_hw && (dst_vpix->hw != NULL))) return FALSE; - if (!vmwgfx_pixmap_validate_hw(src_pixmap, src_reg, 0, 0)) + if (!vmwgfx_pixmap_validate_hw(src_pixmap, src_reg, 0, 0, 0)) return FALSE; - if (!vmwgfx_pixmap_create_hw(vsaa, dst_pixmap, XA_FLAG_RENDER_TARGET)) + if (!vmwgfx_pixmap_create_hw(vsaa, dst_pixmap, 0, + XA_FLAG_RENDER_TARGET)) return FALSE; if (xa_copy_prepare(vsaa->xa_ctx, dst_vpix->hw, src_vpix->hw) == 0) diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h index 90fa728..29863c5 100644 --- a/vmwgfx/vmwgfx_saa.h +++ b/vmwgfx/vmwgfx_saa.h @@ -69,6 +69,7 @@ to_vmwgfx_saa_pixmap(struct saa_pixmap *spix) extern Bool vmwgfx_pixmap_validate_hw(PixmapPtr pixmap, RegionPtr region, + unsigned int depth, unsigned int add_flags, unsigned int remove_flags); diff --git a/vmwgfx/vmwgfx_tex_video.c b/vmwgfx/vmwgfx_tex_video.c index fb8f41e..c357f06 100644 --- a/vmwgfx/vmwgfx_tex_video.c +++ b/vmwgfx/vmwgfx_tex_video.c @@ -455,7 +455,7 @@ display_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id, REGION_NULL(pScreen, ®); - if (!vmwgfx_pixmap_validate_hw(pPixmap, ®, XA_FLAG_RENDER_TARGET, 0)) + if (!vmwgfx_pixmap_validate_hw(pPixmap, ®, 0, XA_FLAG_RENDER_TARGET, 0)) goto out_no_dst; hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y)); -- cgit v1.2.3 From b2e116971031d1357f614e9ce1d843768489a304 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 22 Jun 2011 10:50:35 +0200 Subject: saa: Reuse code for computing composite bounds. Signed-off-by: Thomas Hellstrom --- saa/saa_priv.h | 21 +++++++- saa/saa_render.c | 54 ++++++++++++++------ saa/saa_unaccel.c | 149 +++++++++++++++++++++++++++++++++--------------------- 3 files changed, 148 insertions(+), 76 deletions(-) diff --git a/saa/saa_priv.h b/saa/saa_priv.h index c961345..5d449fd 100644 --- a/saa/saa_priv.h +++ b/saa/saa_priv.h @@ -99,7 +99,7 @@ struct saa_screen_priv { RegionRec srcReg; RegionRec maskReg; - PixmapPtr srcPix; + DrawablePtr srcDraw; }; extern GCOps saa_gc_ops; @@ -228,6 +228,7 @@ saa_render_setup(ScreenPtr pScreen); extern void saa_render_takedown(ScreenPtr pScreen); + extern void saa_check_composite(CARD8 op, PicturePtr pSrc, @@ -237,7 +238,10 @@ saa_check_composite(CARD8 op, INT16 ySrc, INT16 xMask, INT16 yMask, - INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height, + RegionPtr src_region, + RegionPtr mask_region, + RegionPtr dst_region); #endif extern Bool @@ -260,4 +264,17 @@ saa_pix_damage_pending(struct saa_pixmap *spix) extern RegionPtr saa_boxes_to_region(ScreenPtr pScreen, int nbox, BoxPtr pbox, int ordering); + +Bool +saa_compute_composite_regions(ScreenPtr pScreen, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, INT16 ySrc, INT16 xMask, + INT16 yMask, INT16 xDst, + INT16 yDst, INT16 width, INT16 height, + RegionPtr dst_reg, + RegionPtr *src_reg, + RegionPtr *mask_reg); + #endif diff --git a/saa/saa_render.c b/saa/saa_render.c index 8c6e1e6..bec44bf 100644 --- a/saa/saa_render.c +++ b/saa/saa_render.c @@ -221,7 +221,8 @@ saa_copy_composite(CARD8 op, INT16 ySrc, INT16 xMask, INT16 yMask, - INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height, + RegionPtr dst_region) { if (!pSrc->pDrawable || pSrc->transform || pSrc->repeat || xSrc < 0 || ySrc < 0 || @@ -241,28 +242,27 @@ saa_copy_composite(CARD8 op, PICT_FORMAT_B(pSrc->format))))) || (op == PictOpOver && pSrc->format == pDst->format && !PICT_FORMAT_A(pSrc->format))) { - Bool ret; - RegionRec region; + int xoff, yoff; - REGION_NULL(pDst->pDrawable.pScreen, ®ion); + saa_get_pixmap(pDst->pDrawable, &xoff, &yoff); xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; xSrc += pSrc->pDrawable->x; ySrc += pSrc->pDrawable->y; - if (!miComputeCompositeRegion(®ion, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, xDst, - yDst, width, height)) { - return TRUE; - } + /* + * Dst region is in backing pixmap space. We need to + * translate it. + */ + REGION_TRANSLATE(pScreen, dst_region, -xoff, -yoff); ret = saa_hw_copy_nton(pSrc->pDrawable, pDst->pDrawable, NULL, - REGION_RECTS(®ion), - REGION_NUM_RECTS(®ion), + REGION_RECTS(dst_region), + REGION_NUM_RECTS(dst_region), xSrc - xDst, ySrc - yDst, FALSE, FALSE); - REGION_UNINIT(pDst->pDrwable.pScreen, ®ion); + REGION_TRANSLATE(pScreen, dst_region, xoff, yoff); if (ret) return TRUE; } @@ -279,10 +279,32 @@ saa_composite(CARD8 op, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { - if (!saa_copy_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, - xDst, yDst, width, height)) - saa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, - xDst, yDst, width, height); + ScreenPtr pScreen = pDst->pDrawable->pScreen; + RegionRec dst_region; + RegionPtr src_region; + RegionPtr mask_region; + + REGION_NULL(pScreen, &dst_region); + if (!saa_compute_composite_regions(pScreen, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, + yDst, width, height, + &dst_region, &src_region, &mask_region)) + goto out; + + if (saa_copy_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height, &dst_region)) + goto out; + + + saa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height, + src_region, mask_region, &dst_region); + out: + if (src_region) + REGION_UNINIT(pScreen, src_region); + if (mask_region) + REGION_UNINIT(pScreen, mask_region); + REGION_UNINIT(pScreen, &dst_region); } void diff --git a/saa/saa_unaccel.c b/saa/saa_unaccel.c index 27b399d..8c1d89b 100644 --- a/saa/saa_unaccel.c +++ b/saa/saa_unaccel.c @@ -533,20 +533,19 @@ saa_src_validate(DrawablePtr pDrawable, int x, int y, int width, int height) { ScreenPtr pScreen = pDrawable->pScreen; struct saa_screen_priv *sscreen = saa_screen(pScreen); - PixmapPtr pPix = saa_get_drawable_pixmap(pDrawable); + int xoff, yoff; BoxRec box; RegionRec reg; RegionPtr dst; - int xoff, yoff; - - saa_get_drawable_deltas(pDrawable, pPix, &xoff, &yoff); + (void) saa_get_pixmap(pDrawable, &xoff, &yoff); box.x1 = x + xoff; box.y1 = y + yoff; box.x2 = box.x1 + width; box.y2 = box.y1 + height; - dst = (sscreen->srcPix == pPix) ? &sscreen->srcReg : &sscreen->maskReg; + dst = (sscreen->srcDraw == pDrawable) ? + &sscreen->srcReg : &sscreen->maskReg; REGION_INIT(pScreen, ®, &box, 1); REGION_UNION(pScreen, dst, dst, ®); @@ -604,46 +603,45 @@ saa_check_get_spans(DrawablePtr pDrawable, sscreen->fallback_count--; } -static Bool -saa_prepare_composite_reg(ScreenPtr pScreen, - CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height, - RegionPtr region, saa_access_t * access) +/* + * Compute composite regions taking transforms into account. + * The caller must provide a pointer to an initialized dst_reg, + * and the function returns pointers to set up source- and mask regions. + * The source and mask regions must be uninitialized after use. + */ + +Bool +saa_compute_composite_regions(ScreenPtr pScreen, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, INT16 ySrc, INT16 xMask, + INT16 yMask, INT16 xDst, + INT16 yDst, INT16 width, INT16 height, + RegionPtr dst_reg, + RegionPtr *src_reg, + RegionPtr *mask_reg) { - RegionPtr dstReg = NULL; + struct saa_screen_priv *sscreen = saa_screen(pScreen); + PixmapPtr dst_pixmap; RegionPtr srcReg = NULL; RegionPtr maskReg = NULL; - PixmapPtr pSrcPix = NULL; - PixmapPtr pMaskPix = NULL; - PixmapPtr pDstPix; - struct saa_screen_priv *sscreen = saa_screen(pScreen); - struct saa_pixmap *dst_spix; Bool ret; + int xoff, yoff; - *access = SAA_ACCESS_W; + *src_reg = NULL; + *mask_reg = NULL; if (pSrc->pDrawable) { - pSrcPix = saa_get_drawable_pixmap(pSrc->pDrawable); REGION_NULL(pScreen, &sscreen->srcReg); srcReg = &sscreen->srcReg; - sscreen->srcPix = pSrcPix; + sscreen->srcDraw = pSrc->pDrawable; if (pSrc != pDst) REGION_TRANSLATE(pScreen, pSrc->pCompositeClip, -pSrc->pDrawable->x, -pSrc->pDrawable->y); } if (pMask && pMask->pDrawable) { - pMaskPix = saa_get_drawable_pixmap(pMask->pDrawable); REGION_NULL(pScreen, &sscreen->maskReg); maskReg = &sscreen->maskReg; if (pMask != pDst && pMask != pSrc) @@ -656,7 +654,7 @@ saa_prepare_composite_reg(ScreenPtr pScreen, sscreen->saved_SourceValidate = saa_src_validate; saa_swap(sscreen, pScreen, SourceValidate); - ret = miComputeCompositeRegion(region, pSrc, pMask, pDst, + ret = miComputeCompositeRegion(dst_reg, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); saa_swap(sscreen, pScreen, SourceValidate); @@ -679,6 +677,52 @@ saa_prepare_composite_reg(ScreenPtr pScreen, return FALSE; } + *src_reg = srcReg; + *mask_reg = maskReg; + + /* + * Translate dst region to pixmap space. + */ + dst_pixmap = saa_get_pixmap(pDst->pDrawable, &xoff, &yoff); + REGION_TRANSLATE(pScreen, dst_reg, pDst->pDrawable->x + xoff, + pDst->pDrawable->y + yoff); + + + return TRUE; +} + +static Bool +saa_prepare_composite_reg(ScreenPtr pScreen, + CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height, + RegionPtr src_region, + RegionPtr mask_region, + RegionPtr dst_region, + saa_access_t * access) +{ + RegionPtr dstReg = NULL; + PixmapPtr pSrcPix = NULL; + PixmapPtr pMaskPix = NULL; + PixmapPtr pDstPix; + struct saa_pixmap *dst_spix; + + *access = SAA_ACCESS_W; + + if (pSrc->pDrawable) + pSrcPix = saa_get_drawable_pixmap(pSrc->pDrawable); + if (pMask && pMask->pDrawable) + pMaskPix = saa_get_drawable_pixmap(pMask->pDrawable); + /* * Don't limit alphamaps readbacks for now until we've figured out how that * should be done. @@ -691,29 +735,18 @@ saa_prepare_composite_reg(ScreenPtr pScreen, if (!saa_pad_read(pMask->alphaMap->pDrawable)) goto out_no_mask_alpha; if (pSrcPix) - if (!saa_prepare_access_pixmap(pSrcPix, SAA_ACCESS_R, srcReg)) + if (!saa_prepare_access_pixmap(pSrcPix, SAA_ACCESS_R, src_region)) goto out_no_src; if (pMaskPix) - if (!saa_prepare_access_pixmap(pMaskPix, SAA_ACCESS_R, maskReg)) + if (!saa_prepare_access_pixmap(pMaskPix, SAA_ACCESS_R, mask_region)) goto out_no_mask; - if (srcReg) - REGION_UNINIT(pScreen, srcReg); - if (maskReg) - REGION_UNINIT(pScreen, maskReg); pDstPix = saa_get_drawable_pixmap(pDst->pDrawable); dst_spix = saa_get_saa_pixmap(pDstPix); - if (dst_spix->damage) { - int xoff, yoff; - - saa_get_drawable_deltas(pDst->pDrawable, pDstPix, &xoff, &yoff); - REGION_TRANSLATE(pScreen, region, pDst->pDrawable->x + xoff, - pDst->pDrawable->y + yoff); - if (saa_op_reads_destination(op)) { - dstReg = region; - *access |= SAA_ACCESS_R; - } + if (dst_spix->damage && saa_op_reads_destination(op)) { + dstReg = dst_region; + *access |= SAA_ACCESS_R; } if (pDst->alphaMap && pDst->alphaMap->pDrawable) @@ -749,10 +782,6 @@ saa_prepare_composite_reg(ScreenPtr pScreen, saa_fad_read(pSrc->alphaMap->pDrawable); out_no_src_alpha: LogMessage(X_ERROR, "No src alpha\n"); - if (srcReg) - REGION_UNINIT(pScreen, srcReg); - if (maskReg) - REGION_UNINIT(pScreen, maskReg); return FALSE; } @@ -766,20 +795,25 @@ saa_check_composite(CARD8 op, INT16 ySrc, INT16 xMask, INT16 yMask, - INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height, + RegionPtr src_region, + RegionPtr mask_region, + RegionPtr dst_region) { ScreenPtr pScreen = pDst->pDrawable->pScreen; PictureScreenPtr ps = GetPictureScreen(pScreen); struct saa_screen_priv *sscreen = saa_screen(pScreen); saa_access_t access; - RegionRec reg; PixmapPtr pixmap; sscreen->fallback_count++; - REGION_NULL(pScreen, ®); if (!saa_prepare_composite_reg(pScreen, op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, - height, ®, &access)) { + height, + src_region, + mask_region, + dst_region, + &access)) { goto out_no_access;; } @@ -795,11 +829,11 @@ saa_check_composite(CARD8 op, saa_fad_read(pSrc->pDrawable); pixmap = saa_get_drawable_pixmap(pDst->pDrawable); saa_finish_access_pixmap(pixmap, access); - saa_pixmap_dirty(pixmap, FALSE, ®); + saa_pixmap_dirty(pixmap, FALSE, dst_region); if (pDst->alphaMap && pDst->alphaMap->pDrawable) { pixmap = saa_get_drawable_pixmap(pDst->alphaMap->pDrawable); saa_finish_access_pixmap(pixmap, access); - saa_pixmap_dirty(pixmap, FALSE, ®); + saa_pixmap_dirty(pixmap, FALSE, dst_region); } if (pSrc->alphaMap && pSrc->alphaMap->pDrawable) saa_fad_read(pSrc->alphaMap->pDrawable); @@ -807,7 +841,6 @@ saa_check_composite(CARD8 op, saa_fad_read(pMask->alphaMap->pDrawable); out_no_access: sscreen->fallback_count--; - REGION_UNINIT(pScreen, ®); } static void -- cgit v1.2.3 From c7e8388280fc047b33be4f603afa4b7615ffc585 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 22 Jun 2011 11:33:14 +0200 Subject: saa: Add driver composite. Signed-off-by: Thomas Hellstrom --- saa/saa.h | 23 +++++++++++++--- saa/saa_render.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 5 deletions(-) diff --git a/saa/saa.h b/saa/saa.h index fe9617f..3101353 100644 --- a/saa/saa.h +++ b/saa/saa.h @@ -42,6 +42,7 @@ #endif #include #include +#include #define SAA_VERSION_MAJOR 0 #define SAA_VERSION_MINOR 1 @@ -97,15 +98,29 @@ struct saa_driver { int w, int h, int depth, unsigned int usage_hint, int bpp, int *new_pitch); void (*destroy_pixmap) (struct saa_driver * driver, PixmapPtr pixmap); - Bool(*modify_pixmap_header) (PixmapPtr pixmap, int w, int h, int depth, + Bool (*modify_pixmap_header) (PixmapPtr pixmap, int w, int h, int depth, int bpp, int devkind, void *pPixData); - Bool(*copy_prepare) (struct saa_driver * driver, PixmapPtr src_pixmap, - PixmapPtr dst_pixmap, int dx, int dy, int alu, - RegionPtr scr_reg, uint32_t plane_mask); + Bool (*copy_prepare) (struct saa_driver * driver, PixmapPtr src_pixmap, + PixmapPtr dst_pixmap, int dx, int dy, int alu, + RegionPtr scr_reg, uint32_t plane_mask); void (*copy) (struct saa_driver * driver, int src_x, int src_y, int dst_x, int dst_y, int w, int h); void (*copy_done) (struct saa_driver * driver); + Bool (*composite_prepare) (struct saa_driver *driver, CARD8 op, + PicturePtr src_pict, PicturePtr mask_pict, + PicturePtr dst_pict, + PixmapPtr src_pix, PixmapPtr mask_pix, + PixmapPtr dst_pix, + RegionPtr src_region, + RegionPtr mask_region, + RegionPtr dst_region); + void (*composite) (struct saa_driver *driver, + int src_x, int src_y, int mask_x, int mask_y, + int dst_x, int dst_y, + int width, int height); + void (*composite_done) (struct saa_driver *driver); + void (*takedown) (struct saa_driver * driver); uint32_t pad[16]; }; diff --git a/saa/saa_render.c b/saa/saa_render.c index bec44bf..6bd58f7 100644 --- a/saa/saa_render.c +++ b/saa/saa_render.c @@ -207,6 +207,80 @@ saa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, } } +static Bool +saa_driver_composite(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height, + RegionPtr src_reg, + RegionPtr mask_reg, + RegionPtr dst_reg) +{ + struct saa_screen_priv *sscreen = saa_screen(pDst->pDrawable->pScreen); + BoxPtr pbox; + int nbox; + int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; + PixmapPtr src_pix = NULL, mask_pix = NULL, dst_pix; + struct saa_driver *driver = sscreen->driver; + + if (!driver->composite_prepare) + return FALSE; + + dst_pix = saa_get_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); + if (pMask && pMask->pDrawable) { + mask_pix = saa_get_pixmap(pMask->pDrawable, &mask_off_x, &mask_off_y); + } + if (pSrc->pDrawable) { + src_pix = saa_get_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y); + } + + if (!driver->composite_prepare(driver, op, pSrc, pMask, pDst, + src_pix, mask_pix, dst_pix, + src_reg, mask_reg, dst_reg)) + return FALSE; + + nbox = REGION_NUM_RECTS(dst_reg); + pbox = REGION_RECTS(dst_reg); + + xDst += pDst->pDrawable->x + dst_off_x; + yDst += pDst->pDrawable->y + dst_off_y; + + if (src_pix) { + xSrc += pSrc->pDrawable->x + src_off_x - xDst; + ySrc += pSrc->pDrawable->y + src_off_y - yDst; + } + if (mask_pix) { + xMask += pMask->pDrawable->x + mask_off_x - xDst; + yMask += pMask->pDrawable->y + mask_off_y - yDst; + } + + while (nbox--) { + driver->composite(driver, + pbox->x1 + xSrc, + pbox->y1 + ySrc, + pbox->x1 + xMask, + pbox->y1 + yMask, + pbox->x1, + pbox->y1, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + pbox++; + } + + driver->composite_done(driver); + saa_pixmap_dirty(dst_pix, TRUE, dst_reg); + + return TRUE; +} + /* * Try to turn a composite operation into an accelerated copy. * We can do that in some special cases for PictOpSrc and PictOpOver. @@ -295,6 +369,10 @@ saa_composite(CARD8 op, xDst, yDst, width, height, &dst_region)) goto out; + if (saa_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height, src_region, + mask_region, &dst_region)) + goto out; saa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height, @@ -302,7 +380,7 @@ saa_composite(CARD8 op, out: if (src_region) REGION_UNINIT(pScreen, src_region); - if (mask_region) + if (mask_region && mask_region != src_region) REGION_UNINIT(pScreen, mask_region); REGION_UNINIT(pScreen, &dst_region); } -- cgit v1.2.3 From 8a21da8eaa77bb1ec55ab8b5584554ae6cc41e1e Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 22 Jun 2011 22:26:20 +0200 Subject: vmwgfx: Support xa composite. Signed-off-by: Thomas Hellstrom --- vmwgfx/Makefile.am | 1 + vmwgfx/vmwgfx_saa.c | 147 +++++++++++++++++++++-- vmwgfx/vmwgfx_saa.h | 27 ++++- vmwgfx/vmwgfx_xa_composite.c | 277 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 443 insertions(+), 9 deletions(-) create mode 100644 vmwgfx/vmwgfx_xa_composite.c diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am index 3c31543..03dbf6a 100644 --- a/vmwgfx/Makefile.am +++ b/vmwgfx/Makefile.am @@ -20,6 +20,7 @@ vmwgfx_drv_la_SOURCES = \ vmwgfx_overlay.c \ vmwgfx_ctrl.c \ vmwgfx_ctrl.h \ + vmwgfx_xa_composite.c \ wsbm_util.h diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 297e1f3..48c327d 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -33,7 +33,6 @@ #include "vmwgfx_saa.h" #include "vmwgfx_drmi.h" - #define VMWGFX_PIX_MALLOC (1 << 0) #define VMWGFX_PIX_GMR (1 << 1) #define VMWGFX_PIX_SURFACE (1 << 2) @@ -56,6 +55,7 @@ struct vmwgfx_saa { Bool can_optimize_dma; void (*present_flush) (ScreenPtr pScreen); struct _WsbmListHead sync_x_list; + struct vmwgfx_composite *vcomp; }; static inline struct vmwgfx_saa * @@ -276,13 +276,6 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa, !vpix->dirty_present) return TRUE; - /* - * Flush dirty stuff to screen. - */ - - - vsaa->present_flush(vsaa->pScreen); - /* * Intersect dirty region with region to be read back, if any. */ @@ -1014,11 +1007,141 @@ vmwgfx_copy_done(struct saa_driver *driver) xa_copy_done(vsaa->xa_ctx); } +static Bool +vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op, + PicturePtr src_pict, PicturePtr mask_pict, + PicturePtr dst_pict, + PixmapPtr src_pix, PixmapPtr mask_pix, + PixmapPtr dst_pix, + RegionPtr src_region, + RegionPtr mask_region, + RegionPtr dst_region) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + struct vmwgfx_saa_pixmap *src_vpix; + struct vmwgfx_saa_pixmap *dst_vpix; + struct vmwgfx_saa_pixmap *mask_vpix; + Bool tmp_valid_hw; + Bool dirty_hw; + Bool valid_hw; + RegionRec empty; + struct xa_composite *xa_comp; + + REGION_NULL(pScreen, &empty); + + /* + * First we define our migration policy. We accelerate only if there + * is dirty hw regions to be read or if all source data is + * available in hw, and the destination has a hardware surface. + */ + + dst_vpix = vmwgfx_saa_pixmap(dst_pix); + valid_hw = (dst_vpix->hw != NULL); + if (saa_op_reads_destination(op)) { + vmwgfx_check_hw_contents(vsaa, dst_vpix, dst_region, + &dirty_hw, &tmp_valid_hw); + valid_hw = (valid_hw && tmp_valid_hw); + } else { + dirty_hw = FALSE; + dst_region = ∅ + } + + if (src_pix && !dirty_hw) { + src_vpix = vmwgfx_saa_pixmap(src_pix); + vmwgfx_check_hw_contents(vsaa, src_vpix, src_region, + &dirty_hw, &tmp_valid_hw); + valid_hw = (valid_hw && tmp_valid_hw); + } + + if (mask_pict && mask_pix && !dirty_hw) { + mask_vpix = vmwgfx_saa_pixmap(mask_pix); + vmwgfx_check_hw_contents(vsaa, mask_vpix, mask_region, + &dirty_hw, &tmp_valid_hw); + valid_hw = (valid_hw && tmp_valid_hw); + } + + if (!valid_hw && !dirty_hw) + goto out_err; + + /* + * Then, setup most of the XA composite state (except hardware surfaces) + * and check whether XA can accelerate. + */ + + xa_comp = vmwgfx_xa_setup_comp(vsaa->vcomp, op, + src_pict, mask_pict, dst_pict); + if (!xa_comp) + goto out_err; + + if (xa_composite_check_accelerated(xa_comp) != XA_ERR_NONE) + goto out_err; + + /* + * Create hw surfaces and migrate data needed for HW compositing. + */ + + if (src_region == NULL) + src_region = ∅ + if (src_pix && + !vmwgfx_pixmap_validate_hw(src_pix, src_region, 0, 0, 0)) + goto out_err; + + if (mask_region == NULL) + mask_region = ∅ + if (mask_pict && mask_pix && + !vmwgfx_pixmap_validate_hw(mask_pix, mask_region, 0, 0, 0)) + goto out_err; + + if (dst_region == NULL) + dst_region = ∅ + if (!vmwgfx_pixmap_validate_hw(dst_pix, dst_region, 0, 0, 0)) + goto out_err; + + /* + * Update the XA state with our hardware surfaces and + * surface formats, and bind the XA state for compositing. + */ + + if (!vmwgfx_xa_update_comp(xa_comp, src_pix, mask_pix, dst_pix)) + goto out_err; + + if (xa_composite_prepare(vsaa->xa_ctx, xa_comp)) + goto out_err; + + REGION_UNINIT(pScreen, &empty); + return TRUE; + out_err: + REGION_UNINIT(pScreen, &empty); + return FALSE; +} + +static void +vmwgfx_composite(struct saa_driver *driver, + int src_x, int src_y, int mask_x, int mask_y, + int dst_x, int dst_y, + int width, int height) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + + xa_composite_rect(vsaa->xa_ctx, src_x, src_y, mask_x, mask_y, + dst_x, dst_y, width, height); +} + +static void +vmwgfx_composite_done(struct saa_driver *driver) +{ + struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + + xa_composite_done(vsaa->xa_ctx); +} + static void vmwgfx_takedown(struct saa_driver *driver) { struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); + if (vsaa->vcomp) + vmwgfx_free_composite(vsaa->vcomp); free(vsaa); } @@ -1130,6 +1253,9 @@ static const struct saa_driver vmwgfx_saa_driver = { .copy_prepare = vmwgfx_copy_prepare, .copy = vmwgfx_copy, .copy_done = vmwgfx_copy_done, + .composite_prepare = vmwgfx_composite_prepare, + .composite = vmwgfx_composite, + .composite_done = vmwgfx_composite_done, .takedown = vmwgfx_takedown, }; @@ -1154,6 +1280,11 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, WSBMINITLISTHEAD(&vsaa->sync_x_list); vsaa->driver = vmwgfx_saa_driver; + vsaa->vcomp = vmwgfx_alloc_composite(); + + if (!vsaa->vcomp) + vsaa->driver.composite_prepare = NULL; + if (!saa_driver_init(pScreen, &vsaa->driver)) goto out_no_saa; diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h index 29863c5..deb3f37 100644 --- a/vmwgfx/vmwgfx_saa.h +++ b/vmwgfx/vmwgfx_saa.h @@ -29,10 +29,11 @@ #define _VMWGFX_SAA_H_ #include "saa.h" -#include +#include #include "vmwgfx_drmi.h" #include "wsbm_util.h" + #define VMWGFX_FLAG_FORCE_GMR (1 << 0) /* Create with GMR as backing store */ #define VMWGFX_FLAG_FORCE_SURFACE (1 << 1) /* Create with surface as backing store */ #define VMWGFX_FLAG_AVOID_HWACCEL (1 << 2) /* Avoid Hardware acceleration on this pixmap */ @@ -98,4 +99,28 @@ vmwgfx_remove_dri2_list(struct vmwgfx_saa_pixmap *vpix); extern void vmwgfx_flush_dri2(ScreenPtr pScreen); +/* + * vmwgfx_xa_composite.c + */ + +struct vmwgfx_composite; + +void +vmwgfx_free_composite(struct vmwgfx_composite *vcomp); +struct vmwgfx_composite * +vmwgfx_alloc_composite(void); + +Bool +vmwgfx_xa_update_comp(struct xa_composite *comp, + PixmapPtr src_pix, + PixmapPtr mask_pix, + PixmapPtr dst_pix); + +struct xa_composite * +vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp, + int op, + PicturePtr src_pict, + PicturePtr mask_pict, + PicturePtr dst_pict); + #endif diff --git a/vmwgfx/vmwgfx_xa_composite.c b/vmwgfx/vmwgfx_xa_composite.c new file mode 100644 index 0000000..a2e3970 --- /dev/null +++ b/vmwgfx/vmwgfx_xa_composite.c @@ -0,0 +1,277 @@ +/* + * Copyright 2009-2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Thomas Hellstrom + * Author: Zack Ruzin + * + * The code in this file translates XRender PICT composite stuff + * to fit the libxatracker API. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "xa_composite.h" +#include "vmwgfx_saa.h" +#include "vmwgfx_saa_priv.h" + + +struct vmwgfx_composite { + union xa_source_pict *src_spict; + union xa_source_pict *mask_spict; + union xa_source_pict *dst_spict; + struct xa_picture *src_pict; + struct xa_picture *mask_pict; + struct xa_picture *dst_pict; + struct xa_composite *comp; +}; + +static const enum xa_composite_op vmwgfx_op_map[] = { + [PictOpClear] = xa_op_clear, + [PictOpSrc] = xa_op_src, + [PictOpDst] = xa_op_dst, + [PictOpOver] = xa_op_over, + [PictOpOverReverse] = xa_op_over_reverse, + [PictOpIn] = xa_op_in, + [PictOpInReverse] = xa_op_in_reverse, + [PictOpOut] = xa_op_out, + [PictOpOutReverse] = xa_op_out_reverse, + [PictOpAtop] = xa_op_atop, + [PictOpAtopReverse] = xa_op_atop_reverse, + [PictOpXor] = xa_op_xor, + [PictOpAdd] = xa_op_add +}; + +static const unsigned int vmwgfx_op_map_size = + sizeof(vmwgfx_op_map) / sizeof(enum xa_composite_op); + +static Bool +vmwgfx_matrix_from_pict_transform(PictTransform *trans, float *matrix) +{ + if (!trans) + return FALSE; + + matrix[0] = XFixedToDouble(trans->matrix[0][0]); + matrix[3] = XFixedToDouble(trans->matrix[0][1]); + matrix[6] = XFixedToDouble(trans->matrix[0][2]); + + matrix[1] = XFixedToDouble(trans->matrix[1][0]); + matrix[4] = XFixedToDouble(trans->matrix[1][1]); + matrix[7] = XFixedToDouble(trans->matrix[1][2]); + + matrix[2] = XFixedToDouble(trans->matrix[2][0]); + matrix[5] = XFixedToDouble(trans->matrix[2][1]); + matrix[8] = XFixedToDouble(trans->matrix[2][2]); + + return TRUE; +} + +static enum xa_composite_wrap +vmwgfx_xa_setup_wrap(Bool pict_has_repeat, int pict_repeat) +{ + enum xa_composite_wrap wrap = xa_wrap_clamp_to_border; + + if (!pict_has_repeat) + return wrap; + + switch(pict_repeat) { + case RepeatNormal: + wrap = xa_wrap_repeat; + break; + case RepeatReflect: + wrap = xa_wrap_mirror_repeat; + break; + case RepeatPad: + wrap = xa_wrap_clamp_to_edge; + break; + default: + break; + } + return wrap; +} + +static Bool +vmwgfx_render_filter_to_xa(int xrender_filter, + enum xa_composite_filter *out_filter) +{ + switch (xrender_filter) { + case PictFilterConvolution: + case PictFilterNearest: + case PictFilterFast: + *out_filter = xa_filter_nearest; + break; + case PictFilterBest: + case PictFilterGood: + case PictFilterBilinear: + *out_filter = xa_filter_linear; + break; + default: + *out_filter = xa_filter_nearest; + return FALSE; + } + return TRUE; +} + +static Bool +vmwgfx_xa_setup_pict(PicturePtr pict, + struct xa_picture *xa_pict, + union xa_source_pict *src_pict) +{ + if (!pict) + return FALSE; + + memset(xa_pict, 0, sizeof(*xa_pict)); + + xa_pict->pict_format = vmwgfx_xa_format(pict->format); + if (xa_pict->pict_format == xa_format_unknown) + return FALSE; + + /* + * Saa doesn't let drivers accelerate alpha maps. + */ + xa_pict->alpha_map = NULL; + xa_pict->component_alpha = pict->componentAlpha; + + xa_pict->has_transform = + vmwgfx_matrix_from_pict_transform(pict->transform, + xa_pict->transform); + + xa_pict->wrap = vmwgfx_xa_setup_wrap(pict->repeat, + pict->repeatType); + + (void) vmwgfx_render_filter_to_xa(pict->filter, &xa_pict->filter); + + if (pict->pSourcePict) { + if (pict->pSourcePict->type != SourcePictTypeSolidFill) + return FALSE; + + src_pict->type = xa_src_pict_solid_fill; + src_pict->solid_fill.color = pict->pSourcePict->solidFill.color; + xa_pict->src_pict = src_pict; + } + + return TRUE; +} + +struct xa_composite * +vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp, + int op, + PicturePtr src_pict, + PicturePtr mask_pict, + PicturePtr dst_pict) +{ + struct xa_composite *comp = vcomp->comp; + + if (op >= vmwgfx_op_map_size) + return NULL; + + comp->op = vmwgfx_op_map[op]; + if (comp->op == xa_op_clear && op != PictOpClear) + return NULL; + + if (!vmwgfx_xa_setup_pict(dst_pict, vcomp->dst_pict, + vcomp->dst_spict)) + return NULL; + if (!vmwgfx_xa_setup_pict(src_pict, vcomp->src_pict, + vcomp->src_spict)) + return NULL; + if (mask_pict && !vmwgfx_xa_setup_pict(mask_pict, + vcomp->mask_pict, + vcomp->mask_spict)) + return NULL; + + comp->dst = vcomp->dst_pict; + comp->src = vcomp->src_pict; + comp->mask = (mask_pict) ? vcomp->mask_pict : NULL; + + return comp; +} + +Bool +vmwgfx_xa_update_comp(struct xa_composite *comp, + PixmapPtr src_pix, + PixmapPtr mask_pix, + PixmapPtr dst_pix) +{ + comp->dst->srf = vmwgfx_saa_pixmap(dst_pix)->hw; + if (src_pix) + comp->src->srf = vmwgfx_saa_pixmap(src_pix)->hw; + if (mask_pix && comp->mask) + comp->mask->srf = vmwgfx_saa_pixmap(mask_pix)->hw; + return TRUE; +} + + +void +vmwgfx_free_composite(struct vmwgfx_composite *vcomp) +{ + if (!vcomp) + return; + + if (vcomp->src_spict) + free(vcomp->src_spict); + if (vcomp->mask_spict) + free(vcomp->mask_spict); + if (vcomp->dst_spict) + free(vcomp->dst_spict); + if (vcomp->src_pict) + free(vcomp->src_pict); + if (vcomp->mask_pict) + free(vcomp->mask_pict); + if (vcomp->dst_pict) + free(vcomp->dst_pict); + if (vcomp->comp) + free(vcomp->comp); + free(vcomp); +} + +struct vmwgfx_composite * +vmwgfx_alloc_composite(void) +{ + const struct xa_composite_allocation *a = xa_composite_allocation(); + struct vmwgfx_composite *vcomp = calloc(1, sizeof(*vcomp)); + + if (!vcomp) + return NULL; + + vcomp->src_spict = calloc(1, a->xa_source_pict_size); + vcomp->mask_spict = calloc(1, a->xa_source_pict_size); + vcomp->dst_spict = calloc(1, a->xa_source_pict_size); + vcomp->src_pict = calloc(1, a->xa_picture_size); + vcomp->mask_pict = calloc(1, a->xa_picture_size); + vcomp->dst_pict = calloc(1, a->xa_picture_size); + vcomp->comp = calloc(1, a->xa_composite_size); + + if (!vcomp->src_spict || !vcomp->mask_spict || !vcomp->dst_spict || + !vcomp->src_pict || !vcomp->mask_pict || !vcomp->dst_pict || + !vcomp->comp) { + vmwgfx_free_composite(vcomp); + return NULL; + } + + return vcomp; +} -- cgit v1.2.3 From 8a9997f060487c0aef07b8e8a95bb3a862de264f Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 1 Jul 2011 11:28:52 +0200 Subject: vmwgfx: Try to sort out format handling with composite. Try to catch all cases where we have to do readbacks or format conversions due to composite formats not being compatible with ordinary accel formats. Signed-off-by: Thomas Hellstrom --- vmwgfx/Makefile.am | 1 + vmwgfx/vmwgfx_dri2.c | 14 +- vmwgfx/vmwgfx_saa.c | 390 +++++++++++++++++++++++---------------------- vmwgfx/vmwgfx_saa.h | 38 ++--- vmwgfx/vmwgfx_saa_priv.h | 122 ++++++++++++++ vmwgfx/vmwgfx_tex_video.c | 4 +- vmwgfx/vmwgfx_xa_surface.c | 367 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 704 insertions(+), 232 deletions(-) create mode 100644 vmwgfx/vmwgfx_saa_priv.h create mode 100644 vmwgfx/vmwgfx_xa_surface.c diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am index 03dbf6a..e956b64 100644 --- a/vmwgfx/Makefile.am +++ b/vmwgfx/Makefile.am @@ -21,6 +21,7 @@ vmwgfx_drv_la_SOURCES = \ vmwgfx_ctrl.c \ vmwgfx_ctrl.h \ vmwgfx_xa_composite.c \ + vmwgfx_xa_surface.c \ wsbm_util.h diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index 07d538f..be5bd51 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -167,9 +167,8 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for if (!srf) { depth = (format) ? vmwgfx_color_format_to_depth(format) : pDraw->depth; - if (!vmwgfx_pixmap_validate_hw(pPixmap, NULL, depth, - XA_FLAG_SHARED | XA_FLAG_RENDER_TARGET, - 0)) + + if (!vmwgfx_hw_dri2_validate(pPixmap, depth)) return FALSE; srf = vpix->hw; @@ -308,12 +307,9 @@ dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, /* pixmap glXWaitX */ if (pSrcBuffer->attachment == DRI2BufferFrontLeft && pDestBuffer->attachment == DRI2BufferFakeFrontLeft) { - LogMessage(X_INFO, "dri2 Validate hw.\n"); - vmwgfx_pixmap_validate_hw(src_priv->pPixmap, NULL, - 0, - XA_FLAG_SHARED | XA_FLAG_RENDER_TARGET, - 0); - return; + + if (!vmwgfx_hw_dri2_validate(src_priv->pPixmap, 0)) + return; } /* pixmap glXWaitGL */ if (pDestBuffer->attachment == DRI2BufferFrontLeft && diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 48c327d..635fb37 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -32,60 +32,7 @@ #include #include "vmwgfx_saa.h" #include "vmwgfx_drmi.h" - -#define VMWGFX_PIX_MALLOC (1 << 0) -#define VMWGFX_PIX_GMR (1 << 1) -#define VMWGFX_PIX_SURFACE (1 << 2) - -struct vmwgfx_saa { - struct saa_driver driver; - struct vmwgfx_dma_ctx *ctx; - struct xa_tracker *xat; - struct xa_context *xa_ctx; - ScreenPtr pScreen; - int drm_fd; - struct vmwgfx_saa_pixmap *src_vpix; - struct vmwgfx_saa_pixmap *dst_vpix; - Bool present_copy; - Bool diff_valid; - int xdiff; - int ydiff; - RegionRec present_region; - uint32_t src_handle; - Bool can_optimize_dma; - void (*present_flush) (ScreenPtr pScreen); - struct _WsbmListHead sync_x_list; - struct vmwgfx_composite *vcomp; -}; - -static inline struct vmwgfx_saa * -to_vmwgfx_saa(struct saa_driver *driver) { - return (struct vmwgfx_saa *) driver; -} - -static enum xa_formats -vmwgfx_choose_xa_format(unsigned int depth) -{ - /* - * For a given depth, choose the same format as the - * dri state tracker. - */ - - switch(depth) { - case 32: - case 24: /* The dri state tracker never uses 24. */ - return xa_format_a8r8g8b8; - case 16: - return xa_format_r5g6b5; - case 15: /* No dri. */ - return xa_format_x1r5g5b5; - default: - break; - } - - return xa_format_unknown; -} - +#include "vmwgfx_saa_priv.h" static Bool vmwgfx_pixmap_add_damage(PixmapPtr pixmap) @@ -486,6 +433,33 @@ vmwgfx_create_pixmap(struct saa_driver *driver, struct saa_pixmap *spix, return TRUE; } +Bool +vmwgfx_hw_kill(struct vmwgfx_saa *vsaa, + struct saa_pixmap *spix) +{ + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + + /* + * Read back any dirty regions from hardware. + */ + + if (!vmwgfx_download_from_hw(&vsaa->driver, spix->pixmap, + &spix->dirty_hw)) + return FALSE; + + xa_surface_destroy(vpix->hw); + vpix->hw = NULL; + + /* + * Remove damage tracking if this is not a scanout pixmap. + */ + + if (WSBMLISTEMPTY(&vpix->scanout_list)) + vmwgfx_pixmap_remove_damage(spix->pixmap); + + return TRUE; +} + void vmwgfx_flush_dri2(ScreenPtr pScreen) { @@ -530,51 +504,6 @@ vmwgfx_destroy_pixmap(struct saa_driver *driver, PixmapPtr pixmap) LogMessage(X_ERROR, "Incorrect dri2 front count.\n"); } -static Bool -vmwgfx_pixmap_create_hw(struct vmwgfx_saa *vsaa, - PixmapPtr pixmap, unsigned int depth, - unsigned int flags) -{ - struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); - struct xa_surface *hw; - - if (!vsaa->xat) - return FALSE; - - if (vpix->hw) - return TRUE; - - if (!depth) - depth = pixmap->drawable.depth; - - hw = xa_surface_create(vsaa->xat, - pixmap->drawable.width, - pixmap->drawable.height, - depth, - xa_type_argb, - vmwgfx_choose_xa_format(depth), - XA_FLAG_RENDER_TARGET | flags); - if (hw == NULL) - return FALSE; - - if ((vpix->gmr || vpix->malloc) && !vmwgfx_pixmap_add_damage(pixmap)) - goto out_no_damage; - - /* - * Even if we don't have a GMR yet, indicate that when needed it - * should be created. - */ - - vpix->hw = hw; - vpix->backing |= VMWGFX_PIX_SURFACE; - vmwgfx_pixmap_free_storage(vpix); - - return TRUE; - -out_no_damage: - xa_surface_destroy(hw); - return FALSE; -} /** @@ -582,79 +511,6 @@ out_no_damage: * Makes sure we have a surface with valid contents. */ -Bool -vmwgfx_pixmap_validate_hw(PixmapPtr pixmap, RegionPtr region, - unsigned int depth, - unsigned int add_flags, - unsigned int remove_flags) -{ - struct vmwgfx_saa *vsaa = - to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); - struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); - struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); - RegionRec intersection; - - if (!vsaa->xat) - return FALSE; - - if (vpix->hw) { - if (!depth) - depth = pixmap->drawable.depth; - - if (xa_surface_redefine(vpix->hw, - pixmap->drawable.width, - pixmap->drawable.height, - depth, - xa_type_argb, - vmwgfx_choose_xa_format(depth), - XA_FLAG_RENDER_TARGET | add_flags, - remove_flags, 1) != 0) - return FALSE; - } else if (!vmwgfx_pixmap_create_hw(vsaa, pixmap, depth, add_flags)) - return FALSE; - - - if (!vmwgfx_pixmap_present_readback(vsaa, pixmap, region)) - return FALSE; - - REGION_NULL(vsaa->pScreen, &intersection); - REGION_COPY(vsaa->pScreen, &intersection, &spix->dirty_shadow); - - if (vpix->dirty_present) - REGION_UNION(vsaa->pScreen, &intersection, vpix->dirty_present, - &spix->dirty_shadow); - - if (spix->damage && REGION_NOTEMPTY(vsaa->pScreen, &intersection)) { - RegionPtr upload = &intersection; - - /* - * Check whether we need to upload from GMR. - */ - - if (region) { - REGION_INTERSECT(vsaa->pScreen, &intersection, region, - &intersection); - upload = &intersection; - } - - if (REGION_NOTEMPTY(vsaa->pScreen, upload)) { - Bool ret = vmwgfx_upload_to_hw(&vsaa->driver, pixmap, upload); - if (ret) { - REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_shadow, - &spix->dirty_shadow, upload); - if (vpix->dirty_present) - REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present, - vpix->dirty_present, upload); - } else { - REGION_UNINIT(vsaa->pScreen, &intersection); - return FALSE; - } - } - } - REGION_UNINIT(vsaa->pScreen, &intersection); - return TRUE; -} - static void vmwgfx_copy_stride(uint8_t *dst, uint8_t *src, unsigned int dst_pitch, unsigned int src_pitch, unsigned int dst_height, @@ -730,7 +586,7 @@ vmwgfx_pix_resize(PixmapPtr pixmap, unsigned int old_pitch, if (vpix->hw) { if (xa_surface_redefine(vpix->hw, draw->width, draw->height, draw->depth, xa_type_argb, - xa_format_unknown, 0, 0, 1) != 0) + xa_format_unknown, vpix->xa_flags, 1) != 0) return FALSE; } return TRUE; @@ -858,6 +714,106 @@ vmwgfx_check_hw_contents(struct vmwgfx_saa *vsaa, REGION_UNINIT(vsaa->pScreen, &intersection); } + +Bool +vmwgfx_create_hw(struct vmwgfx_saa *vsaa, + PixmapPtr pixmap) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + struct xa_surface *hw; + uint32_t new_flags; + + if (!vsaa->xat) + return FALSE; + + if (vpix->hw) + return TRUE; + + new_flags = (vpix->xa_flags & ~vpix->staging_remove_flags) | + vpix->staging_add_flags; + + hw = xa_surface_create(vsaa->xat, + pixmap->drawable.width, + pixmap->drawable.height, + 0, + xa_type_other, + vpix->staging_format, + new_flags); + if (hw == NULL) + return FALSE; + + vpix->xa_flags = new_flags; + + if ((vpix->gmr || vpix->malloc) && !vmwgfx_pixmap_add_damage(pixmap)) + goto out_no_damage; + + /* + * Even if we don't have a GMR yet, indicate that when needed it + * should be created. + */ + + vpix->hw = hw; + vpix->backing |= VMWGFX_PIX_SURFACE; + vmwgfx_pixmap_free_storage(vpix); + + return TRUE; + +out_no_damage: + xa_surface_destroy(hw); + return FALSE; +} + + +Bool +vmwgfx_hw_validate(PixmapPtr pixmap, RegionPtr region) +{ + struct vmwgfx_saa *vsaa = + to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + RegionRec intersection; + + if (!vmwgfx_pixmap_present_readback(vsaa, pixmap, region)) + return FALSE; + + REGION_NULL(vsaa->pScreen, &intersection); + REGION_COPY(vsaa->pScreen, &intersection, &spix->dirty_shadow); + + if (vpix->dirty_present) + REGION_UNION(vsaa->pScreen, &intersection, vpix->dirty_present, + &spix->dirty_shadow); + + if (spix->damage && REGION_NOTEMPTY(vsaa->pScreen, &intersection)) { + RegionPtr upload = &intersection; + + /* + * Check whether we need to upload from GMR. + */ + + if (region) { + REGION_INTERSECT(vsaa->pScreen, &intersection, region, + &intersection); + upload = &intersection; + } + + if (REGION_NOTEMPTY(vsaa->pScreen, upload)) { + Bool ret = vmwgfx_upload_to_hw(&vsaa->driver, pixmap, upload); + if (ret) { + REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_shadow, + &spix->dirty_shadow, upload); + if (vpix->dirty_present) + REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present, + vpix->dirty_present, upload); + } else { + REGION_UNINIT(vsaa->pScreen, &intersection); + return FALSE; + } + } + } + REGION_UNINIT(vsaa->pScreen, &intersection); + return TRUE; +} + static Bool vmwgfx_copy_prepare(struct saa_driver *driver, PixmapPtr src_pixmap, @@ -891,7 +847,7 @@ vmwgfx_copy_prepare(struct saa_driver *driver, return FALSE; if (vmwgfx_present_prepare(vsaa, src_vpix, dst_vpix)) { - if (!vmwgfx_pixmap_validate_hw(src_pixmap, src_reg, 0, 0, 0)) + if (!vmwgfx_hw_accel_validate(src_pixmap, 0, 0, 0, src_reg)) return FALSE; vsaa->present_copy = TRUE; return TRUE; @@ -900,7 +856,7 @@ vmwgfx_copy_prepare(struct saa_driver *driver, } vsaa->present_copy = FALSE; - if (src_vpix->hw != NULL && src_vpix != dst_vpix) { + if (src_vpix != dst_vpix) { /* * Use hardware acceleration either if source is partially only @@ -910,14 +866,43 @@ vmwgfx_copy_prepare(struct saa_driver *driver, if (!has_dirty_hw && !(has_valid_hw && (dst_vpix->hw != NULL))) return FALSE; - if (!vmwgfx_pixmap_validate_hw(src_pixmap, src_reg, 0, 0, 0)) + + /* + * Determine surface formats. + */ + + if (!vmwgfx_hw_accel_stage(src_pixmap, 0, XA_FLAG_RENDER_TARGET, 0)) return FALSE; - if (!vmwgfx_pixmap_create_hw(vsaa, dst_pixmap, 0, - XA_FLAG_RENDER_TARGET)) + if (!vmwgfx_hw_accel_stage(dst_pixmap, 0, XA_FLAG_RENDER_TARGET, 0)) return FALSE; - if (xa_copy_prepare(vsaa->xa_ctx, dst_vpix->hw, src_vpix->hw) == 0) - return TRUE; + /* + * Create hardware surfaces. + */ + + if (!vmwgfx_hw_commit(src_pixmap)) + return FALSE; + if (!vmwgfx_hw_commit(dst_pixmap)) + return FALSE; + + /* + * Setup copy state. + */ + + if (xa_copy_prepare(vsaa->xa_ctx, dst_vpix->hw, src_vpix->hw) != + XA_ERR_NONE) + return FALSE; + + /* + * Migrate data. + */ + + if (!vmwgfx_hw_validate(src_pixmap, src_reg)) { + xa_copy_done(vsaa->xa_ctx); + return FALSE; + } + + return TRUE; } return FALSE; @@ -1077,24 +1062,26 @@ vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op, goto out_err; /* - * Create hw surfaces and migrate data needed for HW compositing. + * Check that we can create the needed hardware surfaces. */ - if (src_region == NULL) - src_region = ∅ - if (src_pix && - !vmwgfx_pixmap_validate_hw(src_pix, src_region, 0, 0, 0)) + if (src_pix && !vmwgfx_hw_composite_src_stage(src_pix, src_pict->format)) goto out_err; - - if (mask_region == NULL) - mask_region = ∅ if (mask_pict && mask_pix && - !vmwgfx_pixmap_validate_hw(mask_pix, mask_region, 0, 0, 0)) + !vmwgfx_hw_composite_src_stage(mask_pix, mask_pict->format)) + goto out_err; + if (!vmwgfx_hw_composite_dst_stage(dst_pix, dst_pict->format)) goto out_err; - if (dst_region == NULL) - dst_region = ∅ - if (!vmwgfx_pixmap_validate_hw(dst_pix, dst_region, 0, 0, 0)) + /* + * Seems OK. Commit the changes, creating hardware surfaces. + */ + + if (src_pix && !vmwgfx_hw_commit(src_pix)) + goto out_err; + if (mask_pict && mask_pix && !vmwgfx_hw_commit(mask_pix)) + goto out_err; + if (!vmwgfx_hw_commit(dst_pix)) goto out_err; /* @@ -1108,9 +1095,26 @@ vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op, if (xa_composite_prepare(vsaa->xa_ctx, xa_comp)) goto out_err; + /* + * Migrate data to surfaces, now that we know that the hardware can indeed + * accelerate. + */ + + if (src_pix && src_region && !vmwgfx_hw_validate(src_pix, src_region)) + goto out_err_migrate; + if (mask_pict && mask_pix && mask_region && + !vmwgfx_hw_validate(mask_pix, mask_region)) + goto out_err_migrate; + if (dst_region && !vmwgfx_hw_validate(dst_pix, dst_region)) + goto out_err_migrate; + + REGION_UNINIT(pScreen, &empty); return TRUE; - out_err: + + out_err_migrate: + xa_composite_done(vsaa->xa_ctx); + out_err: REGION_UNINIT(pScreen, &empty); return FALSE; } diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h index deb3f37..41c6de3 100644 --- a/vmwgfx/vmwgfx_saa.h +++ b/vmwgfx/vmwgfx_saa.h @@ -54,6 +54,11 @@ struct vmwgfx_saa_pixmap { int hw_is_dri2_fronts; struct _WsbmListHead sync_x_head; struct _WsbmListHead scanout_list; + + uint32_t xa_flags; + uint32_t staging_add_flags; + uint32_t staging_remove_flags; + enum xa_formats staging_format; }; struct vmwgfx_screen_box { @@ -68,12 +73,6 @@ to_vmwgfx_saa_pixmap(struct saa_pixmap *spix) return (struct vmwgfx_saa_pixmap *) spix; } -extern Bool -vmwgfx_pixmap_validate_hw(PixmapPtr pixmap, RegionPtr region, - unsigned int depth, - unsigned int add_flags, - unsigned int remove_flags); - static inline struct vmwgfx_saa_pixmap* vmwgfx_saa_pixmap(PixmapPtr pix) { @@ -99,28 +98,11 @@ vmwgfx_remove_dri2_list(struct vmwgfx_saa_pixmap *vpix); extern void vmwgfx_flush_dri2(ScreenPtr pScreen); -/* - * vmwgfx_xa_composite.c - */ - -struct vmwgfx_composite; - -void -vmwgfx_free_composite(struct vmwgfx_composite *vcomp); -struct vmwgfx_composite * -vmwgfx_alloc_composite(void); +extern Bool +vmwgfx_hw_dri2_validate(PixmapPtr pixmap, unsigned int depth); Bool -vmwgfx_xa_update_comp(struct xa_composite *comp, - PixmapPtr src_pix, - PixmapPtr mask_pix, - PixmapPtr dst_pix); - -struct xa_composite * -vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp, - int op, - PicturePtr src_pict, - PicturePtr mask_pict, - PicturePtr dst_pict); - +vmwgfx_hw_accel_validate(PixmapPtr pixmap, unsigned int depth, + uint32_t add_flags, uint32_t remove_flags, + RegionPtr region); #endif diff --git a/vmwgfx/vmwgfx_saa_priv.h b/vmwgfx/vmwgfx_saa_priv.h new file mode 100644 index 0000000..5080047 --- /dev/null +++ b/vmwgfx/vmwgfx_saa_priv.h @@ -0,0 +1,122 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Thomas Hellstrom + */ +#ifndef _VMWGFX_SAA_PRIV_H_ +#define _VMWGFX_SAA_PRIV_H_ + +#define VMWGFX_PIX_MALLOC (1 << 0) +#define VMWGFX_PIX_GMR (1 << 1) +#define VMWGFX_PIX_SURFACE (1 << 2) + +#include +#include +#include "vmwgfx_saa.h" + +struct vmwgfx_saa { + struct saa_driver driver; + struct vmwgfx_dma_ctx *ctx; + struct xa_tracker *xat; + struct xa_context *xa_ctx; + ScreenPtr pScreen; + int drm_fd; + struct vmwgfx_saa_pixmap *src_vpix; + struct vmwgfx_saa_pixmap *dst_vpix; + Bool present_copy; + Bool diff_valid; + int xdiff; + int ydiff; + RegionRec present_region; + uint32_t src_handle; + Bool can_optimize_dma; + void (*present_flush) (ScreenPtr pScreen); + struct _WsbmListHead sync_x_list; + struct vmwgfx_composite *vcomp; +}; + +static inline struct vmwgfx_saa * +to_vmwgfx_saa(struct saa_driver *driver) { + return (struct vmwgfx_saa *) driver; +} + +/* + * In vmwgfx_saa.c + */ + +Bool +vmwgfx_hw_kill(struct vmwgfx_saa *vsaa, + struct saa_pixmap *spix); +Bool +vmwgfx_create_hw(struct vmwgfx_saa *vsaa, + PixmapPtr pixmap); + + +/* + * vmwgfx_xa_surface.c + */ + +enum xa_formats +vmwgfx_xa_format(enum _PictFormatShort format); +Bool +vmwgfx_hw_validate(PixmapPtr pixmap, RegionPtr region); + +Bool +vmwgfx_hw_accel_stage(PixmapPtr pixmap, unsigned int depth, + uint32_t add_flags, uint32_t remove_flags); +Bool +vmwgfx_hw_composite_src_stage(PixmapPtr pixmap, + enum _PictFormatShort pict_format); +Bool +vmwgfx_hw_composite_dst_stage(PixmapPtr pixmap, + enum _PictFormatShort pict_format); +Bool +vmwgfx_hw_commit(PixmapPtr pixmap); + +/* + * vmwgfx_xa_composite.c + */ + +struct vmwgfx_composite; + +void +vmwgfx_free_composite(struct vmwgfx_composite *vcomp); +struct vmwgfx_composite * +vmwgfx_alloc_composite(void); + +Bool +vmwgfx_xa_update_comp(struct xa_composite *comp, + PixmapPtr src_pix, + PixmapPtr mask_pix, + PixmapPtr dst_pix); + +struct xa_composite * +vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp, + int op, + PicturePtr src_pict, + PicturePtr mask_pict, + PicturePtr dst_pict); + + +#endif diff --git a/vmwgfx/vmwgfx_tex_video.c b/vmwgfx/vmwgfx_tex_video.c index c357f06..801b066 100644 --- a/vmwgfx/vmwgfx_tex_video.c +++ b/vmwgfx/vmwgfx_tex_video.c @@ -223,7 +223,7 @@ check_yuv_surfaces(struct xorg_xv_port_priv *priv, int width, int height) else ret = xa_surface_redefine(yuv[i], width, height, 8, xa_type_yuv_component, - xa_format_unknown, 0, 0, 0); + xa_format_unknown, 0, 0); if (ret || !yuv[i]) return BadAlloc; @@ -455,7 +455,7 @@ display_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id, REGION_NULL(pScreen, ®); - if (!vmwgfx_pixmap_validate_hw(pPixmap, ®, 0, XA_FLAG_RENDER_TARGET, 0)) + if (!vmwgfx_hw_accel_validate(pPixmap, 0, XA_FLAG_RENDER_TARGET, 0, ®)) goto out_no_dst; hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y)); diff --git a/vmwgfx/vmwgfx_xa_surface.c b/vmwgfx/vmwgfx_xa_surface.c new file mode 100644 index 0000000..6c4ab85 --- /dev/null +++ b/vmwgfx/vmwgfx_xa_surface.c @@ -0,0 +1,367 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Thomas Hellstrom + */ +#ifdef _HAVE_CONFIG_H_ +#include "config.h" +#endif + +#include +#include "vmwgfx_saa_priv.h" + + +static const enum xa_surface_type vmwgfx_stype_map[] = { + [PICT_TYPE_OTHER] = xa_type_other, + [PICT_TYPE_A] = xa_type_a, + [PICT_TYPE_ARGB] = xa_type_argb, + [PICT_TYPE_ABGR] = xa_type_abgr, + [PICT_TYPE_BGRA] = xa_type_bgra +}; + +static const unsigned int vmwgfx_stype_map_size = + sizeof(vmwgfx_stype_map) / sizeof(enum xa_surface_type); + + +/* + * Create an xa format from a PICT format. + */ +enum xa_formats +vmwgfx_xa_format(enum _PictFormatShort format) +{ + uint32_t ptype = PICT_FORMAT_TYPE(format); + + if (ptype >= vmwgfx_stype_map_size || + vmwgfx_stype_map[ptype] == 0 || + vmwgfx_stype_map[ptype] == xa_type_other) + return xa_format_unknown; + + return xa_format(PICT_FORMAT_BPP(format), + vmwgfx_stype_map[ptype], + PICT_FORMAT_A(format), + PICT_FORMAT_R(format), + PICT_FORMAT_G(format), + PICT_FORMAT_B(format)); +} + +/* + * Choose formats and flags for a dri2 surface. + */ +static Bool +vmwgfx_hw_dri2_stage(PixmapPtr pixmap, unsigned int depth) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + enum xa_formats format; + + if (depth == 0) + depth = pixmap->drawable.depth; + + switch(depth) { + case 32: + format = xa_format_a8r8g8b8; + break; + case 24: + format = xa_format_x8r8g8b8; + break; + case 16: + format = xa_format_r5g6b5; + break; + case 15: + format = xa_format_x1r5g5b5; + break; + default: + return FALSE; + } + + vpix->staging_format = format; + vpix->staging_remove_flags = 0; + vpix->staging_add_flags = XA_FLAG_RENDER_TARGET | XA_FLAG_SHARED; + + return TRUE; +} + +/* + * Is composite old format compatible? Only difference is that old format + * has more alpha bits? + */ +static inline Bool +vmwgfx_old_format_compatible(enum xa_formats format, + enum xa_formats old_format) +{ + return (format == old_format || + (xa_format_type(old_format) == xa_format_type(old_format) && + xa_format_a(format) <= xa_format_a(old_format) && + xa_format_r(format) == xa_format_r(old_format) && + xa_format_g(format) == xa_format_g(old_format) && + xa_format_b(format) == xa_format_b(old_format))); +} + + +/* + * Choose format and flags for a composite dst surface. + */ +Bool +vmwgfx_hw_composite_dst_stage(PixmapPtr pixmap, + enum _PictFormatShort pict_format) +{ + struct vmwgfx_saa *vsaa = + to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + enum xa_formats format = vmwgfx_xa_format(pict_format); + + /* + * Check if we can reuse old hardware format. + */ + + if (vpix->hw) { + enum xa_formats old_format = xa_surface_format(vpix->hw); + + if (vmwgfx_old_format_compatible(format, old_format)) + format = old_format; + } + + if (xa_format_check_supported(vsaa->xat, format, + vpix->xa_flags | XA_FLAG_RENDER_TARGET) != + XA_ERR_NONE) { + return FALSE; + } + + vpix->staging_format = format; + vpix->staging_remove_flags = 0; + vpix->staging_add_flags = XA_FLAG_RENDER_TARGET; + return TRUE; +} + +/* + * Choose format and flags for a composite src surface. + */ +Bool +vmwgfx_hw_composite_src_stage(PixmapPtr pixmap, + enum _PictFormatShort pict_format) +{ + struct vmwgfx_saa *vsaa = + to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + enum xa_formats format = vmwgfx_xa_format(pict_format); + enum xa_formats swizzle_format = xa_format_unknown; + enum xa_surface_type ftype; + + if (format == xa_format_unknown) + return FALSE; + + ftype = xa_format_type(format); + if (ftype == xa_type_abgr) { + + swizzle_format = xa_format(xa_format_bpp(format), + xa_type_argb, + xa_format_a(format), + xa_format_r(format), + xa_format_g(format), + xa_format_b(format)); + } + + /* + * Check if we can reuse old format. + */ + + if (vpix->hw) { + enum xa_formats old_format = xa_surface_format(vpix->hw); + + if (vmwgfx_old_format_compatible(format, old_format) || + (swizzle_format != xa_format_unknown && + vmwgfx_old_format_compatible(swizzle_format, old_format))) { + format = old_format; + goto have_format; + } + } + + if (swizzle_format != xa_format_unknown && + xa_format_check_supported(vsaa->xat, swizzle_format, vpix->xa_flags) == + XA_ERR_NONE) { + format = swizzle_format; + goto have_format; + } + + if (xa_format_check_supported(vsaa->xat, format, vpix->xa_flags) == + XA_ERR_NONE) { + goto have_format; + } + + return FALSE; + have_format: + vpix->staging_format = format; + vpix->staging_remove_flags = 0; + vpix->staging_add_flags = 0; + + return TRUE; +} + +/* + * Choose accel format given depth. + */ +static enum xa_formats +vmwgfx_choose_accel_format(unsigned int depth) +{ + switch(depth) { + case 32: + case 24: + return xa_format_a8r8g8b8; + case 16: + return xa_format_r5g6b5; + case 15: + return xa_format_x1r5g5b5; + case 8: + return xa_format_a8; + default: + break; + } + return xa_format_unknown; +} + + +/* + * Determine xa format and flags for an ordinary accel surface. + */ +Bool +vmwgfx_hw_accel_stage(PixmapPtr pixmap, unsigned int depth, + uint32_t add_flags, uint32_t remove_flags) +{ + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + enum xa_formats format = xa_format_unknown; + + if (depth == 0) + depth = pixmap->drawable.depth; + + if (vpix->hw) { + enum xa_formats old_format = xa_surface_format(vpix->hw); + enum xa_surface_type ftype = xa_format_type(old_format); + + if (ftype != xa_type_argb && + ftype != xa_type_a) { + LogMessage(X_ERROR, + "Acceleration fallback due to strange hw format.\n"); + return FALSE; + } + + if (xa_format_depth(old_format) == depth || + (xa_format_depth(old_format) == 32 && + depth == 24)) + format = old_format; + } + + if (format == xa_format_unknown) + format = vmwgfx_choose_accel_format(depth); + + if (format == xa_format_unknown) + return FALSE; + + vpix->staging_add_flags = add_flags; + vpix->staging_remove_flags = remove_flags; + vpix->staging_format = format; + + return TRUE; +} + +/* + * Create a surface with a format and flags determined by one of + * the staging functions. + */ +Bool +vmwgfx_hw_commit(PixmapPtr pixmap) +{ + struct vmwgfx_saa *vsaa = + to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + enum xa_formats format = vpix->staging_format; + + if (vpix->hw) { + enum xa_formats old_format = xa_surface_format(vpix->hw); + + if (vpix->staging_format != old_format) { + if (xa_format_type(format) != xa_format_type(old_format) || + xa_format_r(format) != xa_format_r(old_format) || + xa_format_g(format) != xa_format_g(old_format) || + xa_format_b(format) != xa_format_b(old_format)) { + + LogMessage(X_INFO, "Killing old hw surface.\n"); + + if (!vmwgfx_hw_kill(vsaa, spix)) + return FALSE; + } + } + } + + if (vpix->hw) { + uint32_t new_flags; + + new_flags = (vpix->xa_flags & ~vpix->staging_remove_flags) | + vpix->staging_add_flags; + + if (vpix->staging_format != xa_surface_format(vpix->hw)) + LogMessage(X_INFO, "Changing hardware format.\n"); + + if (xa_surface_redefine(vpix->hw, + pixmap->drawable.width, + pixmap->drawable.height, + 0, + xa_type_other, + vpix->staging_format, + new_flags, 1) != XA_ERR_NONE) + return FALSE; + vpix->xa_flags = new_flags; + } else if (!vmwgfx_create_hw(vsaa, pixmap)) + return FALSE; + + return TRUE; +} + +/* + * Create an accel surface if there is none, and make sure the region + * given by @region is valid. If @region is NULL, the whole surface + * will be valid. This is a utility convenience function only. + */ +Bool +vmwgfx_hw_accel_validate(PixmapPtr pixmap, unsigned int depth, + uint32_t add_flags, uint32_t remove_flags, + RegionPtr region) +{ + return (vmwgfx_hw_accel_stage(pixmap, depth, add_flags, remove_flags) && + vmwgfx_hw_commit(pixmap) && + vmwgfx_hw_validate(pixmap, region)); +} + + +/* + * Create a dri2 surface if there is none, + * and make sure the whole surfade is valid. + * This is a utility convenience function only. + */ +Bool +vmwgfx_hw_dri2_validate(PixmapPtr pixmap, unsigned int depth) +{ + return (vmwgfx_hw_dri2_stage(pixmap, depth) && + vmwgfx_hw_commit(pixmap) && + vmwgfx_hw_validate(pixmap, NULL)); +} -- cgit v1.2.3 From d2e27ee5c116cd914d98c2ffa4a974704c250be7 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 1 Jul 2011 12:29:50 +0200 Subject: vmwgfx: Set up XA version checking. Signed-off-by: Thomas Hellstrom --- vmwgfx/vmwgfx_driver.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index 17d93eb..629638e 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -59,6 +59,8 @@ #include #include "vmwgfx_saa.h" +#define XA_VERSION_MINOR_REQUIRED 0 + /* * Some macros to deal with function wrapping. */ @@ -761,6 +763,37 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (!ms->xat) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to initialize Gallium3D Xa. No 3D available.\n"); + else { + int major, minor, patch; + + xa_tracker_version(&major, &minor, &patch); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Gallium3D XA version: %d.%d.%d.\n", + major, minor, patch); + + if (XA_TRACKER_VERSION_MAJOR == 0) { + if (minor != XA_TRACKER_VERSION_MINOR) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Expecting XA version 0.%d.x.\n", + XA_TRACKER_VERSION_MINOR); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No 3D available.\n"); + xa_tracker_destroy(ms->xat); + ms->xat = NULL; + } + } else if (major != XA_TRACKER_VERSION_MAJOR || + minor < XA_VERSION_MINOR_REQUIRED) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Expecting %d.%d.x >= XA version < %d.0.0.\n", + XA_TRACKER_VERSION_MAJOR, + XA_VERSION_MINOR_REQUIRED, + XA_TRACKER_VERSION_MAJOR + 1); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No 3D available.\n"); + xa_tracker_destroy(ms->xat); + ms->xat = NULL; + } + } if (!vmwgfx_saa_init(pScreen, ms->fd, ms->xat, &xorg_flush)) { FatalError("Failed to initialize SAA.\n"); -- cgit v1.2.3 From 81e7099b6bbd9fdae66a3186dfc3fff2758009cf Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 1 Jul 2011 13:23:30 +0200 Subject: vmwgfx: Require libxatracker >= 0.4. Signed-off-by: Thomas Hellstrom --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index da140bf..1f823bb 100644 --- a/configure.ac +++ b/configure.ac @@ -115,7 +115,7 @@ AM_CONDITIONAL(XSERVER_LIBPCIACCESS, test "x$XSERVER_LIBPCIACCESS" = xyes) AC_SUBST([moduledir]) if test x$BUILD_VMWGFX = xyes; then - PKG_CHECK_MODULES([XATRACKER], [xatracker >= 0.2.0],[],[BUILD_VMWGFX=no]) + PKG_CHECK_MODULES([XATRACKER], [xatracker >= 0.4.0],[],[BUILD_VMWGFX=no]) fi DRIVER_NAME=vmware -- cgit v1.2.3 From 9cff0a84308723d9790c6365c0d4b1c107794995 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 7 Jul 2011 09:21:56 +0200 Subject: vmwgfx: Various acceleration fixes. Signed-off-by: Thomas Hellstrom --- vmwgfx/vmwgfx_saa.c | 57 +++++++++++++++++++++++----------------------- vmwgfx/vmwgfx_xa_surface.c | 4 ++-- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 635fb37..b39bc6d 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -439,6 +439,9 @@ vmwgfx_hw_kill(struct vmwgfx_saa *vsaa, { struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + if (!vpix->hw) + return TRUE; + /* * Read back any dirty regions from hardware. */ @@ -846,9 +849,9 @@ vmwgfx_copy_prepare(struct saa_driver *driver, if (!has_dirty_hw && !has_valid_hw) return FALSE; + if (!vmwgfx_hw_accel_validate(src_pixmap, 0, 0, 0, src_reg)) + return FALSE; if (vmwgfx_present_prepare(vsaa, src_vpix, dst_vpix)) { - if (!vmwgfx_hw_accel_validate(src_pixmap, 0, 0, 0, src_reg)) - return FALSE; vsaa->present_copy = TRUE; return TRUE; } @@ -886,21 +889,21 @@ vmwgfx_copy_prepare(struct saa_driver *driver, return FALSE; /* - * Setup copy state. + * Migrate data. */ - if (xa_copy_prepare(vsaa->xa_ctx, dst_vpix->hw, src_vpix->hw) != - XA_ERR_NONE) + if (!vmwgfx_hw_validate(src_pixmap, src_reg)) { + xa_copy_done(vsaa->xa_ctx); return FALSE; + } /* - * Migrate data. + * Setup copy state. */ - if (!vmwgfx_hw_validate(src_pixmap, src_reg)) { - xa_copy_done(vsaa->xa_ctx); + if (xa_copy_prepare(vsaa->xa_ctx, dst_vpix->hw, src_vpix->hw) != + XA_ERR_NONE) return FALSE; - } return TRUE; } @@ -1016,10 +1019,9 @@ vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op, /* * First we define our migration policy. We accelerate only if there - * is dirty hw regions to be read or if all source data is + * are dirty hw regions to be read or if all source data is * available in hw, and the destination has a hardware surface. */ - dst_vpix = vmwgfx_saa_pixmap(dst_pix); valid_hw = (dst_vpix->hw != NULL); if (saa_op_reads_destination(op)) { @@ -1064,7 +1066,6 @@ vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op, /* * Check that we can create the needed hardware surfaces. */ - if (src_pix && !vmwgfx_hw_composite_src_stage(src_pix, src_pict->format)) goto out_err; if (mask_pict && mask_pix && @@ -1076,7 +1077,6 @@ vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op, /* * Seems OK. Commit the changes, creating hardware surfaces. */ - if (src_pix && !vmwgfx_hw_commit(src_pix)) goto out_err; if (mask_pict && mask_pix && !vmwgfx_hw_commit(mask_pix)) @@ -1086,34 +1086,33 @@ vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op, /* * Update the XA state with our hardware surfaces and - * surface formats, and bind the XA state for compositing. + * surface formats */ - if (!vmwgfx_xa_update_comp(xa_comp, src_pix, mask_pix, dst_pix)) goto out_err; - if (xa_composite_prepare(vsaa->xa_ctx, xa_comp)) - goto out_err; - /* - * Migrate data to surfaces, now that we know that the hardware can indeed - * accelerate. + * Migrate data to surfaces. */ - - if (src_pix && src_region && !vmwgfx_hw_validate(src_pix, src_region)) - goto out_err_migrate; + if (src_pix && src_region && !vmwgfx_hw_validate(src_pix, NULL)) + goto out_err; if (mask_pict && mask_pix && mask_region && - !vmwgfx_hw_validate(mask_pix, mask_region)) - goto out_err_migrate; - if (dst_region && !vmwgfx_hw_validate(dst_pix, dst_region)) - goto out_err_migrate; + !vmwgfx_hw_validate(mask_pix, NULL)) + goto out_err; + if (dst_region && !vmwgfx_hw_validate(dst_pix, NULL)) + goto out_err; + + /* + * Bind the XA state. This must be done after data migration, since + * migration may change the hardware surfaces. + */ + if (xa_composite_prepare(vsaa->xa_ctx, xa_comp)) + goto out_err; REGION_UNINIT(pScreen, &empty); return TRUE; - out_err_migrate: - xa_composite_done(vsaa->xa_ctx); out_err: REGION_UNINIT(pScreen, &empty); return FALSE; diff --git a/vmwgfx/vmwgfx_xa_surface.c b/vmwgfx/vmwgfx_xa_surface.c index 6c4ab85..7542413 100644 --- a/vmwgfx/vmwgfx_xa_surface.c +++ b/vmwgfx/vmwgfx_xa_surface.c @@ -110,7 +110,7 @@ vmwgfx_old_format_compatible(enum xa_formats format, enum xa_formats old_format) { return (format == old_format || - (xa_format_type(old_format) == xa_format_type(old_format) && + (xa_format_type(format) == xa_format_type(old_format) && xa_format_a(format) <= xa_format_a(old_format) && xa_format_r(format) == xa_format_r(old_format) && xa_format_g(format) == xa_format_g(old_format) && @@ -133,7 +133,6 @@ vmwgfx_hw_composite_dst_stage(PixmapPtr pixmap, /* * Check if we can reuse old hardware format. */ - if (vpix->hw) { enum xa_formats old_format = xa_surface_format(vpix->hw); @@ -150,6 +149,7 @@ vmwgfx_hw_composite_dst_stage(PixmapPtr pixmap, vpix->staging_format = format; vpix->staging_remove_flags = 0; vpix->staging_add_flags = XA_FLAG_RENDER_TARGET; + return TRUE; } -- cgit v1.2.3 From eea96a6f5ccc6a3a1e2bb2737f211076de443462 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 7 Jul 2011 22:02:15 +0200 Subject: vmwgfx: Add boolean flags for different rendering modes Basically we support three ways of getting data to the screen: 1) Mixed mode: We mix presents and updates. 2) Mixed present optimized: A version of mixed where copies to the front buffer end up as presents, saving a blit. 3) 3D surface mode: We only present from a 3D surface. Software contents are first DMA'd to that surface. This change adds boolean flags to the saa struct to select which mode to use. Signed-off-by: Thomas Hellstrom --- vmwgfx/vmwgfx_saa.c | 78 +++++++++++++++++++++++++++++++++--------------- vmwgfx/vmwgfx_saa_priv.h | 2 ++ 2 files changed, 56 insertions(+), 24 deletions(-) diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index b39bc6d..41cea13 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -94,18 +94,20 @@ vmwgfx_pixmap_remove_present(struct vmwgfx_saa_pixmap *vpix) } static Bool -vmwgfx_pixmap_add_present(PixmapPtr pixmap) +vmwgfx_pixmap_add_present(PixmapPtr pixmap, Bool present_opt) { struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); ScreenPtr pScreen = pixmap->drawable.pScreen; (void) pScreen; - vpix->dirty_present = REGION_CREATE(pScreen, NULL, 0); - if (!vpix->dirty_present) - return FALSE; - vpix->present_damage = REGION_CREATE(pScreen, NULL, 0); - if (!vpix->present_damage) - goto out_no_present_damage; + if (present_opt) { + vpix->dirty_present = REGION_CREATE(pScreen, NULL, 0); + if (!vpix->dirty_present) + return FALSE; + vpix->present_damage = REGION_CREATE(pScreen, NULL, 0); + if (!vpix->present_damage) + goto out_no_present_damage; + } vpix->pending_update = REGION_CREATE(pScreen, NULL, 0); if (!vpix->pending_update) goto out_no_pending_update; @@ -121,9 +123,11 @@ vmwgfx_pixmap_add_present(PixmapPtr pixmap) out_no_pending_present: REGION_DESTROY(pScreen, vpix->pending_update); out_no_pending_update: - REGION_DESTROY(pScreen, vpix->present_damage); + if (vpix->present_damage) + REGION_DESTROY(pScreen, vpix->present_damage); out_no_present_damage: - REGION_DESTROY(pScreen, vpix->dirty_present); + if (vpix->dirty_present) + REGION_DESTROY(pScreen, vpix->dirty_present); return FALSE; } @@ -1148,6 +1152,11 @@ vmwgfx_takedown(struct saa_driver *driver) free(vsaa); } +/* + * This function call originates from the damage layer (outside SAA) + * to indicate that an operation is complete, and that damage is being + * processed. + */ static void vmwgfx_operation_complete(struct saa_driver *driver, PixmapPtr pixmap) @@ -1173,7 +1182,11 @@ vmwgfx_operation_complete(struct saa_driver *driver, } } - +/* + * This function is called by SAA to indicate that SAA has + * dirtied a region of a pixmap, either as hw (accelerated) or as + * !hw (not accelerated). + */ static Bool vmwgfx_dirty(struct saa_driver *driver, PixmapPtr pixmap, Bool hw, RegionPtr damage) @@ -1181,24 +1194,36 @@ vmwgfx_dirty(struct saa_driver *driver, PixmapPtr pixmap, struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); - BoxPtr rects; - int num_rects; - if (!vmwgfx_is_present_hw(pixmap)) + /* + * Return if this is not a scanout pixmap. + */ + if (WSBMLISTEMPTY(&vpix->scanout_list)) return TRUE; - rects = REGION_RECTS(damage); - num_rects = REGION_NUM_RECTS(damage); + if (vsaa->only_hw_presents) { + if (!vpix->hw) { + if (!vmwgfx_hw_accel_stage(pixmap, 0, XA_FLAG_RENDER_TARGET, 0)) + return FALSE; + if (!vmwgfx_hw_commit(pixmap)) + return FALSE; + } + if (!hw && !vmwgfx_upload_to_hw(&vsaa->driver, pixmap, damage)) + return FALSE; + REGION_SUBTRACT(&vsaa->pScreen, &spix->dirty_shadow, + &spix->dirty_shadow, damage); + hw = TRUE; + } /* * Is the new scanout damage hw or sw? */ - if (hw) { /* * Dump pending present into present tracking region. */ - if (REGION_NOTEMPTY(vsaa->pScreen, vpix->present_damage)) { + if (vpix->dirty_present && + REGION_NOTEMPTY(vsaa->pScreen, vpix->present_damage)) { REGION_UNION(vsaa->pScreen, vpix->dirty_present, vpix->dirty_present, damage); REGION_EMPTY(vsaa->pScreen, vpix->present_damage); @@ -1215,8 +1240,9 @@ vmwgfx_dirty(struct saa_driver *driver, PixmapPtr pixmap, } REGION_UNION(vsaa->pScreen, vpix->pending_present, vpix->pending_present, damage); - REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present, - vpix->dirty_present, damage); + if (vpix->dirty_present) + REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present, + vpix->dirty_present, damage); } } else { if (REGION_NOTEMPTY(vsaa->pScreen, vpix->pending_present)) { @@ -1231,8 +1257,9 @@ vmwgfx_dirty(struct saa_driver *driver, PixmapPtr pixmap, } REGION_UNION(vsaa->pScreen, vpix->pending_update, vpix->pending_update, damage); - REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present, - vpix->dirty_present, damage); + if (vpix->dirty_present) + REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present, + vpix->dirty_present, damage); } return TRUE; @@ -1280,6 +1307,8 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, vsaa->drm_fd = drm_fd; vsaa->present_flush = present_flush; vsaa->can_optimize_dma = FALSE; + vsaa->use_present_opt = TRUE; + vsaa->only_hw_presents = FALSE; WSBMINITLISTHEAD(&vsaa->sync_x_list); vsaa->driver = vmwgfx_saa_driver; @@ -1322,8 +1351,9 @@ vmwgfx_scanout_refresh(PixmapPtr pixmap) box.y2 = pixmap->drawable.height; REGION_RESET(vsaa->pScreen, vpix->pending_update, &box); - REGION_SUBTRACT(vsaa->pScreen, vpix->pending_present, - &vpix->base.dirty_hw, vpix->dirty_present); + if (vpix->dirty_present) + REGION_SUBTRACT(vsaa->pScreen, vpix->pending_present, + &vpix->base.dirty_hw, vpix->dirty_present); REGION_SUBTRACT(vsaa->pScreen, vpix->pending_update, vpix->pending_update, &vpix->base.dirty_hw); } @@ -1346,7 +1376,7 @@ vmwgfx_scanout_ref(struct vmwgfx_screen_box *box) if (WSBMLISTEMPTY(&vpix->scanout_list)) { ret = !vmwgfx_pixmap_create_gmr(vsaa, pixmap); if (!ret) - ret = !vmwgfx_pixmap_add_present(pixmap); + ret = !vmwgfx_pixmap_add_present(pixmap, vsaa->use_present_opt); if (!ret) ret = drmModeAddFB(vsaa->drm_fd, pixmap->drawable.width, diff --git a/vmwgfx/vmwgfx_saa_priv.h b/vmwgfx/vmwgfx_saa_priv.h index 5080047..b48ef18 100644 --- a/vmwgfx/vmwgfx_saa_priv.h +++ b/vmwgfx/vmwgfx_saa_priv.h @@ -51,6 +51,8 @@ struct vmwgfx_saa { RegionRec present_region; uint32_t src_handle; Bool can_optimize_dma; + Bool use_present_opt; + Bool only_hw_presents; void (*present_flush) (ScreenPtr pScreen); struct _WsbmListHead sync_x_list; struct vmwgfx_composite *vcomp; -- cgit v1.2.3 From 858dbcdddb35b690a543a103d43dcaeb040260c1 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sat, 9 Jul 2011 22:54:41 +0200 Subject: vmwgfx: Don't dirty the front buffer as hw when doing a dri2copyregion from it When copying from a dri2 buffer we usually dirty it as hw, since dri has been rendering to it, and there can only be hw contents in the buffer. However for the real front, X has already done the dirty work for us. Also remove a glxWaitX() debug message. This should fix piglit read-front. Signed-off-by: Thomas Hellstrom --- vmwgfx/vmwgfx_dri2.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index be5bd51..5cffc4d 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -271,10 +271,6 @@ dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, RegionPtr myClip; GCPtr gc; - if (pSrcBuffer->attachment == DRI2BufferFrontLeft && - pDestBuffer->attachment == DRI2BufferFakeFrontLeft) - LogMessage(X_ERROR, "glxwaitx\n"); - /* * In driCreateBuffers we dewrap windows into the * backing pixmaps in order to get to the texture. @@ -332,7 +328,8 @@ dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, * that something changed. */ DamageRegionAppend(src_draw, pRegion); - saa_drawable_dirty(src_draw, TRUE, pRegion); + if (pSrcBuffer->attachment != DRI2BufferFrontLeft) + saa_drawable_dirty(src_draw, TRUE, pRegion); DamageRegionProcessPending(src_draw); /* -- cgit v1.2.3 From 98ff64fd7a13d2824d6f36b0d8f13d95f8be9e48 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Mon, 11 Jul 2011 12:23:32 +0100 Subject: vmwgfx: Fix logic when checking for XA Signed-off-by: Jakob Bornecrantz --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1f823bb..2c4f959 100644 --- a/configure.ac +++ b/configure.ac @@ -92,7 +92,7 @@ PKG_CHECK_EXISTS([xorg-server >= 1.4.99], PKG_CHECK_EXISTS([xorg-server >= 1.7.0], [AC_DEFINE([HAVE_XORG_SERVER_1_7_0], 1, [Has version 1.7.0 or greater of the Xserver]) - BUILD_VMWGFX=yes],[BUILD_VMWGFX=yes]) + BUILD_VMWGFX=yes],[BUILD_VMWGFX=no]) # Obtain compiler/linker options for the vmwarectrl client tool PKG_CHECK_MODULES(X11, x11 xext) -- cgit v1.2.3 From b29d71e3adb16f2a8e3e9d534bf8b1c1f8e0d9ef Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 13 Jul 2011 16:28:52 +0100 Subject: saa: Remove superflouos headers includes Signed-off-by: Jakob Bornecrantz --- saa/saa.c | 1 - saa/saa_priv.h | 1 - 2 files changed, 2 deletions(-) diff --git a/saa/saa.c b/saa/saa.c index 9d7436b..173c090 100644 --- a/saa/saa.c +++ b/saa/saa.c @@ -36,7 +36,6 @@ #include "saa_priv.h" #include -#include "dixfontstr.h" #include "regionstr.h" #include "saa.h" #include "saa_priv.h" diff --git a/saa/saa_priv.h b/saa/saa_priv.h index 5d449fd..6652054 100644 --- a/saa/saa_priv.h +++ b/saa/saa_priv.h @@ -56,7 +56,6 @@ #include "mi.h" #include "dix.h" #include "fb.h" -#include "fboverlay.h" #ifdef RENDER #include "glyphstr.h" #endif -- cgit v1.2.3 From f17abaa926fdbedab1e6236e109fa746fcc2320b Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 13 Jul 2011 16:30:01 +0100 Subject: vmwgfx: Just include vmwgfx_drm.h We do this in mesa as well Signed-off-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_drm.h | 615 ++++++++++++++++++++++++++++++++++++++++++++++++ vmwgfx/vmwgfx_drmi.c | 2 +- vmwgfx/vmwgfx_overlay.c | 2 +- 3 files changed, 617 insertions(+), 2 deletions(-) create mode 100644 vmwgfx/vmwgfx_drm.h diff --git a/vmwgfx/vmwgfx_drm.h b/vmwgfx/vmwgfx_drm.h new file mode 100644 index 0000000..650e6bf --- /dev/null +++ b/vmwgfx/vmwgfx_drm.h @@ -0,0 +1,615 @@ +/************************************************************************** + * + * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef __VMWGFX_DRM_H__ +#define __VMWGFX_DRM_H__ + +#define DRM_VMW_MAX_SURFACE_FACES 6 +#define DRM_VMW_MAX_MIP_LEVELS 24 + +#define DRM_VMW_EXT_NAME_LEN 128 + +#define DRM_VMW_GET_PARAM 0 +#define DRM_VMW_ALLOC_DMABUF 1 +#define DRM_VMW_UNREF_DMABUF 2 +#define DRM_VMW_CURSOR_BYPASS 3 +/* guarded by DRM_VMW_PARAM_NUM_STREAMS != 0*/ +#define DRM_VMW_CONTROL_STREAM 4 +#define DRM_VMW_CLAIM_STREAM 5 +#define DRM_VMW_UNREF_STREAM 6 +/* guarded by DRM_VMW_PARAM_3D == 1 */ +#define DRM_VMW_CREATE_CONTEXT 7 +#define DRM_VMW_UNREF_CONTEXT 8 +#define DRM_VMW_CREATE_SURFACE 9 +#define DRM_VMW_UNREF_SURFACE 10 +#define DRM_VMW_REF_SURFACE 11 +#define DRM_VMW_EXECBUF 12 +#define DRM_VMW_FIFO_DEBUG 13 +#define DRM_VMW_FENCE_WAIT 14 +/* guarded by minor version >= 2 */ +#define DRM_VMW_UPDATE_LAYOUT 15 + + +/*************************************************************************/ +/** + * DRM_VMW_GET_PARAM - get device information. + * + * DRM_VMW_PARAM_FIFO_OFFSET: + * Offset to use to map the first page of the FIFO read-only. + * The fifo is mapped using the mmap() system call on the drm device. + * + * DRM_VMW_PARAM_OVERLAY_IOCTL: + * Does the driver support the overlay ioctl. + */ + +#define DRM_VMW_PARAM_NUM_STREAMS 0 +#define DRM_VMW_PARAM_NUM_FREE_STREAMS 1 +#define DRM_VMW_PARAM_3D 2 +#define DRM_VMW_PARAM_FIFO_OFFSET 3 +#define DRM_VMW_PARAM_HW_CAPS 4 +#define DRM_VMW_PARAM_FIFO_CAPS 5 +#define DRM_VMW_PARAM_MAX_FB_SIZE 6 + +/** + * struct drm_vmw_getparam_arg + * + * @value: Returned value. //Out + * @param: Parameter to query. //In. + * + * Argument to the DRM_VMW_GET_PARAM Ioctl. + */ + +struct drm_vmw_getparam_arg { + uint64_t value; + uint32_t param; + uint32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_EXTENSION - Query device extensions. + */ + +/** + * struct drm_vmw_extension_rep + * + * @exists: The queried extension exists. + * @driver_ioctl_offset: Ioctl number of the first ioctl in the extension. + * @driver_sarea_offset: Offset to any space in the DRI SAREA + * used by the extension. + * @major: Major version number of the extension. + * @minor: Minor version number of the extension. + * @pl: Patch level version number of the extension. + * + * Output argument to the DRM_VMW_EXTENSION Ioctl. + */ + +struct drm_vmw_extension_rep { + int32_t exists; + uint32_t driver_ioctl_offset; + uint32_t driver_sarea_offset; + uint32_t major; + uint32_t minor; + uint32_t pl; + uint32_t pad64; +}; + +/** + * union drm_vmw_extension_arg + * + * @extension - Ascii name of the extension to be queried. //In + * @rep - Reply as defined above. //Out + * + * Argument to the DRM_VMW_EXTENSION Ioctl. + */ + +union drm_vmw_extension_arg { + char extension[DRM_VMW_EXT_NAME_LEN]; + struct drm_vmw_extension_rep rep; +}; + +/*************************************************************************/ +/** + * DRM_VMW_CREATE_CONTEXT - Create a host context. + * + * Allocates a device unique context id, and queues a create context command + * for the host. Does not wait for host completion. + */ + +/** + * struct drm_vmw_context_arg + * + * @cid: Device unique context ID. + * + * Output argument to the DRM_VMW_CREATE_CONTEXT Ioctl. + * Input argument to the DRM_VMW_UNREF_CONTEXT Ioctl. + */ + +struct drm_vmw_context_arg { + int32_t cid; + uint32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_UNREF_CONTEXT - Create a host context. + * + * Frees a global context id, and queues a destroy host command for the host. + * Does not wait for host completion. The context ID can be used directly + * in the command stream and shows up as the same context ID on the host. + */ + +/*************************************************************************/ +/** + * DRM_VMW_CREATE_SURFACE - Create a host suface. + * + * Allocates a device unique surface id, and queues a create surface command + * for the host. Does not wait for host completion. The surface ID can be + * used directly in the command stream and shows up as the same surface + * ID on the host. + */ + +/** + * struct drm_wmv_surface_create_req + * + * @flags: Surface flags as understood by the host. + * @format: Surface format as understood by the host. + * @mip_levels: Number of mip levels for each face. + * An unused face should have 0 encoded. + * @size_addr: Address of a user-space array of sruct drm_vmw_size + * cast to an uint64_t for 32-64 bit compatibility. + * The size of the array should equal the total number of mipmap levels. + * @shareable: Boolean whether other clients (as identified by file descriptors) + * may reference this surface. + * @scanout: Boolean whether the surface is intended to be used as a + * scanout. + * + * Input data to the DRM_VMW_CREATE_SURFACE Ioctl. + * Output data from the DRM_VMW_REF_SURFACE Ioctl. + */ + +struct drm_vmw_surface_create_req { + uint32_t flags; + uint32_t format; + uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES]; + uint64_t size_addr; + int32_t shareable; + int32_t scanout; +}; + +/** + * struct drm_wmv_surface_arg + * + * @sid: Surface id of created surface or surface to destroy or reference. + * + * Output data from the DRM_VMW_CREATE_SURFACE Ioctl. + * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl. + * Input argument to the DRM_VMW_REF_SURFACE Ioctl. + */ + +struct drm_vmw_surface_arg { + int32_t sid; + uint32_t pad64; +}; + +/** + * struct drm_vmw_size ioctl. + * + * @width - mip level width + * @height - mip level height + * @depth - mip level depth + * + * Description of a mip level. + * Input data to the DRM_WMW_CREATE_SURFACE Ioctl. + */ + +struct drm_vmw_size { + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t pad64; +}; + +/** + * union drm_vmw_surface_create_arg + * + * @rep: Output data as described above. + * @req: Input data as described above. + * + * Argument to the DRM_VMW_CREATE_SURFACE Ioctl. + */ + +union drm_vmw_surface_create_arg { + struct drm_vmw_surface_arg rep; + struct drm_vmw_surface_create_req req; +}; + +/*************************************************************************/ +/** + * DRM_VMW_REF_SURFACE - Reference a host surface. + * + * Puts a reference on a host surface with a give sid, as previously + * returned by the DRM_VMW_CREATE_SURFACE ioctl. + * A reference will make sure the surface isn't destroyed while we hold + * it and will allow the calling client to use the surface ID in the command + * stream. + * + * On successful return, the Ioctl returns the surface information given + * in the DRM_VMW_CREATE_SURFACE ioctl. + */ + +/** + * union drm_vmw_surface_reference_arg + * + * @rep: Output data as described above. + * @req: Input data as described above. + * + * Argument to the DRM_VMW_REF_SURFACE Ioctl. + */ + +union drm_vmw_surface_reference_arg { + struct drm_vmw_surface_create_req rep; + struct drm_vmw_surface_arg req; +}; + +/*************************************************************************/ +/** + * DRM_VMW_UNREF_SURFACE - Unreference a host surface. + * + * Clear a reference previously put on a host surface. + * When all references are gone, including the one implicitly placed + * on creation, + * a destroy surface command will be queued for the host. + * Does not wait for completion. + */ + +/*************************************************************************/ +/** + * DRM_VMW_EXECBUF + * + * Submit a command buffer for execution on the host, and return a + * fence sequence that when signaled, indicates that the command buffer has + * executed. + */ + +/** + * struct drm_vmw_execbuf_arg + * + * @commands: User-space address of a command buffer cast to an uint64_t. + * @command-size: Size in bytes of the command buffer. + * @throttle-us: Sleep until software is less than @throttle_us + * microseconds ahead of hardware. The driver may round this value + * to the nearest kernel tick. + * @fence_rep: User-space address of a struct drm_vmw_fence_rep cast to an + * uint64_t. + * @version: Allows expanding the execbuf ioctl parameters without breaking + * backwards compatibility, since user-space will always tell the kernel + * which version it uses. + * @flags: Execbuf flags. None currently. + * + * Argument to the DRM_VMW_EXECBUF Ioctl. + */ + +#define DRM_VMW_EXECBUF_VERSION 0 + +struct drm_vmw_execbuf_arg { + uint64_t commands; + uint32_t command_size; + uint32_t throttle_us; + uint64_t fence_rep; + uint32_t version; + uint32_t flags; +}; + +/** + * struct drm_vmw_fence_rep + * + * @fence_seq: Fence sequence associated with a command submission. + * @error: This member should've been set to -EFAULT on submission. + * The following actions should be take on completion: + * error == -EFAULT: Fence communication failed. The host is synchronized. + * Use the last fence id read from the FIFO fence register. + * error != 0 && error != -EFAULT: + * Fence submission failed. The host is synchronized. Use the fence_seq member. + * error == 0: All is OK, The host may not be synchronized. + * Use the fence_seq member. + * + * Input / Output data to the DRM_VMW_EXECBUF Ioctl. + */ + +struct drm_vmw_fence_rep { + uint64_t fence_seq; + int32_t error; + uint32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_ALLOC_DMABUF + * + * Allocate a DMA buffer that is visible also to the host. + * NOTE: The buffer is + * identified by a handle and an offset, which are private to the guest, but + * useable in the command stream. The guest kernel may translate these + * and patch up the command stream accordingly. In the future, the offset may + * be zero at all times, or it may disappear from the interface before it is + * fixed. + * + * The DMA buffer may stay user-space mapped in the guest at all times, + * and is thus suitable for sub-allocation. + * + * DMA buffers are mapped using the mmap() syscall on the drm device. + */ + +/** + * struct drm_vmw_alloc_dmabuf_req + * + * @size: Required minimum size of the buffer. + * + * Input data to the DRM_VMW_ALLOC_DMABUF Ioctl. + */ + +struct drm_vmw_alloc_dmabuf_req { + uint32_t size; + uint32_t pad64; +}; + +/** + * struct drm_vmw_dmabuf_rep + * + * @map_handle: Offset to use in the mmap() call used to map the buffer. + * @handle: Handle unique to this buffer. Used for unreferencing. + * @cur_gmr_id: GMR id to use in the command stream when this buffer is + * referenced. See not above. + * @cur_gmr_offset: Offset to use in the command stream when this buffer is + * referenced. See note above. + * + * Output data from the DRM_VMW_ALLOC_DMABUF Ioctl. + */ + +struct drm_vmw_dmabuf_rep { + uint64_t map_handle; + uint32_t handle; + uint32_t cur_gmr_id; + uint32_t cur_gmr_offset; + uint32_t pad64; +}; + +/** + * union drm_vmw_dmabuf_arg + * + * @req: Input data as described above. + * @rep: Output data as described above. + * + * Argument to the DRM_VMW_ALLOC_DMABUF Ioctl. + */ + +union drm_vmw_alloc_dmabuf_arg { + struct drm_vmw_alloc_dmabuf_req req; + struct drm_vmw_dmabuf_rep rep; +}; + +/*************************************************************************/ +/** + * DRM_VMW_UNREF_DMABUF - Free a DMA buffer. + * + */ + +/** + * struct drm_vmw_unref_dmabuf_arg + * + * @handle: Handle indicating what buffer to free. Obtained from the + * DRM_VMW_ALLOC_DMABUF Ioctl. + * + * Argument to the DRM_VMW_UNREF_DMABUF Ioctl. + */ + +struct drm_vmw_unref_dmabuf_arg { + uint32_t handle; + uint32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_FIFO_DEBUG - Get last FIFO submission. + * + * This IOCTL copies the last FIFO submission directly out of the FIFO buffer. + */ + +/** + * struct drm_vmw_fifo_debug_arg + * + * @debug_buffer: User space address of a debug_buffer cast to an uint64_t //In + * @debug_buffer_size: Size in bytes of debug buffer //In + * @used_size: Number of bytes copied to the buffer // Out + * @did_not_fit: Boolean indicating that the fifo contents did not fit. //Out + * + * Argument to the DRM_VMW_FIFO_DEBUG Ioctl. + */ + +struct drm_vmw_fifo_debug_arg { + uint64_t debug_buffer; + uint32_t debug_buffer_size; + uint32_t used_size; + int32_t did_not_fit; + uint32_t pad64; +}; + +struct drm_vmw_fence_wait_arg { + uint64_t sequence; + uint64_t kernel_cookie; + int32_t cookie_valid; + int32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_CONTROL_STREAM - Control overlays, aka streams. + * + * This IOCTL controls the overlay units of the svga device. + * The SVGA overlay units does not work like regular hardware units in + * that they do not automaticaly read back the contents of the given dma + * buffer. But instead only read back for each call to this ioctl, and + * at any point between this call being made and a following call that + * either changes the buffer or disables the stream. + */ + +/** + * struct drm_vmw_rect + * + * Defines a rectangle. Used in the overlay ioctl to define + * source and destination rectangle. + */ + +struct drm_vmw_rect { + int32_t x; + int32_t y; + uint32_t w; + uint32_t h; +}; + +/** + * struct drm_vmw_control_stream_arg + * + * @stream_id: Stearm to control + * @enabled: If false all following arguments are ignored. + * @handle: Handle to buffer for getting data from. + * @format: Format of the overlay as understood by the host. + * @width: Width of the overlay. + * @height: Height of the overlay. + * @size: Size of the overlay in bytes. + * @pitch: Array of pitches, the two last are only used for YUV12 formats. + * @offset: Offset from start of dma buffer to overlay. + * @src: Source rect, must be within the defined area above. + * @dst: Destination rect, x and y may be negative. + * + * Argument to the DRM_VMW_CONTROL_STREAM Ioctl. + */ + +struct drm_vmw_control_stream_arg { + uint32_t stream_id; + uint32_t enabled; + + uint32_t flags; + uint32_t color_key; + + uint32_t handle; + uint32_t offset; + int32_t format; + uint32_t size; + uint32_t width; + uint32_t height; + uint32_t pitch[3]; + + uint32_t pad64; + struct drm_vmw_rect src; + struct drm_vmw_rect dst; +}; + +/*************************************************************************/ +/** + * DRM_VMW_CURSOR_BYPASS - Give extra information about cursor bypass. + * + */ + +#define DRM_VMW_CURSOR_BYPASS_ALL (1 << 0) +#define DRM_VMW_CURSOR_BYPASS_FLAGS (1) + +/** + * struct drm_vmw_cursor_bypass_arg + * + * @flags: Flags. + * @crtc_id: Crtc id, only used if DMR_CURSOR_BYPASS_ALL isn't passed. + * @xpos: X position of cursor. + * @ypos: Y position of cursor. + * @xhot: X hotspot. + * @yhot: Y hotspot. + * + * Argument to the DRM_VMW_CURSOR_BYPASS Ioctl. + */ + +struct drm_vmw_cursor_bypass_arg { + uint32_t flags; + uint32_t crtc_id; + int32_t xpos; + int32_t ypos; + int32_t xhot; + int32_t yhot; +}; + +/*************************************************************************/ +/** + * DRM_VMW_CLAIM_STREAM - Claim a single stream. + */ + +/** + * struct drm_vmw_context_arg + * + * @stream_id: Device unique context ID. + * + * Output argument to the DRM_VMW_CREATE_CONTEXT Ioctl. + * Input argument to the DRM_VMW_UNREF_CONTEXT Ioctl. + */ + +struct drm_vmw_stream_arg { + uint32_t stream_id; + uint32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_UNREF_STREAM - Unclaim a stream. + * + * Return a single stream that was claimed by this process. Also makes + * sure that the stream has been stopped. + */ + +/*************************************************************************/ +/** + * DRM_VMW_UPDATE_LAYOUT - Update layout + * + * Updates the prefered modes and connection status for connectors. The + * command conisits of one drm_vmw_update_layout_arg pointing out a array + * of num_outputs drm_vmw_rect's. + */ + +/** + * struct drm_vmw_update_layout_arg + * + * @num_outputs: number of active + * @rects: pointer to array of drm_vmw_rect + * + * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl. + */ + +struct drm_vmw_update_layout_arg { + uint32_t num_outputs; + uint32_t pad64; + uint64_t rects; +}; + +#endif diff --git a/vmwgfx/vmwgfx_drmi.c b/vmwgfx/vmwgfx_drmi.c index 3add305..f6b6f0b 100644 --- a/vmwgfx/vmwgfx_drmi.c +++ b/vmwgfx/vmwgfx_drmi.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include "vmwgfx_drm.h" #include #include "vmwgfx_drmi.h" diff --git a/vmwgfx/vmwgfx_overlay.c b/vmwgfx/vmwgfx_overlay.c index 28df983..6624a10 100644 --- a/vmwgfx/vmwgfx_overlay.c +++ b/vmwgfx/vmwgfx_overlay.c @@ -61,7 +61,7 @@ typedef uint8_t uint8; #include #include "xf86drm.h" -#include +#include "vmwgfx_drm.h" #include "vmwgfx_drmi.h" #include "vmwgfx_driver.h" -- cgit v1.2.3 From 3c2f9cc43f7d36952e78d10d224da0ba68ecefea Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 30 Aug 2011 12:22:53 +0200 Subject: vmwgfx-xorg: Avoid enabling unwanted outputs in initial configuration Add a hack so that we avoid enabling all connected outputs during the initial configuration. On older X servers they would be enabled as cloned, which didn't really cause any problem, but on later X servers they would initially be enabled next to eachother which looks odd. A RandR call will still show the disabled outputs as connected, and if there is a monitor section in the config file for the output in question, it will also have a connected status, so that it may be explicitly enabled or disabled from a config file. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_driver.c | 2 ++ vmwgfx/vmwgfx_driver.h | 2 ++ vmwgfx/vmwgfx_output.c | 20 +++++++++++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index 629638e..a682e55 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -426,10 +426,12 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) xorg_crtc_init(pScrn); xorg_output_init(pScrn); + ms->initialization = TRUE; if (!xf86InitialConfiguration(pScrn, TRUE)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); return FALSE; } + ms->initialization = FALSE; /* * If the driver can do gamma correction, it should call xf86SetGamma() here. diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h index cb92bc9..8b3017d 100644 --- a/vmwgfx/vmwgfx_driver.h +++ b/vmwgfx/vmwgfx_driver.h @@ -112,6 +112,8 @@ typedef struct _modesettingRec #ifdef DRI2 Bool dri2_available; #endif + + Bool initialization; } modesettingRec, *modesettingPtr; #define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate)) diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c index 2081f2a..5ec84a1 100644 --- a/vmwgfx/vmwgfx_output.c +++ b/vmwgfx/vmwgfx_output.c @@ -104,7 +104,25 @@ output_detect(xf86OutputPtr output) switch (drm_connector->connection) { case DRM_MODE_CONNECTED: - status = XF86OutputStatusConnected; + /* + * Hack to avoid enabling outputs during the intial + * configuration that are connected but that we don't + * really want to have enabled just yet. + * + * If we are in initial config, and + * an output higher than LVDS1 is connected, + * and it has no monitor section in the config file, + * status will be reported as unknown, which means + * the xorg modesetting code will think it is + * disconnected. + */ + + if (ms->initialization && + drm_connector->connector_type_id != 1 && + !output->conf_monitor) + status = XF86OutputStatusUnknown; + else + status = XF86OutputStatusConnected; break; case DRM_MODE_DISCONNECTED: status = XF86OutputStatusDisconnected; -- cgit v1.2.3 From 5c43481aa639053bbbf7fbf5f72f0edecf616731 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 1 Sep 2011 13:59:10 +0200 Subject: vmwgfx: Adapt to vmwgfx kernel driver 2.1 This introduces fence objects with 2.0, and present / present readback ioctls with 2.1. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_driver.c | 36 +++++- vmwgfx/vmwgfx_driver.h | 7 +- vmwgfx/vmwgfx_drm.h | 313 +++++++++++++++++++++++++++++++++---------------- vmwgfx/vmwgfx_drmi.c | 181 +++++++++++++--------------- vmwgfx/vmwgfx_drmi.h | 6 +- vmwgfx/vmwgfx_saa.c | 6 +- 6 files changed, 335 insertions(+), 214 deletions(-) diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index a682e55..42d33ab 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -60,6 +60,8 @@ #include "vmwgfx_saa.h" #define XA_VERSION_MINOR_REQUIRED 0 +#define DRM_VERSION_MAJOR_REQUIRED 2 +#define DRM_VERSION_MINOR_REQUIRED 1 /* * Some macros to deal with function wrapping. @@ -268,8 +270,22 @@ drv_init_drm(ScrnInfoPtr pScrn) ms->isMaster = TRUE; free(BusID); - if (ms->fd >= 0) + if (ms->fd >= 0) { + drmVersionPtr ver = drmGetVersion(ms->fd); + + if (ver == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not determine DRM version.\n"); + return FALSE; + } + + ms->drm_major = ver->version_major; + ms->drm_minor = ver->version_minor; + ms->drm_patch = ver->version_patchlevel; + + drmFreeVersion(ver); return TRUE; + } return FALSE; } @@ -338,6 +354,22 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) if (!drv_init_drm(pScrn)) return FALSE; + if (ms->drm_major != DRM_VERSION_MAJOR_REQUIRED || + ms->drm_minor < DRM_VERSION_MINOR_REQUIRED) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "DRM driver version is %d.%d.%d\n", + ms->drm_major, ms->drm_minor, ms->drm_patch); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "But this driver needs %d.%d.x to work. Giving up.\n", + DRM_VERSION_MAJOR_REQUIRED, + DRM_VERSION_MINOR_REQUIRED); + return FALSE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "DRM driver version is %d.%d.%d\n", + ms->drm_major, ms->drm_minor, ms->drm_patch); + } + ms->check_fb_size = (vmwgfx_max_fb_size(ms->fd, &ms->max_fb_size) == 0); pScrn->monitor = pScrn->confScreen->monitor; @@ -515,7 +547,7 @@ vmwgfx_scanout_present(ScreenPtr pScreen, int drm_fd, return FALSE; } - if (vmwgfx_present(drm_fd, 0, 0, dirty, handle) != 0) { + if (vmwgfx_present(drm_fd, vpix->fb_id, 0, 0, dirty, handle) != 0) { LogMessage(X_ERROR, "Could not get present surface handle.\n"); return FALSE; } diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h index 8b3017d..c672b62 100644 --- a/vmwgfx/vmwgfx_driver.h +++ b/vmwgfx/vmwgfx_driver.h @@ -74,6 +74,9 @@ typedef struct _modesettingRec { /* drm */ int fd; + int drm_major; + int drm_minor; + int drm_patch; /* X */ EntPtr entityPrivate; @@ -166,10 +169,6 @@ vmw_video_init_adaptor(ScrnInfoPtr pScrn); void vmw_video_free_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports); -int -vmwgfx_present(int drm_fd, unsigned int dst_x, unsigned int dst_y, - RegionPtr region, uint32_t handle); - void vmw_ctrl_ext_init(ScrnInfoPtr pScrn); diff --git a/vmwgfx/vmwgfx_drm.h b/vmwgfx/vmwgfx_drm.h index 650e6bf..bad47a7 100644 --- a/vmwgfx/vmwgfx_drm.h +++ b/vmwgfx/vmwgfx_drm.h @@ -31,7 +31,6 @@ #define DRM_VMW_MAX_SURFACE_FACES 6 #define DRM_VMW_MAX_MIP_LEVELS 24 -#define DRM_VMW_EXT_NAME_LEN 128 #define DRM_VMW_GET_PARAM 0 #define DRM_VMW_ALLOC_DMABUF 1 @@ -48,10 +47,13 @@ #define DRM_VMW_UNREF_SURFACE 10 #define DRM_VMW_REF_SURFACE 11 #define DRM_VMW_EXECBUF 12 -#define DRM_VMW_FIFO_DEBUG 13 +#define DRM_VMW_GET_3D_CAP 13 #define DRM_VMW_FENCE_WAIT 14 -/* guarded by minor version >= 2 */ -#define DRM_VMW_UPDATE_LAYOUT 15 +#define DRM_VMW_FENCE_SIGNALED 15 +#define DRM_VMW_FENCE_UNREF 16 +#define DRM_VMW_FENCE_EVENT 17 +#define DRM_VMW_PRESENT 18 +#define DRM_VMW_PRESENT_READBACK 19 /*************************************************************************/ @@ -69,10 +71,10 @@ #define DRM_VMW_PARAM_NUM_STREAMS 0 #define DRM_VMW_PARAM_NUM_FREE_STREAMS 1 #define DRM_VMW_PARAM_3D 2 -#define DRM_VMW_PARAM_FIFO_OFFSET 3 -#define DRM_VMW_PARAM_HW_CAPS 4 -#define DRM_VMW_PARAM_FIFO_CAPS 5 -#define DRM_VMW_PARAM_MAX_FB_SIZE 6 +#define DRM_VMW_PARAM_HW_CAPS 3 +#define DRM_VMW_PARAM_FIFO_CAPS 4 +#define DRM_VMW_PARAM_MAX_FB_SIZE 5 +#define DRM_VMW_PARAM_FIFO_HW_VERSION 6 /** * struct drm_vmw_getparam_arg @@ -89,49 +91,6 @@ struct drm_vmw_getparam_arg { uint32_t pad64; }; -/*************************************************************************/ -/** - * DRM_VMW_EXTENSION - Query device extensions. - */ - -/** - * struct drm_vmw_extension_rep - * - * @exists: The queried extension exists. - * @driver_ioctl_offset: Ioctl number of the first ioctl in the extension. - * @driver_sarea_offset: Offset to any space in the DRI SAREA - * used by the extension. - * @major: Major version number of the extension. - * @minor: Minor version number of the extension. - * @pl: Patch level version number of the extension. - * - * Output argument to the DRM_VMW_EXTENSION Ioctl. - */ - -struct drm_vmw_extension_rep { - int32_t exists; - uint32_t driver_ioctl_offset; - uint32_t driver_sarea_offset; - uint32_t major; - uint32_t minor; - uint32_t pl; - uint32_t pad64; -}; - -/** - * union drm_vmw_extension_arg - * - * @extension - Ascii name of the extension to be queried. //In - * @rep - Reply as defined above. //Out - * - * Argument to the DRM_VMW_EXTENSION Ioctl. - */ - -union drm_vmw_extension_arg { - char extension[DRM_VMW_EXT_NAME_LEN]; - struct drm_vmw_extension_rep rep; -}; - /*************************************************************************/ /** * DRM_VMW_CREATE_CONTEXT - Create a host context. @@ -292,7 +251,7 @@ union drm_vmw_surface_reference_arg { * DRM_VMW_EXECBUF * * Submit a command buffer for execution on the host, and return a - * fence sequence that when signaled, indicates that the command buffer has + * fence seqno that when signaled, indicates that the command buffer has * executed. */ @@ -314,21 +273,30 @@ union drm_vmw_surface_reference_arg { * Argument to the DRM_VMW_EXECBUF Ioctl. */ -#define DRM_VMW_EXECBUF_VERSION 0 +#define DRM_VMW_EXECBUF_VERSION 1 struct drm_vmw_execbuf_arg { uint64_t commands; uint32_t command_size; uint32_t throttle_us; uint64_t fence_rep; - uint32_t version; - uint32_t flags; + uint32_t version; + uint32_t flags; }; /** * struct drm_vmw_fence_rep * - * @fence_seq: Fence sequence associated with a command submission. + * @handle: Fence object handle for fence associated with a command submission. + * @mask: Fence flags relevant for this fence object. + * @seqno: Fence sequence number in fifo. A fence object with a lower + * seqno will signal the EXEC flag before a fence object with a higher + * seqno. This can be used by user-space to avoid kernel calls to determine + * whether a fence has signaled the EXEC flag. Note that @seqno will + * wrap at 32-bit. + * @passed_seqno: The highest seqno number processed by the hardware + * so far. This can be used to mark user-space fence objects as signaled, and + * to determine whether a fence seqno might be stale. * @error: This member should've been set to -EFAULT on submission. * The following actions should be take on completion: * error == -EFAULT: Fence communication failed. The host is synchronized. @@ -342,9 +310,12 @@ struct drm_vmw_execbuf_arg { */ struct drm_vmw_fence_rep { - uint64_t fence_seq; - int32_t error; + uint32_t handle; + uint32_t mask; + uint32_t seqno; + uint32_t passed_seqno; uint32_t pad64; + int32_t error; }; /*************************************************************************/ @@ -433,39 +404,6 @@ struct drm_vmw_unref_dmabuf_arg { uint32_t pad64; }; -/*************************************************************************/ -/** - * DRM_VMW_FIFO_DEBUG - Get last FIFO submission. - * - * This IOCTL copies the last FIFO submission directly out of the FIFO buffer. - */ - -/** - * struct drm_vmw_fifo_debug_arg - * - * @debug_buffer: User space address of a debug_buffer cast to an uint64_t //In - * @debug_buffer_size: Size in bytes of debug buffer //In - * @used_size: Number of bytes copied to the buffer // Out - * @did_not_fit: Boolean indicating that the fifo contents did not fit. //Out - * - * Argument to the DRM_VMW_FIFO_DEBUG Ioctl. - */ - -struct drm_vmw_fifo_debug_arg { - uint64_t debug_buffer; - uint32_t debug_buffer_size; - uint32_t used_size; - int32_t did_not_fit; - uint32_t pad64; -}; - -struct drm_vmw_fence_wait_arg { - uint64_t sequence; - uint64_t kernel_cookie; - int32_t cookie_valid; - int32_t pad64; -}; - /*************************************************************************/ /** * DRM_VMW_CONTROL_STREAM - Control overlays, aka streams. @@ -590,26 +528,197 @@ struct drm_vmw_stream_arg { /*************************************************************************/ /** - * DRM_VMW_UPDATE_LAYOUT - Update layout + * DRM_VMW_GET_3D_CAP + * + * Read 3D capabilities from the FIFO * - * Updates the prefered modes and connection status for connectors. The - * command conisits of one drm_vmw_update_layout_arg pointing out a array - * of num_outputs drm_vmw_rect's. */ /** - * struct drm_vmw_update_layout_arg + * struct drm_vmw_get_3d_cap_arg * - * @num_outputs: number of active - * @rects: pointer to array of drm_vmw_rect + * @buffer: Pointer to a buffer for capability data, cast to an uint64_t + * @size: Max size to copy * - * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl. + * Input argument to the DRM_VMW_GET_3D_CAP_IOCTL + * ioctls. */ -struct drm_vmw_update_layout_arg { - uint32_t num_outputs; +struct drm_vmw_get_3d_cap_arg { + uint64_t buffer; + uint32_t max_size; uint32_t pad64; - uint64_t rects; }; + +/*************************************************************************/ +/** + * DRM_VMW_FENCE_WAIT + * + * Waits for a fence object to signal. The wait is interruptible, so that + * signals may be delivered during the interrupt. The wait may timeout, + * in which case the calls returns -EBUSY. If the wait is restarted, + * that is restarting without resetting @cookie_valid to zero, + * the timeout is computed from the first call. + * + * The flags argument to the DRM_VMW_FENCE_WAIT ioctl indicates what to wait + * on: + * DRM_VMW_FENCE_FLAG_EXEC: All commands ahead of the fence in the command + * stream + * have executed. + * DRM_VMW_FENCE_FLAG_QUERY: All query results resulting from query finish + * commands + * in the buffer given to the EXECBUF ioctl returning the fence object handle + * are available to user-space. + * + * DRM_VMW_WAIT_OPTION_UNREF: If this wait option is given, and the + * fenc wait ioctl returns 0, the fence object has been unreferenced after + * the wait. + */ + +#define DRM_VMW_FENCE_FLAG_EXEC (1 << 0) +#define DRM_VMW_FENCE_FLAG_QUERY (1 << 1) + +#define DRM_VMW_WAIT_OPTION_UNREF (1 << 0) + +/** + * struct drm_vmw_fence_wait_arg + * + * @handle: Fence object handle as returned by the DRM_VMW_EXECBUF ioctl. + * @cookie_valid: Must be reset to 0 on first call. Left alone on restart. + * @kernel_cookie: Set to 0 on first call. Left alone on restart. + * @timeout_us: Wait timeout in microseconds. 0 for indefinite timeout. + * @lazy: Set to 1 if timing is not critical. Allow more than a kernel tick + * before returning. + * @flags: Fence flags to wait on. + * @wait_options: Options that control the behaviour of the wait ioctl. + * + * Input argument to the DRM_VMW_FENCE_WAIT ioctl. + */ + +struct drm_vmw_fence_wait_arg { + uint32_t handle; + int32_t cookie_valid; + uint64_t kernel_cookie; + uint64_t timeout_us; + int32_t lazy; + int32_t flags; + int32_t wait_options; + int32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_FENCE_SIGNALED + * + * Checks if a fence object is signaled.. + */ + +/** + * struct drm_vmw_fence_signaled_arg + * + * @handle: Fence object handle as returned by the DRM_VMW_EXECBUF ioctl. + * @flags: Fence object flags input to DRM_VMW_FENCE_SIGNALED ioctl + * @signaled: Out: Flags signaled. + * @sequence: Out: Highest sequence passed so far. Can be used to signal the + * EXEC flag of user-space fence objects. + * + * Input/Output argument to the DRM_VMW_FENCE_SIGNALED and DRM_VMW_FENCE_UNREF + * ioctls. + */ + +struct drm_vmw_fence_signaled_arg { + uint32_t handle; + uint32_t flags; + int32_t signaled; + uint32_t passed_seqno; + uint32_t signaled_flags; + uint32_t pad64; +}; + +/*************************************************************************/ +/** + * DRM_VMW_FENCE_UNREF + * + * Unreferences a fence object, and causes it to be destroyed if there are no + * other references to it. + * + */ + +/** + * struct drm_vmw_fence_arg + * + * @handle: Fence object handle as returned by the DRM_VMW_EXECBUF ioctl. + * + * Input/Output argument to the DRM_VMW_FENCE_UNREF ioctl.. + */ + +struct drm_vmw_fence_arg { + uint32_t handle; + uint32_t pad64; +}; + + +/*************************************************************************/ +/** + * DRM_VMW_PRESENT + * + * Executes an SVGA present on a given fb for a given surface. The surface + * is placed on the framebuffer. Cliprects are given relative to the given + * point (the point disignated by dest_{x|y}). + * + */ + +/** + * struct drm_vmw_present_arg + * @fb_id: framebuffer id to present / read back from. + * @sid: Surface id to present from. + * @dest_x: X placement coordinate for surface. + * @dest_y: Y placement coordinate for surface. + * @clips_ptr: Pointer to an array of clip rects cast to an uint64_t. + * @num_clips: Number of cliprects given relative to the framebuffer origin, + * in the same coordinate space as the frame buffer. + * @pad64: Unused 64-bit padding. + * + * Input argument to the DRM_VMW_PRESENT ioctl. + */ + +struct drm_vmw_present_arg { + uint32_t fb_id; + uint32_t sid; + int32_t dest_x; + int32_t dest_y; + uint64_t clips_ptr; + uint32_t num_clips; + uint32_t pad64; +}; + + +/*************************************************************************/ +/** + * DRM_VMW_PRESENT_READBACK + * + * Executes an SVGA present readback from a given fb to the dma buffer + * currently bound as the fb. If there is no dma buffer bound to the fb, + * an error will be returned. + * + */ + +/** + * struct drm_vmw_present_arg + * @fb_id: fb_id to present / read back from. + * @num_clips: Number of cliprects. + * @clips_ptr: Pointer to an array of clip rects cast to an uint64_t. + * @fence_rep: Pointer to a struct drm_vmw_fence_rep, cast to an uint64_t. + * If this member is NULL, then the ioctl should not return a fence. + */ + +struct drm_vmw_present_readback_arg { + uint32_t fb_id; + uint32_t num_clips; + uint64_t clips_ptr; + uint64_t fence_rep; +}; + + #endif diff --git a/vmwgfx/vmwgfx_drmi.c b/vmwgfx/vmwgfx_drmi.c index f6b6f0b..44904a7 100644 --- a/vmwgfx/vmwgfx_drmi.c +++ b/vmwgfx/vmwgfx_drmi.c @@ -46,151 +46,138 @@ #include "vmwgfx_driver.h" static int -vmwgfx_fence_wait(int drm_fd, uint64_t seq) +vmwgfx_fence_wait(int drm_fd, uint32_t handle, Bool unref) { struct drm_vmw_fence_wait_arg farg; memset(&farg, 0, sizeof(farg)); - farg.sequence = seq; + farg.handle = handle; + farg.flags = DRM_VMW_FENCE_FLAG_EXEC; + farg.timeout_us = 10*1000000; farg.cookie_valid = 0; + if (unref) + farg.wait_options |= DRM_VMW_WAIT_OPTION_UNREF; + return drmCommandWriteRead(drm_fd, DRM_VMW_FENCE_WAIT, &farg, sizeof(farg)); } +static void +vmwgfx_fence_unref(int drm_fd, uint32_t handle) +{ + struct drm_vmw_fence_arg farg; + memset(&farg, 0, sizeof(farg)); + + farg.handle = handle; + + (void) drmCommandWrite(drm_fd, DRM_VMW_FENCE_UNREF, &farg, + sizeof(farg)); +} + + int -vmwgfx_present_readback(int drm_fd, RegionPtr region) +vmwgfx_present_readback(int drm_fd, uint32_t fb_id, RegionPtr region) { BoxPtr clips = REGION_RECTS(region); unsigned int num_clips = REGION_NUM_RECTS(region); - struct drm_vmw_execbuf_arg arg; struct drm_vmw_fence_rep rep; + struct drm_vmw_present_readback_arg arg; int ret; - unsigned int size; unsigned i; - SVGA3dRect *cr; - - struct { - SVGA3dCmdHeader header; - SVGA3dRect cr; - } *cmd; + struct drm_vmw_rect *rects, *r; - if (num_clips == 0) - return 0; - - size = sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr); - cmd = malloc(size); - if (!cmd) + rects = calloc(num_clips, sizeof(*rects)); + if (!rects) { + LogMessage(X_ERROR, "Failed to alloc cliprects for " + "present readback.\n"); return -1; - - cmd->header.id = SVGA_3D_CMD_PRESENT_READBACK; - cmd->header.size = num_clips * sizeof(cmd->cr); - - for (i=0, cr = &cmd->cr; i < num_clips; i++, cr++, clips++) { - cr->x = (uint16_t) clips->x1; - cr->y = (uint16_t) clips->y1; - cr->w = (uint16_t) (clips->x2 - clips->x1); - cr->h = (uint16_t) (clips->y2 - clips->y1); -#if 0 - LogMessage(X_INFO, - "Readback x: %u y: %u srcx: %u srcy: %u w: %u h: %u\n", - cr->x, cr->y, cr->x, cr->y, cr->w, cr->h); -#endif } - memset(&arg, 0, sizeof(arg)); memset(&rep, 0, sizeof(rep)); + arg.fb_id = fb_id; + arg.num_clips = num_clips; + arg.clips_ptr = (unsigned long) rects; + arg.fence_rep = (unsigned long) &rep; rep.error = -EFAULT; - arg.fence_rep = (unsigned long)&rep; - arg.commands = (unsigned long)cmd; - arg.command_size = size; - arg.throttle_us = 0; - ret = drmCommandWrite(drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg)); + for (i = 0, r = rects; i < num_clips; ++i, ++r, ++clips) { + r->x = clips->x1; + r->y = clips->y1; + r->w = clips->x2 - clips->x1; + r->h = clips->y2 - clips->y1; + } + + ret = drmCommandWrite(drm_fd, DRM_VMW_PRESENT_READBACK, &arg, sizeof(arg)); if (ret) LogMessage(X_ERROR, "Present readback error %s.\n", strerror(-ret)); - - free(cmd); + free(rects); /* * Sync to avoid racing with Xorg SW rendering. */ if (rep.error == 0) { - ret = vmwgfx_fence_wait(drm_fd, rep.fence_seq); - if (ret) + ret = vmwgfx_fence_wait(drm_fd, rep.handle, TRUE); + if (ret) { LogMessage(X_ERROR, "Present readback fence wait error %s.\n", strerror(-ret)); + vmwgfx_fence_unref(drm_fd, rep.handle); + } } return 0; } + int -vmwgfx_present(int drm_fd, unsigned int dst_x, unsigned int dst_y, - RegionPtr region, uint32_t handle) +vmwgfx_present(int drm_fd, uint32_t fb_id, unsigned int dst_x, + unsigned int dst_y, RegionPtr region, uint32_t handle) { BoxPtr clips = REGION_RECTS(region); unsigned int num_clips = REGION_NUM_RECTS(region); - struct drm_vmw_execbuf_arg arg; - struct drm_vmw_fence_rep rep; + struct drm_vmw_present_arg arg; + unsigned int i; + struct drm_vmw_rect *rects, *r; int ret; - unsigned int size; - unsigned i; - SVGA3dCopyRect *cr; - - struct { - SVGA3dCmdHeader header; - SVGA3dCmdPresent body; - SVGA3dCopyRect cr; - } *cmd; if (num_clips == 0) return 0; - size = sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr); - cmd = malloc(size); - if (!cmd) + rects = calloc(num_clips, sizeof(*rects)); + if (!rects) { + LogMessage(X_ERROR, "Failed to alloc cliprects for " + "present.\n"); return -1; - - cmd->header.id = SVGA_3D_CMD_PRESENT; - cmd->header.size = sizeof(cmd->body) + num_clips * sizeof(cmd->cr); - cmd->body.sid = handle; - - - for (i=0, cr = &cmd->cr; i < num_clips; i++, cr++, clips++) { - cr->x = (uint16_t) clips->x1 + dst_x; - cr->y = (uint16_t) clips->y1 + dst_y; - cr->srcx = (uint16_t) clips->x1; - cr->srcy = (uint16_t) clips->y1; - cr->w = (uint16_t) (clips->x2 - clips->x1); - cr->h = (uint16_t) (clips->y2 - clips->y1); -#if 0 - LogMessage(X_INFO, "Present: x: %u y: %u srcx: %u srcy: %u w: %u h: %u\n", - cr->x, cr->y, cr->srcx, cr->srcy, cr->w, cr->h); -#endif } memset(&arg, 0, sizeof(arg)); - memset(&rep, 0, sizeof(rep)); - - rep.error = -EFAULT; - arg.fence_rep = (unsigned long)&rep; - arg.commands = (unsigned long)cmd; - arg.command_size = size; - arg.throttle_us = 0; + arg.fb_id = fb_id; + arg.sid = handle; + arg.dest_x = dst_x; + arg.dest_y = dst_y; + arg.num_clips = num_clips; + arg.clips_ptr = (unsigned long) rects; + + for (i = 0, r = rects; i < num_clips; ++i, ++r, ++clips) { + r->x = clips->x1; + r->y = clips->y1; + r->w = clips->x2 - clips->x1; + r->h = clips->y2 - clips->y1; + } - ret = drmCommandWrite(drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg)); + ret = drmCommandWrite(drm_fd, DRM_VMW_PRESENT, &arg, sizeof(arg)); if (ret) { LogMessage(X_ERROR, "Present error %s.\n", strerror(-ret)); } - free(cmd); - return 0; + free(rects); + return ((ret != 0) ? -1 : 0); } + struct vmwgfx_int_dmabuf { struct vmwgfx_dmabuf buf; uint64_t map_handle; @@ -374,10 +361,11 @@ vmwgfx_dma(unsigned int host_x, unsigned int host_y, memset(&rep, 0, sizeof(rep)); rep.error = -EFAULT; - arg.fence_rep = (unsigned long)&rep; + arg.fence_rep = ((to_surface) ? 0UL : (unsigned long)&rep); arg.commands = (unsigned long)cmd; arg.command_size = size; arg.throttle_us = 0; + arg.version = DRM_VMW_EXECBUF_VERSION; ret = drmCommandWrite(ibuf->drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg)); if (ret) { @@ -386,11 +374,13 @@ vmwgfx_dma(unsigned int host_x, unsigned int host_y, free(cmd); - if (!to_surface && rep.error == 0) { - ret = vmwgfx_fence_wait(ibuf->drm_fd, rep.fence_seq); - if (ret) + if (rep.error == 0) { + ret = vmwgfx_fence_wait(ibuf->drm_fd, rep.handle, TRUE); + if (ret) { LogMessage(X_ERROR, "DMA from host fence wait error %s.\n", strerror(-ret)); + vmwgfx_fence_unref(ibuf->drm_fd, rep.handle); + } } return 0; @@ -485,23 +475,12 @@ vmwgfx_cursor_bypass(int drm_fd, int xhot, int yhot) int vmwgfx_max_fb_size(int drm_fd, size_t *size) { - drmVersionPtr ver; - int ret = -1; uint64_t tmp_size; - ver = drmGetVersion(drm_fd); - if (ver == NULL || - !(ver->version_major > 1 || - (ver->version_major == 1 && ver->version_minor >= 3))) - goto out; - if (vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_MAX_FB_SIZE, &tmp_size) != 0) - goto out; + return -1; *size = tmp_size; - ret = 0; - out: - drmFreeVersion(ver); - return ret; + return 0; } diff --git a/vmwgfx/vmwgfx_drmi.h b/vmwgfx/vmwgfx_drmi.h index 0c92719..ba4c440 100644 --- a/vmwgfx/vmwgfx_drmi.h +++ b/vmwgfx/vmwgfx_drmi.h @@ -36,11 +36,11 @@ struct vmwgfx_dma_ctx; extern int -vmwgfx_present_readback(int drm_fd, RegionPtr region); +vmwgfx_present_readback(int drm_fd, uint32_t fb_id, RegionPtr region); extern int -vmwgfx_present(int drm_fd, unsigned int dst_x, unsigned int dst_y, - RegionPtr region, uint32_t handle); +vmwgfx_present(int drm_fd, uint32_t fb_id, unsigned int dst_x, + unsigned int dst_y, RegionPtr region, uint32_t handle); struct vmwgfx_dmabuf { uint32_t handle; diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 41cea13..b0c8301 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -264,7 +264,8 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa, REGION_INTERSECT(vsaa->pScreen, &screen_intersection, &screen_intersection, &intersection); - if (vmwgfx_present_readback(vsaa->drm_fd, &intersection) != 0) + if (vmwgfx_present_readback(vsaa->drm_fd, vpix->fb_id, + &intersection) != 0) goto out_readback_err; REGION_SUBTRACT(vsaa->pScreen, &intersection, &intersection, @@ -926,7 +927,8 @@ vmwgfx_present_done(struct vmwgfx_saa *vsaa) if (!vsaa->diff_valid) return; - (void) vmwgfx_present(vsaa->drm_fd, vsaa->xdiff, vsaa->ydiff, + (void) vmwgfx_present(vsaa->drm_fd, dst_vpix->fb_id, + vsaa->xdiff, vsaa->ydiff, &vsaa->present_region, vsaa->src_handle); REGION_TRANSLATE(pScreen, &vsaa->present_region, vsaa->xdiff, vsaa->ydiff); -- cgit v1.2.3 From a33710b0d16c9c01a1995b60f0b0d4d482f459d3 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 21 Oct 2011 11:19:36 +0200 Subject: vmwgfx: Save the dri2 requested depth since it may differ from the drawable depth. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_dri2.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index 5cffc4d..b3fb1e8 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -48,6 +48,7 @@ typedef struct { int refcount; PixmapPtr pPixmap; struct xa_surface *srf; + unsigned int dri2_depth; } *BufferPrivatePtr; @@ -114,6 +115,7 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for return FALSE; private->pPixmap = pPixmap; + private->dri2_depth = depth; vpix = vmwgfx_saa_pixmap(pPixmap); } break; @@ -127,6 +129,7 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for buffer->flags = 0; /* not tiled */ buffer->format = pDraw->bitsPerPixel; if (!private->pPixmap) { + private->dri2_depth = 0; private->pPixmap = pPixmap; pPixmap->refcnt++; } @@ -146,6 +149,8 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for if (!srf) return FALSE; + private->dri2_depth = depth; + break; case DRI2BufferDepth: depth = (format) ? vmwgfx_z_format_to_depth(format) : @@ -156,6 +161,9 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for XA_FLAG_SHARED); if (!srf) return FALSE; + + private->dri2_depth = depth; + break; } @@ -179,6 +187,7 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for vpix->hw_is_dri2_fronts++; private->refcount++; + private->dri2_depth = depth; } private->srf = srf; @@ -303,8 +312,9 @@ dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, /* pixmap glXWaitX */ if (pSrcBuffer->attachment == DRI2BufferFrontLeft && pDestBuffer->attachment == DRI2BufferFakeFrontLeft) { - - if (!vmwgfx_hw_dri2_validate(src_priv->pPixmap, 0)) + + if (!vmwgfx_hw_dri2_validate(dst_priv->pPixmap, + dst_priv->dri2_depth)) return; } /* pixmap glXWaitGL */ -- cgit v1.2.3 From c73a7f3d991dd95d332829f2ca8a88aabfea5a46 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 26 Oct 2011 07:28:31 +0200 Subject: vmwgfx: Update the connector type name array Also map connector types that are not in the array to "Unknown". Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_output.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c index 5ec84a1..d0f238d 100644 --- a/vmwgfx/vmwgfx_output.c +++ b/vmwgfx/vmwgfx_output.c @@ -72,6 +72,9 @@ static char *output_enum_list[] = { "DP", "HDMI", "HDMI", + "TV", + "EDP", + "Virtual", }; static void @@ -110,7 +113,7 @@ output_detect(xf86OutputPtr output) * really want to have enabled just yet. * * If we are in initial config, and - * an output higher than LVDS1 is connected, + * an output higher than Virtual1 is connected, * and it has no monitor section in the config file, * status will be reported as unknown, which means * the xorg modesetting code will think it is @@ -276,6 +279,10 @@ xorg_output_init(ScrnInfoPtr pScrn) (void)v; #endif + if (drm_connector->connector_type >= + sizeof(output_enum_list) / sizeof(output_enum_list[0])) + drm_connector->connector_type = 0; + snprintf(name, 32, "%s%d", output_enum_list[drm_connector->connector_type], drm_connector->connector_type_id); -- cgit v1.2.3 From 55113dae7cbe99bfb69869831536ff34ed445c73 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 26 Oct 2011 15:08:18 +0200 Subject: vmwgfx: Hook up vmwarectrl to the gui layout ioctl Requires drm 2.3. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_ctrl.c | 26 +++++++++---------- vmwgfx/vmwgfx_driver.c | 2 +- vmwgfx/vmwgfx_drm.h | 70 +++++++++++++++++++++++++++++++++++++++++++++++++- vmwgfx/vmwgfx_drmi.c | 16 ++++++++++++ vmwgfx/vmwgfx_drmi.h | 4 +++ 5 files changed, 102 insertions(+), 16 deletions(-) diff --git a/vmwgfx/vmwgfx_ctrl.c b/vmwgfx/vmwgfx_ctrl.c index 5157f86..3185879 100644 --- a/vmwgfx/vmwgfx_ctrl.c +++ b/vmwgfx/vmwgfx_ctrl.c @@ -39,9 +39,8 @@ #include #include "vmwarectrlproto.h" -#include "xf86drm.h" #include "vmwgfx_driver.h" - +#include "vmwgfx_drmi.h" /* *---------------------------------------------------------------------------- @@ -110,17 +109,17 @@ VMwareCtrlDoSetRes(ScrnInfoPtr pScrn, CARD32 x, CARD32 y) { -#if 0 - struct vmw_rect rect; + modesettingPtr ms = modesettingPTR(pScrn); + struct drm_vmw_rect rect; + int ret; + rect.x = 0; rect.y = 0; rect.w = x; rect.h = y; - vmw_ioctl_update_layout(vmw, 1, &rect); -#endif - - return TRUE; + ret = vmwgfx_update_gui_layout(ms->fd, 1, &rect); + return (ret == 0); } @@ -208,10 +207,10 @@ VMwareCtrlDoSetTopology(ScrnInfoPtr pScrn, xXineramaScreenInfo *extents, unsigned long number) { -#if 0 - struct vmw_rect *rects; - struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn)); + modesettingPtr ms = modesettingPTR(pScrn); + struct drm_vmw_rect *rects; int i; + int ret; rects = calloc(number, sizeof(*rects)); if (!rects) @@ -224,11 +223,10 @@ VMwareCtrlDoSetTopology(ScrnInfoPtr pScrn, rects[i].h = extents[i].height; } - vmw_ioctl_update_layout(vmw, number, rects); + ret = vmwgfx_update_gui_layout(ms->fd, number, rects); free(rects); -#endif - return TRUE; + return (ret == 0); } diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index 42d33ab..1b02a7b 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -61,7 +61,7 @@ #define XA_VERSION_MINOR_REQUIRED 0 #define DRM_VERSION_MAJOR_REQUIRED 2 -#define DRM_VERSION_MINOR_REQUIRED 1 +#define DRM_VERSION_MINOR_REQUIRED 3 /* * Some macros to deal with function wrapping. diff --git a/vmwgfx/vmwgfx_drm.h b/vmwgfx/vmwgfx_drm.h index bad47a7..f10f09e 100644 --- a/vmwgfx/vmwgfx_drm.h +++ b/vmwgfx/vmwgfx_drm.h @@ -27,6 +27,7 @@ #ifndef __VMWGFX_DRM_H__ #define __VMWGFX_DRM_H__ +#include #define DRM_VMW_MAX_SURFACE_FACES 6 #define DRM_VMW_MAX_MIP_LEVELS 24 @@ -54,7 +55,7 @@ #define DRM_VMW_FENCE_EVENT 17 #define DRM_VMW_PRESENT 18 #define DRM_VMW_PRESENT_READBACK 19 - +#define DRM_VMW_UPDATE_LAYOUT 20 /*************************************************************************/ /** @@ -659,6 +660,51 @@ struct drm_vmw_fence_arg { }; +/*************************************************************************/ +/** + * DRM_VMW_FENCE_EVENT + * + * Queues an event on a fence to be delivered on the drm character device + * when the fence has signaled the DRM_VMW_FENCE_FLAG_EXEC flag. + * Optionally the approximate time when the fence signaled is + * given by the event. + */ + +/* + * The event type + */ +#define DRM_VMW_EVENT_FENCE_SIGNALED 0x80000000 + +struct drm_vmw_event_fence { + struct drm_event base; + uint64_t user_data; + uint32_t tv_sec; + uint32_t tv_usec; +}; + +/* + * Flags that may be given to the command. + */ +/* Request fence signaled time on the event. */ +#define DRM_VMW_FE_FLAG_REQ_TIME (1 << 0) + +/** + * struct drm_vmw_fence_event_arg + * + * @fence_rep: Pointer to fence_rep structure cast to uint64_t or 0 if + * the fence is not supposed to be referenced by user-space. + * @user_info: Info to be delivered with the event. + * @handle: Attach the event to this fence only. + * @flags: A set of flags as defined above. + */ +struct drm_vmw_fence_event_arg { + uint64_t fence_rep; + uint64_t user_data; + uint32_t handle; + uint32_t flags; +}; + + /*************************************************************************/ /** * DRM_VMW_PRESENT @@ -720,5 +766,27 @@ struct drm_vmw_present_readback_arg { uint64_t fence_rep; }; +/*************************************************************************/ +/** + * DRM_VMW_UPDATE_LAYOUT - Update layout + * + * Updates the preferred modes and connection status for connectors. The + * command consists of one drm_vmw_update_layout_arg pointing to an array + * of num_outputs drm_vmw_rect's. + */ + +/** + * struct drm_vmw_update_layout_arg + * + * @num_outputs: number of active connectors + * @rects: pointer to array of drm_vmw_rect cast to an uint64_t + * + * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl. + */ +struct drm_vmw_update_layout_arg { + uint32_t num_outputs; + uint32_t pad64; + uint64_t rects; +}; #endif diff --git a/vmwgfx/vmwgfx_drmi.c b/vmwgfx/vmwgfx_drmi.c index 44904a7..cc595ab 100644 --- a/vmwgfx/vmwgfx_drmi.c +++ b/vmwgfx/vmwgfx_drmi.c @@ -472,6 +472,22 @@ vmwgfx_cursor_bypass(int drm_fd, int xhot, int yhot) return ret; } +int +vmwgfx_update_gui_layout(int drm_fd, unsigned int num_rects, + struct drm_vmw_rect *rects) +{ + struct drm_vmw_update_layout_arg arg; + + memset(&arg, 0, sizeof(arg)); + + arg.num_outputs = num_rects; + arg.rects = (unsigned long) rects; + + return drmCommandWrite(drm_fd, DRM_VMW_UPDATE_LAYOUT, &arg, + sizeof(arg)); +} + + int vmwgfx_max_fb_size(int drm_fd, size_t *size) { diff --git a/vmwgfx/vmwgfx_drmi.h b/vmwgfx/vmwgfx_drmi.h index ba4c440..11abf25 100644 --- a/vmwgfx/vmwgfx_drmi.h +++ b/vmwgfx/vmwgfx_drmi.h @@ -32,6 +32,7 @@ #include #include #include +#include "vmwgfx_drm.h" struct vmwgfx_dma_ctx; @@ -78,4 +79,7 @@ vmwgfx_cursor_bypass(int drm_fd, int xhot, int yhot); int vmwgfx_max_fb_size(int drm_fd, size_t *size); +int +vmwgfx_update_gui_layout(int drm_fd, unsigned int num_rects, + struct drm_vmw_rect *rects); #endif -- cgit v1.2.3 From 427064b57c52c8881c7a64d9c9e21411e79e644b Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 26 Oct 2011 16:33:30 +0200 Subject: vmwgfx: Fix crtc position of transformed fb The fb allocated for transformed data always matches the scanout region, so set the crtc origin to (0,0) Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_crtc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vmwgfx/vmwgfx_crtc.c b/vmwgfx/vmwgfx_crtc.c index 8f8ced4..13ca7e5 100644 --- a/vmwgfx/vmwgfx_crtc.c +++ b/vmwgfx/vmwgfx_crtc.c @@ -180,9 +180,11 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, if (!xf86CrtcRotate(crtc)) return FALSE; - if (crtc->transform_in_use && crtc->rotatedData) + if (crtc->transform_in_use && crtc->rotatedData) { + x = 0; + y = 0; pixmap = (PixmapPtr) crtc->rotatedData; - else + } else pixmap = pScreen->GetScreenPixmap(pScreen); if (crtcp->box.pixmap != pixmap) { -- cgit v1.2.3 From cc7c1c961b77c139b95fbb6948204def1b4b908a Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 31 Oct 2011 10:50:09 +0100 Subject: vmwgfx: Fall back to sw cursors if needed If there is a risc that we need two simultaneous cursors, (two outputs showing the same contents, at least one of them explicit), fall back to sw cursor. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_driver.c | 84 +++++++++++++++++++++++++++++++++++++++- vmwgfx/vmwgfx_driver.h | 5 +++ vmwgfx/vmwgfx_output.c | 102 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 180 insertions(+), 11 deletions(-) diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index 1b02a7b..c1938a5 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -671,6 +671,86 @@ drv_set_master(ScrnInfoPtr pScrn) return TRUE; } +/** + * vmwgfx_use_hw_cursor_argb - wrapper around hw argb cursor check. + * + * screen: Pointer to the current screen metadata. + * cursor: Pointer to the current cursor metadata. + * + * In addition to the default test, also check whether we might be + * needing more than one hw cursor (which we don't support). + */ +static Bool +vmwgfx_use_hw_cursor_argb(ScreenPtr screen, CursorPtr cursor) +{ + ScrnInfoPtr pScrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; + modesettingPtr ms = modesettingPTR(pScrn); + Bool ret; + + vmwgfx_swap(ms, cursor_info, UseHWCursorARGB); + ret = cursor_info->UseHWCursorARGB(screen, cursor); + vmwgfx_swap(ms, cursor_info, UseHWCursorARGB); + if (!ret) + return FALSE; + + /* + * If there is a chance we might need two cursors, + * revert to sw cursor. + */ + return !vmwgfx_output_explicit_overlap(pScrn); +} + +/** + * vmwgfx_use_hw_cursor - wrapper around hw cursor check. + * + * screen: Pointer to the current screen metadata. + * cursor: Pointer to the current cursor metadata. + * + * In addition to the default test, also check whether we might be + * needing more than one hw cursor (which we don't support). + */ +static Bool +vmwgfx_use_hw_cursor(ScreenPtr screen, CursorPtr cursor) +{ + ScrnInfoPtr pScrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; + modesettingPtr ms = modesettingPTR(pScrn); + Bool ret; + + vmwgfx_swap(ms, cursor_info, UseHWCursor); + ret = cursor_info->UseHWCursor(screen, cursor); + vmwgfx_swap(ms, cursor_info, UseHWCursor); + if (!ret) + return FALSE; + + /* + * If there is a chance we might need two simultaneous cursors, + * revert to sw cursor. + */ + return !vmwgfx_output_explicit_overlap(pScrn); +} + +/** + * vmwgfx_wrap_use_hw_cursor - Wrap functions that check for hw cursor + * support. + * + * pScrn: Pointer to current screen info. + * + * Enables the device-specific hw cursor support check functions. + */ +static void vmwgfx_wrap_use_hw_cursor(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; + modesettingPtr ms = modesettingPTR(pScrn); + + vmwgfx_wrap(ms, cursor_info, UseHWCursor, vmwgfx_use_hw_cursor); + vmwgfx_wrap(ms, cursor_info, UseHWCursorARGB, vmwgfx_use_hw_cursor_argb); +} + static void drv_load_palette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual) @@ -865,11 +945,13 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); /* Need to extend HWcursor support to handle mask interleave */ - if (!ms->SWCursor) + if (!ms->SWCursor) { xf86_cursors_init(pScreen, 64, 64, HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | HARDWARE_CURSOR_ARGB | HARDWARE_CURSOR_UPDATE_UNHIDDEN); + vmwgfx_wrap_use_hw_cursor(pScrn); + } /* Must force it before EnterVT, so we are in control of VT and * later memory should be bound when allocating, e.g rotate_mem */ diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h index c672b62..da07a73 100644 --- a/vmwgfx/vmwgfx_driver.h +++ b/vmwgfx/vmwgfx_driver.h @@ -105,6 +105,8 @@ typedef struct _modesettingRec Bool (*saved_EnterVT)(int, int); void (*saved_LeaveVT)(int, int); void (*saved_AdjustFrame)(int, int, int, int); + Bool (*saved_UseHWCursor)(ScreenPtr, CursorPtr); + Bool (*saved_UseHWCursorARGB)(ScreenPtr, CursorPtr); uint16_t lut_r[256], lut_g[256], lut_b[256]; @@ -157,6 +159,9 @@ xorg_output_init(ScrnInfoPtr pScrn); unsigned xorg_output_get_id(xf86OutputPtr output); +Bool +vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn); + /*********************************************************************** * xorg_xv.c diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c index d0f238d..1a0835d 100644 --- a/vmwgfx/vmwgfx_output.c +++ b/vmwgfx/vmwgfx_output.c @@ -56,6 +56,8 @@ struct output_private drmModeConnectorPtr drm_connector; int c; + + Bool is_implicit; }; static char *output_enum_list[] = { @@ -237,6 +239,75 @@ static const xf86OutputFuncsRec output_funcs = { .destroy = output_destroy, }; +/** + * vmwgfx_output_explicit_overlap -- Check for explicit output overlaps + * + * This function returns TRUE iff the bounding box in screen space of an + * exlplicit output overlaps the bounding box in screen space of any other + * output. + */ +Bool +vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; + ScreenPtr pScreen = pScrn->pScreen; + RegionRec output_union; + RegionRec cur_output; + RegionRec result; + struct output_private *priv; + xf86CrtcPtr crtc; + Bool overlap = FALSE; + int i; + + (void) pScreen; + REGION_NULL(pScreen, &output_union); + REGION_NULL(pScreen, &cur_output); + REGION_NULL(pScreen, &result); + + /* + * Collect a region of implicit outputs. These may overlap. + */ + for (i = 0; i < config->num_output; i++) { + output = config->output[i]; + priv = output->driver_private; + crtc = output->crtc; + + if (!crtc || !crtc->enabled || !priv->is_implicit) + continue; + + REGION_RESET(pScreen, &cur_output, &crtc->bounds); + REGION_UNION(pScreen, &output_union, &output_union, &cur_output); + } + + /* + * Explicit outputs may not overlap any other output. + */ + for (i = 0; i < config->num_output; i++) { + output = config->output[i]; + priv = output->driver_private; + crtc = output->crtc; + + if (!crtc || !crtc->enabled || priv->is_implicit) + continue; + + REGION_RESET(pScreen, &cur_output, &crtc->bounds); + REGION_NULL(pScreen, &result); + REGION_INTERSECT(pScreen, &result, &output_union, &cur_output); + overlap = REGION_NOTEMPTY(vsaa->pScreen, &result); + if (overlap) + break; + + REGION_UNION(pScreen, &output_union, &output_union, &cur_output); + } + + REGION_UNINIT(pScreen, &output_union); + REGION_UNINIT(pScreen, &cur_output); + REGION_UNINIT(pScreen, &result); + + return overlap; +} + void xorg_output_init(ScrnInfoPtr pScrn) { @@ -247,7 +318,7 @@ xorg_output_init(ScrnInfoPtr pScrn) drmModeEncoderPtr drm_encoder = NULL; struct output_private *priv; char name[32]; - int c, v, p; + int c, p; res = drmModeGetResources(ms->fd); if (res == 0) { @@ -256,28 +327,37 @@ xorg_output_init(ScrnInfoPtr pScrn) } for (c = 0; c < res->count_connectors; c++) { + Bool is_implicit = TRUE; + drm_connector = drmModeGetConnector(ms->fd, res->connectors[c]); if (!drm_connector) goto out; -#if 0 + for (p = 0; p < drm_connector->count_props; p++) { drmModePropertyPtr prop; prop = drmModeGetProperty(ms->fd, drm_connector->props[p]); - name = NULL; if (prop) { - ErrorF("VALUES %d\n", prop->count_values); - for (v = 0; v < prop->count_values; v++) - ErrorF("%s %lld\n", prop->name, prop->values[v]); +#if 0 + /* + * Disabled until we sort out what the interface should + * look like. + */ + + if (strcmp(prop->name, "implicit placement") == 0) { + drmModeConnectorSetProperty(ms->fd, + drm_connector->connector_id, + prop->prop_id, + 0); + is_implicit = FALSE; + } +#endif + drmModeFreeProperty(prop); } } -#else - (void)p; - (void)v; -#endif if (drm_connector->connector_type >= sizeof(output_enum_list) / sizeof(output_enum_list[0])) @@ -299,6 +379,8 @@ xorg_output_init(ScrnInfoPtr pScrn) continue; } + priv->is_implicit = is_implicit; + drm_encoder = drmModeGetEncoder(ms->fd, drm_connector->encoders[0]); if (drm_encoder) { output->possible_crtcs = drm_encoder->possible_crtcs; -- cgit v1.2.3 From b6faecc7613e8c73f0681d20a1a80e5e0ddd4058 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 31 Oct 2011 14:27:29 +0100 Subject: vmwgfx: Don't do present readbacks per crtc The kernel now takes care of doing this the right way; no need to duplicate that functionality. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_crtc.c | 33 +++++++++++++-------------------- vmwgfx/vmwgfx_saa.c | 50 +++++++++++++------------------------------------- vmwgfx/vmwgfx_saa.h | 7 +++---- 3 files changed, 29 insertions(+), 61 deletions(-) diff --git a/vmwgfx/vmwgfx_crtc.c b/vmwgfx/vmwgfx_crtc.c index 13ca7e5..eaf87b2 100644 --- a/vmwgfx/vmwgfx_crtc.c +++ b/vmwgfx/vmwgfx_crtc.c @@ -62,7 +62,7 @@ struct crtc_private unsigned cursor_handle; /* Scanout info for pixmaps */ - struct vmwgfx_screen_box box; + struct vmwgfx_screen_entry entry; }; static void @@ -89,8 +89,8 @@ crtc_dpms(xf86CrtcPtr crtc, int mode) * the crtc may be turned on again by * another dpms call, so don't release the scanout pixmap ref. */ - if (!crtc->enabled && crtcp->box.pixmap) { - vmwgfx_scanout_unref(&crtcp->box); + if (!crtc->enabled && crtcp->entry.pixmap) { + vmwgfx_scanout_unref(&crtcp->entry); } break; } @@ -134,7 +134,6 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, int i, ret; unsigned int connector_id; PixmapPtr pixmap; - BoxPtr screen_box; for (i = 0; i < config->num_output; output = NULL, i++) { output = config->output[i]; @@ -187,12 +186,12 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, } else pixmap = pScreen->GetScreenPixmap(pScreen); - if (crtcp->box.pixmap != pixmap) { - if (crtcp->box.pixmap) - vmwgfx_scanout_unref(&crtcp->box); + if (crtcp->entry.pixmap != pixmap) { + if (crtcp->entry.pixmap) + vmwgfx_scanout_unref(&crtcp->entry); - crtcp->box.pixmap = pixmap; - crtcp->scanout_id = vmwgfx_scanout_ref(&crtcp->box); + crtcp->entry.pixmap = pixmap; + crtcp->scanout_id = vmwgfx_scanout_ref(&crtcp->entry); if (crtcp->scanout_id == -1) { LogMessage(X_ERROR, "Failed to convert pixmap to scanout.\n"); return FALSE; @@ -203,12 +202,6 @@ crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, if (ret) return FALSE; - screen_box = &crtcp->box.box; - screen_box->x1 = crtc->x; - screen_box->y1 = crtc->y; - screen_box->x2 = screen_box->x1 + mode->HDisplay; - screen_box->y2 = screen_box->y1 + mode->VDisplay; - vmwgfx_scanout_refresh(pixmap); /* Only set gamma when needed, to avoid unneeded delays. */ @@ -380,8 +373,8 @@ crtc_destroy(xf86CrtcPtr crtc) { struct crtc_private *crtcp = crtc->driver_private; - if (!WSBMLISTEMPTY(&crtcp->box.scanout_head)) - vmwgfx_scanout_unref(&crtcp->box); + if (!WSBMLISTEMPTY(&crtcp->entry.scanout_head)) + vmwgfx_scanout_unref(&crtcp->entry); xorg_crtc_cursor_destroy(crtc); @@ -442,8 +435,8 @@ xorg_crtc_init(ScrnInfoPtr pScrn) } crtcp->drm_crtc = drm_crtc; - crtcp->box.pixmap = NULL; - WSBMINITLISTHEAD(&crtcp->box.scanout_head); + crtcp->entry.pixmap = NULL; + WSBMINITLISTHEAD(&crtcp->entry.scanout_head); crtc->driver_private = crtcp; } @@ -456,7 +449,7 @@ PixmapPtr crtc_get_scanout(xf86CrtcPtr crtc) { struct crtc_private *crtcp = crtc->driver_private; - return crtcp->box.pixmap; + return crtcp->entry.pixmap; } /* vim: set sw=4 ts=8 sts=4: */ diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index b0c8301..4638ef0 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -220,8 +220,6 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa, struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); RegionRec intersection; - RegionRec screen_intersection; - struct _WsbmListHead *list; if (!spix->damage || !REGION_NOTEMPTY(vsaa->pScreen, &spix->dirty_hw) || !vpix->dirty_present) @@ -249,38 +247,16 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa, if (!vmwgfx_pixmap_create_gmr(vsaa, pixmap)) goto out_err; - /* - * Readback regions are not allowed to cross screen boundaries, so - * loop over all scanouts and make sure all readback calls are completely - * contained within a scanout bounding box. - */ - - REGION_NULL(vsaa->pScreen, &screen_intersection); - WSBMLISTFOREACH(list, &vpix->scanout_list) { - struct vmwgfx_screen_box *box = - WSBMLISTENTRY(list, struct vmwgfx_screen_box, scanout_head); - - REGION_RESET(vsaa->pScreen, &screen_intersection, &box->box); - REGION_INTERSECT(vsaa->pScreen, &screen_intersection, - &screen_intersection, &intersection); - - if (vmwgfx_present_readback(vsaa->drm_fd, vpix->fb_id, - &intersection) != 0) - goto out_readback_err; - - REGION_SUBTRACT(vsaa->pScreen, &intersection, &intersection, - &screen_intersection); - REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_hw, - &spix->dirty_hw, &screen_intersection); - } + if (vmwgfx_present_readback(vsaa->drm_fd, vpix->fb_id, + &intersection) != 0) + goto out_err; - REGION_UNINIT(vsaa->pScreen, &screen_intersection); + REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_hw, + &spix->dirty_hw, &intersection); out: REGION_UNINIT(vsaa->pScreen, &intersection); return TRUE; - out_readback_err: - REGION_UNINIT(vsaa->pScreen, &screen_intersection); out_err: REGION_UNINIT(vsaa->pScreen, &intersection); return FALSE; @@ -1367,9 +1343,9 @@ vmwgfx_scanout_refresh(PixmapPtr pixmap) */ uint32_t -vmwgfx_scanout_ref(struct vmwgfx_screen_box *box) +vmwgfx_scanout_ref(struct vmwgfx_screen_entry *entry) { - PixmapPtr pixmap = box->pixmap; + PixmapPtr pixmap = entry->pixmap; struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); @@ -1389,14 +1365,14 @@ vmwgfx_scanout_ref(struct vmwgfx_screen_box *box) vpix->gmr->handle, &vpix->fb_id); if (ret) { - box->pixmap = NULL; + entry->pixmap = NULL; vpix->fb_id = -1; goto out_err; } } pixmap->refcnt += 1; - WSBMLISTADDTAIL(&box->scanout_head, &vpix->scanout_list); + WSBMLISTADDTAIL(&entry->scanout_head, &vpix->scanout_list); out_err: return vpix->fb_id; @@ -1408,18 +1384,18 @@ vmwgfx_scanout_ref(struct vmwgfx_screen_box *box) * damage tracking and kms fbs. */ void -vmwgfx_scanout_unref(struct vmwgfx_screen_box *box) +vmwgfx_scanout_unref(struct vmwgfx_screen_entry *entry) { struct vmwgfx_saa *vsaa; struct vmwgfx_saa_pixmap *vpix; - PixmapPtr pixmap = box->pixmap; + PixmapPtr pixmap = entry->pixmap; if (!pixmap) return; vsaa = to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); vpix = vmwgfx_saa_pixmap(pixmap); - WSBMLISTDELINIT(&box->scanout_head); + WSBMLISTDELINIT(&entry->scanout_head); if (WSBMLISTEMPTY(&vpix->scanout_list)) { REGION_EMPTY(vsaa->pScreen, vpix->pending_update); @@ -1430,6 +1406,6 @@ vmwgfx_scanout_unref(struct vmwgfx_screen_box *box) vmwgfx_pixmap_remove_damage(pixmap); } - box->pixmap = NULL; + entry->pixmap = NULL; pixmap->drawable.pScreen->DestroyPixmap(pixmap); } diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h index 41c6de3..30eeacc 100644 --- a/vmwgfx/vmwgfx_saa.h +++ b/vmwgfx/vmwgfx_saa.h @@ -61,8 +61,7 @@ struct vmwgfx_saa_pixmap { enum xa_formats staging_format; }; -struct vmwgfx_screen_box { - BoxRec box; +struct vmwgfx_screen_entry { struct _WsbmListHead scanout_head; PixmapPtr pixmap; }; @@ -84,10 +83,10 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, void (*present_flush)(ScreenPtr pScreen)); extern uint32_t -vmwgfx_scanout_ref(struct vmwgfx_screen_box *box); +vmwgfx_scanout_ref(struct vmwgfx_screen_entry *box); extern void -vmwgfx_scanout_unref(struct vmwgfx_screen_box *box); +vmwgfx_scanout_unref(struct vmwgfx_screen_entry *box); extern void vmwgfx_scanout_refresh(PixmapPtr pixmap); -- cgit v1.2.3 From da85719e9e373ee8da53388cccc71a0f9c8bbefc Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 31 Oct 2011 14:40:55 +0100 Subject: vmwgfx: Remove a couple of unused options Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Reviewed-by: Alan Hourihane --- vmwgfx/vmwgfx_driver.c | 10 ---------- vmwgfx/vmwgfx_driver.h | 1 - 2 files changed, 11 deletions(-) diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index c1938a5..7c8c9fb 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -105,18 +105,12 @@ typedef enum { OPTION_SW_CURSOR, OPTION_2D_ACCEL, - OPTION_DEBUG_FALLBACK, - OPTION_THROTTLE_SWAP, - OPTION_THROTTLE_DIRTY, OPTION_3D_ACCEL } drv_option_enums; static const OptionInfoRec drv_options[] = { {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_2D_ACCEL, "2DAccel", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_DEBUG_FALLBACK, "DebugFallback", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_THROTTLE_SWAP, "SwapThrottling", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_THROTTLE_DIRTY, "DirtyThrottling", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_3D_ACCEL, "3DAccel", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; @@ -869,8 +863,6 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86SetBlackWhitePixels(pScreen); ms->accelerate_2d = xf86ReturnOptValBool(ms->Options, OPTION_2D_ACCEL, FALSE); - ms->debug_fallback = xf86ReturnOptValBool(ms->Options, OPTION_DEBUG_FALLBACK, ms->accelerate_2d); - vmw_ctrl_ext_init(pScrn); ms->xat = xa_tracker_create(ms->fd); @@ -930,8 +922,6 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using libkms backend.\n"); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D Acceleration is %s.\n", ms->accelerate_2d ? "enabled" : "disabled"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Fallback debugging is %s.\n", - ms->debug_fallback ? "enabled" : "disabled"); #ifdef DRI2 xf86DrvMsg(pScrn->scrnIndex, ms->from_3D, "3D Acceleration is disabled.\n"); #else diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h index da07a73..bb52d09 100644 --- a/vmwgfx/vmwgfx_driver.h +++ b/vmwgfx/vmwgfx_driver.h @@ -87,7 +87,6 @@ typedef struct _modesettingRec /* Accel */ Bool accelerate_2d; - Bool debug_fallback; Bool noAccel; Bool SWCursor; -- cgit v1.2.3 From b2c4a7e682e14fa8af42415d429d6735117fefcb Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 31 Oct 2011 15:14:21 +0100 Subject: vmwgfx: Fix acceleration options. Introduce relevant acceleration options and fix up the log printout. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Reviewed-by: Alan Hourihane --- vmwgfx/vmwgfx_driver.c | 117 ++++++++++++++++++++++++++----------------------- vmwgfx/vmwgfx_driver.h | 9 ++-- 2 files changed, 65 insertions(+), 61 deletions(-) diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index 7c8c9fb..132c617 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -104,14 +104,14 @@ extern const OptionInfoRec * xorg_tracker_available_options(int chipid, typedef enum { OPTION_SW_CURSOR, - OPTION_2D_ACCEL, - OPTION_3D_ACCEL + OPTION_RENDER_ACCEL, + OPTION_DRI } drv_option_enums; static const OptionInfoRec drv_options[] = { {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_2D_ACCEL, "2DAccel", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_3D_ACCEL, "3DAccel", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; @@ -295,7 +295,6 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) rgb defaultWeight = { 0, 0, 0 }; EntityInfoPtr pEnt; EntPtr msEnt = NULL; - Bool use3D; if (pScrn->numEntities != 1) return FALSE; @@ -401,12 +400,15 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) memcpy(ms->Options, drv_options, sizeof(drv_options)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options); - use3D = TRUE; - ms->from_3D = xf86GetOptValBool(ms->Options, OPTION_3D_ACCEL, - &use3D) ? + ms->accelerate_render = TRUE; + ms->from_render = xf86GetOptValBool(ms->Options, OPTION_RENDER_ACCEL, + &ms->accelerate_render) ? X_CONFIG : X_PROBED; - ms->no3D = !use3D; + ms->enable_dri = ms->accelerate_render; + ms->from_dri = xf86GetOptValBool(ms->Options, OPTION_DRI, + &ms->enable_dri) ? + X_CONFIG : X_PROBED; /* Allocate an xf86CrtcConfig */ xf86CrtcConfigInit(pScrn, &crtc_config_funcs); @@ -862,42 +864,47 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86SetBlackWhitePixels(pScreen); - ms->accelerate_2d = xf86ReturnOptValBool(ms->Options, OPTION_2D_ACCEL, FALSE); vmw_ctrl_ext_init(pScrn); - ms->xat = xa_tracker_create(ms->fd); - if (!ms->xat) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to initialize Gallium3D Xa. No 3D available.\n"); - else { - int major, minor, patch; - - xa_tracker_version(&major, &minor, &patch); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Gallium3D XA version: %d.%d.%d.\n", - major, minor, patch); - - if (XA_TRACKER_VERSION_MAJOR == 0) { - if (minor != XA_TRACKER_VERSION_MINOR) { + if (ms->accelerate_render) { + ms->xat = xa_tracker_create(ms->fd); + if (!ms->xat) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to initialize Gallium3D Xa. " + "No render acceleration available.\n"); + ms->from_render = X_PROBED; + } else { + int major, minor, patch; + + xa_tracker_version(&major, &minor, &patch); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Gallium3D XA version: %d.%d.%d.\n", + major, minor, patch); + + if (XA_TRACKER_VERSION_MAJOR == 0) { + if (minor != XA_TRACKER_VERSION_MINOR) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Expecting XA version 0.%d.x.\n", + XA_TRACKER_VERSION_MINOR); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No render acceleration available.\n"); + xa_tracker_destroy(ms->xat); + ms->xat = NULL; + ms->from_render = X_PROBED; + } + } else if (major != XA_TRACKER_VERSION_MAJOR || + minor < XA_VERSION_MINOR_REQUIRED) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Expecting XA version 0.%d.x.\n", - XA_TRACKER_VERSION_MINOR); + "Expecting %d.%d.x >= XA version < %d.0.0.\n", + XA_TRACKER_VERSION_MAJOR, + XA_VERSION_MINOR_REQUIRED, + XA_TRACKER_VERSION_MAJOR + 1); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "No 3D available.\n"); + "No render acceleration available.\n"); xa_tracker_destroy(ms->xat); ms->xat = NULL; + ms->from_render = X_PROBED; } - } else if (major != XA_TRACKER_VERSION_MAJOR || - minor < XA_VERSION_MINOR_REQUIRED) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Expecting %d.%d.x >= XA version < %d.0.0.\n", - XA_TRACKER_VERSION_MAJOR, - XA_VERSION_MINOR_REQUIRED, - XA_TRACKER_VERSION_MAJOR + 1); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "No 3D available.\n"); - xa_tracker_destroy(ms->xat); - ms->xat = NULL; } } @@ -907,27 +914,25 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #ifdef DRI2 ms->dri2_available = FALSE; - if (ms->xat) { - ms->dri2_available = xorg_dri2_init(pScreen); - if (!ms->dri2_available) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to initialize DRI2. " - "No direct rendring available.\n"); + if (ms->enable_dri) { + if (ms->xat) { + ms->dri2_available = xorg_dri2_init(pScreen); + if (!ms->dri2_available) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to initialize direct rendering.\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Skipped initialization of direct rendering due " + "to lack of render acceleration.\n"); + ms->from_dri = X_PROBED; + } } #endif - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "#################################\n"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "# Useful debugging info follows #\n"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "#################################\n"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using libkms backend.\n"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D Acceleration is %s.\n", - ms->accelerate_2d ? "enabled" : "disabled"); -#ifdef DRI2 - xf86DrvMsg(pScrn->scrnIndex, ms->from_3D, "3D Acceleration is disabled.\n"); -#else - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D Acceleration is disabled.\n"); -#endif - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n"); + xf86DrvMsg(pScrn->scrnIndex, ms->from_render, "Render acceleration is %s.\n", + (ms->xat != NULL) ? "enabled" : "disabled"); + xf86DrvMsg(pScrn->scrnIndex, ms->from_dri, "Direct rendering (3D) is %s.\n", + (ms->dri2_available) ? "enabled" : "disabled"); miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h index bb52d09..fd750ca 100644 --- a/vmwgfx/vmwgfx_driver.h +++ b/vmwgfx/vmwgfx_driver.h @@ -86,13 +86,12 @@ typedef struct _modesettingRec struct pci_device *PciInfo; /* Accel */ - Bool accelerate_2d; - - Bool noAccel; + Bool accelerate_render; + Bool from_render; Bool SWCursor; CursorPtr cursor; - Bool no3D; - Bool from_3D; + Bool enable_dri; + Bool from_dri; Bool isMaster; /* Broken-out options. */ -- cgit v1.2.3 From ed7bba3cda4b454eec771d3bf0ebed4fd998a82a Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 1 Nov 2011 08:38:52 +0100 Subject: vmwgfx: Add an option for direct presents With this option set to true, accelerated copies to a scanout pixmap will be performed as hardware presents instead of copies to an intermediate 3D surface backing the scanout pixmap, followed by a present. Depending on the application this might be a performance boost, but since it might trigger device software readbacks in other situations, for example dri2 copy front->fake_front, it might be a performance hog in other situations, so disable it by default. (Before this commit it was enabled by default). Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_driver.c | 16 ++++++++++++++-- vmwgfx/vmwgfx_driver.h | 3 +++ vmwgfx/vmwgfx_saa.c | 5 +++-- vmwgfx/vmwgfx_saa.h | 3 ++- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index 132c617..4ac829f 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -105,13 +105,15 @@ typedef enum { OPTION_SW_CURSOR, OPTION_RENDER_ACCEL, - OPTION_DRI + OPTION_DRI, + OPTION_DIRECT_PRESENTS, } drv_option_enums; static const OptionInfoRec drv_options[] = { {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_DIRECT_PRESENTS, "DirectPresents", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; @@ -410,6 +412,11 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) &ms->enable_dri) ? X_CONFIG : X_PROBED; + ms->direct_presents = FALSE; + ms->from_dp = xf86GetOptValBool(ms->Options, OPTION_DIRECT_PRESENTS, + &ms->direct_presents) ? + X_CONFIG : X_DEFAULT; + /* Allocate an xf86CrtcConfig */ xf86CrtcConfigInit(pScrn, &crtc_config_funcs); xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); @@ -908,7 +915,8 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } } - if (!vmwgfx_saa_init(pScreen, ms->fd, ms->xat, &xorg_flush)) { + if (!vmwgfx_saa_init(pScreen, ms->fd, ms->xat, &xorg_flush, + ms->direct_presents)) { FatalError("Failed to initialize SAA.\n"); } @@ -933,6 +941,10 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) (ms->xat != NULL) ? "enabled" : "disabled"); xf86DrvMsg(pScrn->scrnIndex, ms->from_dri, "Direct rendering (3D) is %s.\n", (ms->dri2_available) ? "enabled" : "disabled"); + if (ms->xat != NULL) { + xf86DrvMsg(pScrn->scrnIndex, ms->from_dp, "Direct presents are %s.\n", + (ms->direct_presents) ? "enabled" : "disabled"); + } miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h index fd750ca..a88fa82 100644 --- a/vmwgfx/vmwgfx_driver.h +++ b/vmwgfx/vmwgfx_driver.h @@ -92,8 +92,11 @@ typedef struct _modesettingRec CursorPtr cursor; Bool enable_dri; Bool from_dri; + Bool direct_presents; + Bool from_dp; Bool isMaster; + /* Broken-out options. */ OptionInfoPtr Options; diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 4638ef0..66c6cfc 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -1270,7 +1270,8 @@ static const struct saa_driver vmwgfx_saa_driver = { Bool vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, - void (*present_flush)(ScreenPtr pScreen)) + void (*present_flush)(ScreenPtr pScreen), + Bool direct_presents) { struct vmwgfx_saa *vsaa; @@ -1285,7 +1286,7 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, vsaa->drm_fd = drm_fd; vsaa->present_flush = present_flush; vsaa->can_optimize_dma = FALSE; - vsaa->use_present_opt = TRUE; + vsaa->use_present_opt = direct_presents; vsaa->only_hw_presents = FALSE; WSBMINITLISTHEAD(&vsaa->sync_x_list); diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h index 30eeacc..1fd06b6 100644 --- a/vmwgfx/vmwgfx_saa.h +++ b/vmwgfx/vmwgfx_saa.h @@ -80,7 +80,8 @@ vmwgfx_saa_pixmap(PixmapPtr pix) extern Bool vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, - void (*present_flush)(ScreenPtr pScreen)); + void (*present_flush)(ScreenPtr pScreen), + Bool direct_presents); extern uint32_t vmwgfx_scanout_ref(struct vmwgfx_screen_entry *box); -- cgit v1.2.3 From 5137e8736edfab1aaebef4046baab37361584b2e Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 1 Nov 2011 09:59:18 +0100 Subject: vmwgfx: Be correct when setting up damage tracking When setting up damage tracking, previously the code would guess wether sw or hw was currently dirty. The caller always have that information, so pass it to the damage tracking setup function. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_saa.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 66c6cfc..50b9fe6 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -35,7 +35,7 @@ #include "vmwgfx_saa_priv.h" static Bool -vmwgfx_pixmap_add_damage(PixmapPtr pixmap) +vmwgfx_pixmap_add_damage(PixmapPtr pixmap, Bool dirty_as_hw) { struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); @@ -53,7 +53,7 @@ vmwgfx_pixmap_add_damage(PixmapPtr pixmap) box.y1 = 0; box.y2 = draw->height; - if (vpix->hw) { + if (dirty_as_hw && vpix->hw) { REGION_INIT(draw->pScreen, &spix->dirty_hw, &box, 1); } else { REGION_INIT(draw->pScreen, &spix->dirty_shadow, &box, 1); @@ -114,7 +114,14 @@ vmwgfx_pixmap_add_present(PixmapPtr pixmap, Bool present_opt) vpix->pending_present = REGION_CREATE(pScreen, NULL, 0); if (!vpix->pending_present) goto out_no_pending_present; - if (!vmwgfx_pixmap_add_damage(pixmap)) + + /* + * We're not creating new storage here, so if there isn't already + * a damage tracker attached, there is either only sw storage or + * only hw storage, and we use that fact to determine where to put + * the initial dirty region. + */ + if (!vmwgfx_pixmap_add_damage(pixmap, vpix->hw != NULL)) goto out_no_damage; return TRUE; @@ -172,7 +179,7 @@ vmwgfx_pixmap_create_gmr(struct vmwgfx_saa *vsaa, PixmapPtr pixmap) memcpy(addr, vpix->malloc, size); vmwgfx_dmabuf_unmap(gmr); - } else if (vpix->hw && !vmwgfx_pixmap_add_damage(pixmap)) + } else if (vpix->hw && !vmwgfx_pixmap_add_damage(pixmap, TRUE)) goto out_no_transfer; vpix->backing |= VMWGFX_PIX_GMR; @@ -198,11 +205,20 @@ vmwgfx_pixmap_create_sw(struct vmwgfx_saa *vsaa, PixmapPtr pixmap) if (!vpix->malloc && (vpix->backing & VMWGFX_PIX_MALLOC)) { vpix->malloc = malloc(pixmap->devKind * pixmap->drawable.height); - return (vpix->malloc != NULL); + if (!vpix->malloc) + goto out_no_malloc; + if (!vmwgfx_pixmap_add_damage(pixmap, TRUE)) + goto out_no_damage; } else if (vpix->backing & VMWGFX_PIX_GMR) return vmwgfx_pixmap_create_gmr(vsaa, pixmap); return TRUE; + + out_no_damage: + free(vpix->malloc); + vpix->malloc = NULL; + out_no_malloc: + return FALSE; } @@ -624,7 +640,6 @@ vmwgfx_modify_pixmap_header (PixmapPtr pixmap, int w, int h, int depth, vpix->backing = VMWGFX_PIX_MALLOC; vmwgfx_pix_resize(pixmap, old_pitch, old_height, old_width); - vmwgfx_pixmap_add_damage(pixmap); vmwgfx_pixmap_free_storage(vpix); return TRUE; @@ -728,7 +743,7 @@ vmwgfx_create_hw(struct vmwgfx_saa *vsaa, vpix->xa_flags = new_flags; - if ((vpix->gmr || vpix->malloc) && !vmwgfx_pixmap_add_damage(pixmap)) + if ((vpix->gmr || vpix->malloc) && !vmwgfx_pixmap_add_damage(pixmap, FALSE)) goto out_no_damage; /* -- cgit v1.2.3 From aff799d007c8383321213ad177e5a9deec2b3978 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 1 Nov 2011 15:39:07 +0100 Subject: vmwgfx: Add an option to use a scanout surface With this option enabled, we compose all contents (both sw and hw) in the guest before presenting it. Just like the old xorg state tracker did when 3D was enabled. It's not as bad as the old xorg state tracker was for interactivity, but there's a small but noticeable lag when moving windows. It's mainly intended for testing purposes, like testing the surface dirty paths in the kernel module. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_driver.c | 34 ++++++++++++++++---- vmwgfx/vmwgfx_driver.h | 2 ++ vmwgfx/vmwgfx_saa.c | 87 +++++++++++++++++++++++++++++++++++--------------- vmwgfx/vmwgfx_saa.h | 3 +- 4 files changed, 93 insertions(+), 33 deletions(-) diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index 4ac829f..0504c2d 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -107,6 +107,7 @@ typedef enum OPTION_RENDER_ACCEL, OPTION_DRI, OPTION_DIRECT_PRESENTS, + OPTION_HW_PRESENTS } drv_option_enums; static const OptionInfoRec drv_options[] = { @@ -114,6 +115,7 @@ static const OptionInfoRec drv_options[] = { {OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_DIRECT_PRESENTS, "DirectPresents", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_HW_PRESENTS, "HWPresents", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; @@ -417,6 +419,11 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) &ms->direct_presents) ? X_CONFIG : X_DEFAULT; + ms->only_hw_presents = FALSE; + ms->from_hwp = xf86GetOptValBool(ms->Options, OPTION_HW_PRESENTS, + &ms->only_hw_presents) ? + X_CONFIG : X_DEFAULT; + /* Allocate an xf86CrtcConfig */ xf86CrtcConfigInit(pScrn, &crtc_config_funcs); xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); @@ -551,7 +558,7 @@ vmwgfx_scanout_present(ScreenPtr pScreen, int drm_fd, } if (vmwgfx_present(drm_fd, vpix->fb_id, 0, 0, dirty, handle) != 0) { - LogMessage(X_ERROR, "Could not get present surface handle.\n"); + LogMessage(X_ERROR, "Failed present kernel call.\n"); return FALSE; } @@ -610,13 +617,24 @@ void xorg_flush(ScreenPtr pScreen) if (vpix->fb_id != -1) { if (vpix->pending_update) { - (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id, - vpix->pending_update); + if (ms->only_hw_presents && + REGION_NOTEMPTY(pscreen, vpix->pending_update)) { + (void) vmwgfx_hw_accel_validate(pixmap, 0, XA_FLAG_SCANOUT, + 0, NULL); + REGION_UNION(pScreen, vpix->pending_present, + vpix->pending_present, vpix->pending_update); + } else + (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id, + vpix->pending_update); REGION_EMPTY(pScreen, vpix->pending_update); } if (vpix->pending_present) { - (void) vmwgfx_scanout_present(pScreen, ms->fd, vpix, - vpix->pending_present); + if (ms->only_hw_presents) + (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id, + vpix->pending_present); + else + (void) vmwgfx_scanout_present(pScreen, ms->fd, vpix, + vpix->pending_present); REGION_EMPTY(pScreen, vpix->pending_present); } } @@ -916,7 +934,8 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } if (!vmwgfx_saa_init(pScreen, ms->fd, ms->xat, &xorg_flush, - ms->direct_presents)) { + ms->direct_presents, + ms->only_hw_presents)) { FatalError("Failed to initialize SAA.\n"); } @@ -944,6 +963,9 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (ms->xat != NULL) { xf86DrvMsg(pScrn->scrnIndex, ms->from_dp, "Direct presents are %s.\n", (ms->direct_presents) ? "enabled" : "disabled"); + xf86DrvMsg(pScrn->scrnIndex, ms->from_hwp, "Hardware only presents " + "are %s.\n", + (ms->only_hw_presents) ? "enabled" : "disabled"); } miInitializeBackingStore(pScreen); diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h index a88fa82..d0d4e52 100644 --- a/vmwgfx/vmwgfx_driver.h +++ b/vmwgfx/vmwgfx_driver.h @@ -94,6 +94,8 @@ typedef struct _modesettingRec Bool from_dri; Bool direct_presents; Bool from_dp; + Bool only_hw_presents; + Bool from_hwp; Bool isMaster; diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 50b9fe6..bd90b3d 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -1194,19 +1194,22 @@ vmwgfx_dirty(struct saa_driver *driver, PixmapPtr pixmap, if (WSBMLISTEMPTY(&vpix->scanout_list)) return TRUE; +#if 0 + /* + * This code can be enabled to immediately upload scanout sw + * contents to the hw surface. Otherwise this is done + * just before we call the kms update function for the hw + * surface. + */ if (vsaa->only_hw_presents) { - if (!vpix->hw) { - if (!vmwgfx_hw_accel_stage(pixmap, 0, XA_FLAG_RENDER_TARGET, 0)) - return FALSE; - if (!vmwgfx_hw_commit(pixmap)) - return FALSE; - } if (!hw && !vmwgfx_upload_to_hw(&vsaa->driver, pixmap, damage)) return FALSE; + REGION_SUBTRACT(&vsaa->pScreen, &spix->dirty_shadow, &spix->dirty_shadow, damage); hw = TRUE; } +#endif /* * Is the new scanout damage hw or sw? @@ -1286,7 +1289,8 @@ static const struct saa_driver vmwgfx_saa_driver = { Bool vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, void (*present_flush)(ScreenPtr pScreen), - Bool direct_presents) + Bool direct_presents, + Bool only_hw_presents) { struct vmwgfx_saa *vsaa; @@ -1294,6 +1298,11 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, if (!vsaa) return FALSE; + if (xat == NULL) { + direct_presents = FALSE; + only_hw_presents = FALSE; + } + vsaa->pScreen = pScreen; vsaa->xat = xat; if (xat) @@ -1302,7 +1311,7 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, vsaa->present_flush = present_flush; vsaa->can_optimize_dma = FALSE; vsaa->use_present_opt = direct_presents; - vsaa->only_hw_presents = FALSE; + vsaa->only_hw_presents = only_hw_presents; WSBMINITLISTHEAD(&vsaa->sync_x_list); vsaa->driver = vmwgfx_saa_driver; @@ -1365,33 +1374,59 @@ vmwgfx_scanout_ref(struct vmwgfx_screen_entry *entry) struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen)); struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); - int ret; if (WSBMLISTEMPTY(&vpix->scanout_list)) { - ret = !vmwgfx_pixmap_create_gmr(vsaa, pixmap); - if (!ret) - ret = !vmwgfx_pixmap_add_present(pixmap, vsaa->use_present_opt); - if (!ret) - ret = drmModeAddFB(vsaa->drm_fd, - pixmap->drawable.width, - pixmap->drawable.height, - pixmap->drawable.depth, - pixmap->drawable.bitsPerPixel, - pixmap->devKind, - vpix->gmr->handle, - &vpix->fb_id); - if (ret) { - entry->pixmap = NULL; - vpix->fb_id = -1; - goto out_err; + uint32_t handle, dummy; + unsigned int depth; + + if (vsaa->only_hw_presents) { + /* + * The KMS fb will be a HW surface. Create it, add damage + * and get the handle. + */ + if (!vmwgfx_hw_accel_validate(pixmap, 0, XA_FLAG_SCANOUT, 0, NULL)) + goto out_err; + if (xa_surface_handle(vpix->hw, &handle, &dummy) != 0) + goto out_err; + depth = xa_format_depth(xa_surface_format(vpix->hw)); + + } else { + /* + * The KMS fb will be a Guest Memory Region. Create it, + * add damage and get the handle. + */ + if (!vmwgfx_pixmap_create_gmr(vsaa, pixmap)) + goto out_err; + + handle = vpix->gmr->handle; + depth = pixmap->drawable.depth; + } + if (!vmwgfx_pixmap_add_present(pixmap, vsaa->use_present_opt)) + goto out_no_present; + + if (drmModeAddFB(vsaa->drm_fd, + pixmap->drawable.width, + pixmap->drawable.height, + depth, + pixmap->drawable.bitsPerPixel, + pixmap->devKind, + handle, + &vpix->fb_id) != 0) + goto out_no_fb;; } pixmap->refcnt += 1; WSBMLISTADDTAIL(&entry->scanout_head, &vpix->scanout_list); + return vpix->fb_id; + out_no_fb: + vmwgfx_pixmap_remove_present(vpix); + out_no_present: + vmwgfx_pixmap_remove_damage(pixmap); out_err: - return vpix->fb_id; + vpix->fb_id = -1; + return -1; } /* diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h index 1fd06b6..1276768 100644 --- a/vmwgfx/vmwgfx_saa.h +++ b/vmwgfx/vmwgfx_saa.h @@ -81,7 +81,8 @@ vmwgfx_saa_pixmap(PixmapPtr pix) extern Bool vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, void (*present_flush)(ScreenPtr pScreen), - Bool direct_presents); + Bool direct_presents, + Bool only_hw_presents); extern uint32_t vmwgfx_scanout_ref(struct vmwgfx_screen_entry *box); -- cgit v1.2.3 From d0b493d67afd1b5e8c8397c7938752ecd56c91ba Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 8 Nov 2011 14:49:36 +0100 Subject: vmwgfx: A number of damage fixes A damage tracker was sometimes attached to a pixmap in the middle of an operation. That meant that damage was never registered for that operation which caused dirty-tracking to fail. Instead, add a damage tracker as soon as we have storage attached to the pixmap. Also, when a pixmap was resized, the dirty region trackers could become stale, and cause DMA operation extending outside of the pixmap with server crashes as a result. This commit fixes that. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_saa.c | 62 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index bd90b3d..3c80ef2 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -34,8 +34,11 @@ #include "vmwgfx_drmi.h" #include "vmwgfx_saa_priv.h" +/* + * Damage to be added as soon as we attach storage to the pixmap. + */ static Bool -vmwgfx_pixmap_add_damage(PixmapPtr pixmap, Bool dirty_as_hw) +vmwgfx_pixmap_add_damage(PixmapPtr pixmap) { struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); @@ -53,10 +56,12 @@ vmwgfx_pixmap_add_damage(PixmapPtr pixmap, Bool dirty_as_hw) box.y1 = 0; box.y2 = draw->height; - if (dirty_as_hw && vpix->hw) { - REGION_INIT(draw->pScreen, &spix->dirty_hw, &box, 1); + if (vpix->hw) { + REGION_RESET(draw->pScreen, &spix->dirty_hw, &box); + REGION_EMPTY(draw->pScreen, &spix->dirty_shadow); } else { - REGION_INIT(draw->pScreen, &spix->dirty_shadow, &box, 1); + REGION_RESET(draw->pScreen, &spix->dirty_shadow, &box); + REGION_EMPTY(draw->pScreen, &spix->dirty_hw); } return TRUE; @@ -68,7 +73,7 @@ vmwgfx_pixmap_remove_damage(PixmapPtr pixmap) struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); - if (!spix->damage || (vpix->hw && vpix->gmr)) + if (!spix->damage || vpix->hw || vpix->gmr || vpix->malloc) return; DamageUnregister(&pixmap->drawable, spix->damage); @@ -115,18 +120,7 @@ vmwgfx_pixmap_add_present(PixmapPtr pixmap, Bool present_opt) if (!vpix->pending_present) goto out_no_pending_present; - /* - * We're not creating new storage here, so if there isn't already - * a damage tracker attached, there is either only sw storage or - * only hw storage, and we use that fact to determine where to put - * the initial dirty region. - */ - if (!vmwgfx_pixmap_add_damage(pixmap, vpix->hw != NULL)) - goto out_no_damage; - return TRUE; - out_no_damage: - REGION_DESTROY(pScreen, vpix->pending_present); out_no_pending_present: REGION_DESTROY(pScreen, vpix->pending_update); out_no_pending_update: @@ -179,7 +173,7 @@ vmwgfx_pixmap_create_gmr(struct vmwgfx_saa *vsaa, PixmapPtr pixmap) memcpy(addr, vpix->malloc, size); vmwgfx_dmabuf_unmap(gmr); - } else if (vpix->hw && !vmwgfx_pixmap_add_damage(pixmap, TRUE)) + } else if (!vmwgfx_pixmap_add_damage(pixmap)) goto out_no_transfer; vpix->backing |= VMWGFX_PIX_GMR; @@ -207,7 +201,7 @@ vmwgfx_pixmap_create_sw(struct vmwgfx_saa *vsaa, PixmapPtr pixmap) vpix->malloc = malloc(pixmap->devKind * pixmap->drawable.height); if (!vpix->malloc) goto out_no_malloc; - if (!vmwgfx_pixmap_add_damage(pixmap, TRUE)) + if (!vmwgfx_pixmap_add_damage(pixmap)) goto out_no_damage; } else if (vpix->backing & VMWGFX_PIX_GMR) return vmwgfx_pixmap_create_gmr(vsaa, pixmap); @@ -534,9 +528,12 @@ vmwgfx_pix_resize(PixmapPtr pixmap, unsigned int old_pitch, { ScreenPtr pScreen = pixmap->drawable.pScreen; struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pScreen)); - struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); + struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); + struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); DrawablePtr draw = &pixmap->drawable; unsigned int size = pixmap->devKind * draw->height; + BoxRec b_box; + RegionRec b_reg; /* * Ignore copying errors. At worst they will show up as rendering @@ -589,6 +586,31 @@ vmwgfx_pix_resize(PixmapPtr pixmap, unsigned int old_pitch, xa_format_unknown, vpix->xa_flags, 1) != 0) return FALSE; } + + b_box.x1 = 0; + b_box.x2 = draw->width; + b_box.y1 = 0; + b_box.y2 = draw->height; + + REGION_INIT(pScreen, &b_reg, &b_box, 1); + REGION_INTERSECT(pScreen, &spix->dirty_shadow, &spix->dirty_shadow, + &b_reg); + REGION_INTERSECT(pScreen, &spix->dirty_hw, &spix->dirty_hw, &b_reg); + if (vpix->dirty_present) + REGION_INTERSECT(pScreen, vpix->dirty_present, vpix->dirty_present, + &b_reg); + if (vpix->pending_update) + REGION_INTERSECT(pScreen, vpix->pending_update, vpix->pending_update, + &b_reg); + if (vpix->pending_present) + REGION_INTERSECT(pScreen, vpix->pending_present, + vpix->pending_present, &b_reg); + if (vpix->present_damage) + REGION_INTERSECT(pScreen, vpix->present_damage, vpix->present_damage, + &b_reg); + + REGION_UNINIT(pScreen, &b_reg); + return TRUE; } @@ -743,7 +765,7 @@ vmwgfx_create_hw(struct vmwgfx_saa *vsaa, vpix->xa_flags = new_flags; - if ((vpix->gmr || vpix->malloc) && !vmwgfx_pixmap_add_damage(pixmap, FALSE)) + if (!vmwgfx_pixmap_add_damage(pixmap)) goto out_no_damage; /* -- cgit v1.2.3 From e1810e0b09e07bdab05a57fdef74450a507e9dfa Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 8 Nov 2011 15:28:40 +0100 Subject: vmwgfx: Fix rendering errors when rotating / unrotating a screen. The dirty trackers weren't correctly translated to pending presents / updates when a pixmap was bound as a scanout. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrants --- vmwgfx/vmwgfx_saa.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 3c80ef2..ad3adf8 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -1375,12 +1375,14 @@ vmwgfx_scanout_refresh(PixmapPtr pixmap) box.x2 = pixmap->drawable.width; box.y2 = pixmap->drawable.height; - REGION_RESET(vsaa->pScreen, vpix->pending_update, &box); + REGION_RESET(vsaa->pScreen, vpix->pending_present, &box); if (vpix->dirty_present) REGION_SUBTRACT(vsaa->pScreen, vpix->pending_present, - &vpix->base.dirty_hw, vpix->dirty_present); - REGION_SUBTRACT(vsaa->pScreen, vpix->pending_update, - vpix->pending_update, &vpix->base.dirty_hw); + vpix->pending_present, vpix->dirty_present); + REGION_SUBTRACT(vsaa->pScreen, vpix->pending_present, + vpix->pending_present, &vpix->base.dirty_shadow); + REGION_COPY(vsaa->pScreen, vpix->pending_update, + &vpix->base.dirty_shadow); } /* -- cgit v1.2.3 From 70487eee975c63b5ed1492927bbc661425278276 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 9 Nov 2011 11:34:16 +0100 Subject: vmwgfx: Make sure we don't render when VT switched When compiz is enabled, we may try to DMA sw rendered contents of dri2 drawables to surfaces while VT switched. I'm not sure how this could be happening, but queue the DMA until the next block handler. Signed-off-by: Thomas Hellstrom Reviewed-by: Alan Hourihane --- vmwgfx/vmwgfx_driver.c | 1 + vmwgfx/vmwgfx_saa.c | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index 0504c2d..a3d7860 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -652,6 +652,7 @@ static void drv_block_handler(int i, pointer blockData, pointer pTimeout, pScreen->BlockHandler(i, blockData, pTimeout, pReadmask); vmwgfx_swap(ms, pScreen, BlockHandler); + vmwgfx_flush_dri2(pScreen); xorg_flush(pScreen); } diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index ad3adf8..d14c551 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -460,6 +460,10 @@ vmwgfx_flush_dri2(ScreenPtr pScreen) struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pScreen)); struct _WsbmListHead *list, *next; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (!pScrn->vtSema) + return; WSBMLISTFOREACHSAFE(list, next, &vsaa->sync_x_list) { struct vmwgfx_saa_pixmap *vpix = @@ -1179,21 +1183,25 @@ vmwgfx_operation_complete(struct saa_driver *driver, struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver); struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix); + ScrnInfoPtr pScrn = xf86Screens[vsaa->pScreen->myNum]; /* * Make dri2 drawables up to date, or add them to the flush list - * executed at glxWaitX(). + * executed at glxWaitX(). Currently glxWaitX() is broken, so + * we flush immediately, unless we're VT-switched away, in which + * case a flush would deadlock in the kernel. */ if (vpix->hw && vpix->hw_is_dri2_fronts) { - if (1) { - if (!vmwgfx_upload_to_hw(driver, pixmap, &spix->dirty_shadow)) - return; + if (1 && pScrn->vtSema && + vmwgfx_upload_to_hw(driver, pixmap, &spix->dirty_shadow)) { + REGION_EMPTY(vsaa->pScreen, &spix->dirty_shadow); - } else { - if (WSBMLISTEMPTY(&vpix->sync_x_head)) - WSBMLISTADDTAIL(&vpix->sync_x_head, &vsaa->sync_x_list); + return; } + + if (WSBMLISTEMPTY(&vpix->sync_x_head)) + WSBMLISTADDTAIL(&vpix->sync_x_head, &vsaa->sync_x_list); } } -- cgit v1.2.3 From 2aa256c96496ed6dd9dbd5880c278f4422500b0f Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 22 Nov 2011 18:37:44 +0100 Subject: vmwlegacy: Factor out bootstrap functions Preparing for choosing driver path in preinit instead of using shim loader. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- src/Makefile.am | 3 +- src/vmware.c | 405 ++---------------------------------------- src/vmware_bootstrap.c | 465 +++++++++++++++++++++++++++++++++++++++++++++++++ src/vmware_bootstrap.h | 48 +++++ 4 files changed, 529 insertions(+), 392 deletions(-) create mode 100644 src/vmware_bootstrap.c create mode 100644 src/vmware_bootstrap.h diff --git a/src/Makefile.am b/src/Makefile.am index 7c972cf..c035757 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -50,7 +50,8 @@ vmwlegacy_drv_la_SOURCES = \ vmwarectrlproto.h \ vmwarexinerama.c \ vmwarevideo.c \ - vmwaremodes.c + vmwaremodes.c \ + vmware_bootstrap.c vmware_drv_la_LTLIBRARIES = vmware_drv.la vmware_drv_la_LDFLAGS = -module -avoid-version diff --git a/src/vmware.c b/src/vmware.c index 4158732..0f3e36f 100644 --- a/src/vmware.c +++ b/src/vmware.c @@ -39,195 +39,16 @@ char rcsId_vmware[] = #include "guest_os.h" #include "vm_device_version.h" #include "svga_modes.h" +#include "vmware_bootstrap.h" #ifndef HAVE_XORG_SERVER_1_5_0 #include #include #endif -#ifdef HaveDriverFuncs -#define VMWARE_DRIVER_FUNC HaveDriverFuncs -#else -#define VMWARE_DRIVER_FUNC 0 -#endif - -/* - * So that the file compiles unmodified when dropped in to a < 6.9 source tree. - */ -#ifndef _X_EXPORT -#define _X_EXPORT -#endif -/* - * So that the file compiles unmodified when dropped into an xfree source tree. - */ -#ifndef XORG_VERSION_CURRENT -#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT -#endif - -/* - * 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 - -#define VMWARE_INCHTOMM 25.4 - -/* - * 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 "vmwlegacy" -#define VMWARE_DRIVER_NAME "vmwlegacy" -#define VMWARE_DRIVER_VERSION \ - (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL) -#define VMWARE_DRIVER_VERSION_STRING \ - VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \ - "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL) - -static const char VMWAREBuildStr[] = "VMware Guest X Server " - VMWARE_DRIVER_VERSION_STRING " - build=$Name$\n"; - -/* - * Standard four digit version string expected by VMware Tools installer. - * As the driver's version is only {major, minor, patchlevel}, - * The fourth digit may describe the commit number relative to the - * last version tag as output from `git describe` - */ - -#ifdef __GNUC__ -#ifdef VMW_SUBPATCH -const char vmwlegacy_drv_modinfo[] -__attribute__((section(".modinfo"),unused)) = - "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH); -#else -const char vmwlegacy_drv_modinfo[] -__attribute__((section(".modinfo"),unused)) = - "version=" VMWARE_DRIVER_VERSION_STRING ".0"; -#endif /*VMW_SUBPATCH*/ -#endif - -static SymTabRec VMWAREChipsets[] = { - { PCI_CHIP_VMWARE0405, "vmware0405" }, - { PCI_CHIP_VMWARE0710, "vmware0710" }, - { -1, NULL } -}; - -#ifndef XSERVER_LIBPCIACCESS -static resRange vmwareLegacyRes[] = { - { ResExcIoBlock, SVGA_LEGACY_BASE_PORT, - SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)}, - _VGA_EXCLUSIVE, _END -}; -#else -#define vmwareLegacyRes NULL -#endif - -#if XSERVER_LIBPCIACCESS - -#define VMWARE_DEVICE_MATCH(d, i) \ - {PCI_VENDOR_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) } - -static const struct pci_id_match VMwareDeviceMatch[] = { - VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0405, 0 ), - VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0710, 0 ), - { 0, 0, 0 }, -}; -#endif - -/* - * 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 } -}; - -#if HAVE_XORG_SERVER_1_7_0 - +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5) #define xf86LoaderReqSymLists(...) do {} while (0) -#define LoaderRefSymLists(...) do {} while (0) - -#else - -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 -}; - -#endif /* HAVE_XORG_SERVER_1_7_0 */ - -#ifdef XFree86LOADER -static XF86ModuleVersionInfo vmwlegacyVersRec = { - VMWARE_DRIVER_NAME, - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, - ABI_CLASS_VIDEODRV, - ABI_VIDEODRV_VERSION, - MOD_CLASS_VIDEODRV, - { 0, 0, 0, 0} -}; -#endif /* XFree86LOADER */ - -typedef enum { - OPTION_HW_CURSOR, - OPTION_XINERAMA, - OPTION_STATIC_XINERAMA, - OPTION_DEFAULT_MODE, -} VMWAREOpts; - -static const OptionInfoRec VMWAREOptions[] = { - { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE }, - { OPTION_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE } -}; +#endif /* Table of default modes to always add to the mode list. */ @@ -463,18 +284,6 @@ RewriteTagString(const char *istr, char *ostr, int osize) } #endif -static void -VMWAREIdentify(int flags) -{ - xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets); -} - -static const OptionInfoRec * -VMWAREAvailableOptions(int chipid, int busid) -{ - return VMWAREOptions; -} - static int VMWAREParseTopologyElement(ScrnInfoPtr pScrn, unsigned int output, @@ -894,18 +703,14 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int flags) #endif xf86CollectOptions(pScrn, NULL); - if (!(options = malloc(sizeof(VMWAREOptions)))) + if (!(options = VMWARECopyOptions())) 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, DEVICE_ID(pVMWARE->PciInfo)); - if (!pScrn->chipset) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04x is not recognised\n", DEVICE_ID(pVMWARE->PciInfo)); return FALSE; @@ -1599,46 +1404,6 @@ vmwareIsRegionEqual(const RegionPtr reg1, return TRUE; } -#if VMWARE_DRIVER_FUNC -static Bool -VMWareDriverFunc(ScrnInfoPtr pScrn, - xorgDriverFuncOp op, - pointer data) -{ - CARD32 *flag; - xorgRRModeMM *modemm; - - switch (op) { - case GET_REQUIRED_HW_INTERFACES: - flag = (CARD32 *)data; - - if (flag) { - *flag = HW_IO | HW_MMIO; - } - return TRUE; - case RR_GET_MODE_MM: - modemm = (xorgRRModeMM *)data; - - /* - * Because changing the resolution of the guest is usually changing the size - * of a window on the host desktop, the real physical DPI will not change. To - * keep the guest in sync, we scale the 'physical' screen dimensions to - * keep the DPI constant. - */ - if (modemm && modemm->mode) { - modemm->mmWidth = (modemm->mode->HDisplay * VMWARE_INCHTOMM + - pScrn->xDpi / 2) / pScrn->xDpi; - modemm->mmHeight = (modemm->mode->VDisplay * VMWARE_INCHTOMM + - pScrn->yDpi / 2) / pScrn->yDpi; - } - return TRUE; - default: - return FALSE; - } -} -#endif - - static Bool VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { @@ -1654,9 +1419,8 @@ VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86CollectOptions(pScrn, NULL); - if (!(options = malloc(sizeof(VMWAREOptions)))) + if (!(options = VMWARECopyOptions())) return FALSE; - memcpy(options, VMWAREOptions, sizeof(VMWAREOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); /* @@ -1977,155 +1741,14 @@ VMWAREValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) return MODE_OK; } -#if XSERVER_LIBPCIACCESS -static Bool -VMwarePciProbe (DriverPtr drv, - int entity_num, - struct pci_device *device, - intptr_t match_data) -{ - ScrnInfoPtr scrn = NULL; - EntityInfoPtr entity; - - scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets, - NULL, NULL, NULL, NULL, NULL); - if (scrn != NULL) { - scrn->driverVersion = VMWARE_DRIVER_VERSION; - scrn->driverName = VMWARE_DRIVER_NAME; - scrn->name = VMWARE_NAME; - scrn->Probe = NULL; - } - - entity = xf86GetEntityInfo(entity_num); - switch (DEVICE_ID(device)) { - case PCI_CHIP_VMWARE0405: - case PCI_CHIP_VMWARE0710: - xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n"); - scrn->PreInit = VMWAREPreInit; - scrn->ScreenInit = VMWAREScreenInit; - scrn->SwitchMode = VMWARESwitchMode; - scrn->EnterVT = VMWAREEnterVT; - scrn->LeaveVT = VMWARELeaveVT; - scrn->FreeScreen = VMWAREFreeScreen; - scrn->ValidMode = VMWAREValidMode; - break; - default: - xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n"); - } - return scrn != NULL; -} -#else - -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); - free(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 = VMWARE_DRIVER_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; - } - } - free(usedChips); - } - return foundScreen; -} -#endif - - -_X_EXPORT DriverRec vmwlegacy = { - VMWARE_DRIVER_VERSION, - VMWARE_DRIVER_NAME, - VMWAREIdentify, -#if XSERVER_LIBPCIACCESS - NULL, -#else - VMWAREProbe, -#endif - VMWAREAvailableOptions, - NULL, - 0, -#if VMWARE_DRIVER_FUNC - VMWareDriverFunc, -#endif -#if XSERVER_LIBPCIACCESS - VMwareDeviceMatch, - VMwarePciProbe, -#endif -}; - -#ifdef XFree86LOADER -static MODULESETUPPROTO(vmwlegacySetup); - -_X_EXPORT XF86ModuleData vmwlegacyModuleData = { - &vmwlegacyVersRec, - vmwlegacySetup, - NULL -}; - -static pointer -vmwlegacySetup(pointer module, pointer opts, int *errmaj, int *errmin) +void +vmwlegacy_hookup(ScrnInfoPtr pScrn) { - static Bool setupDone = FALSE; - - if (!setupDone) { - setupDone = TRUE; - - xf86AddDriver(&vmwlegacy, module, VMWARE_DRIVER_FUNC); - - LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols, - shadowfbSymbols, NULL); - - return (pointer)1; - } - if (errmaj) { - *errmaj = LDR_ONCEONLY; - } - return NULL; + pScrn->PreInit = VMWAREPreInit; + pScrn->ScreenInit = VMWAREScreenInit; + pScrn->SwitchMode = VMWARESwitchMode; + pScrn->EnterVT = VMWAREEnterVT; + pScrn->LeaveVT = VMWARELeaveVT; + pScrn->FreeScreen = VMWAREFreeScreen; + pScrn->ValidMode = VMWAREValidMode; } -#endif /* XFree86LOADER */ diff --git a/src/vmware_bootstrap.c b/src/vmware_bootstrap.c new file mode 100644 index 0000000..45f8cc2 --- /dev/null +++ b/src/vmware_bootstrap.c @@ -0,0 +1,465 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Unknown at vmware + * Author: Thomas Hellstrom + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "compiler.h" +#include "xf86PciInfo.h" /* pci vendor id */ +#include "xf86Pci.h" /* pci */ +#include "vm_device_version.h" +#include "vmware_bootstrap.h" + +#ifndef HAVE_XORG_SERVER_1_5_0 +#include +#include +#endif + +#ifdef HaveDriverFuncs +#define VMWARE_DRIVER_FUNC HaveDriverFuncs +#else +#define VMWARE_DRIVER_FUNC 0 +#endif + +/* + * So that the file compiles unmodified when dropped in to a < 6.9 source tree. + */ +#ifndef _X_EXPORT +#define _X_EXPORT +#endif +/* + * So that the file compiles unmodified when dropped into an xfree source tree. + */ +#ifndef XORG_VERSION_CURRENT +#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT +#endif + +/* + * 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 "vmwlegacy" +#define VMWARE_DRIVER_NAME "vmwlegacy" +#define VMWARE_DRIVER_VERSION \ + (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL) +#define VMWARE_DRIVER_VERSION_STRING \ + VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \ + "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL) + +static const char VMWAREBuildStr[] = "VMware Guest X Server " + VMWARE_DRIVER_VERSION_STRING " - build=$Name$\n"; + +/* + * Standard four digit version string expected by VMware Tools installer. + * As the driver's version is only {major, minor, patchlevel}, + * The fourth digit may describe the commit number relative to the + * last version tag as output from `git describe` + */ + +#ifdef __GNUC__ +#ifdef VMW_SUBPATCH +const char vmwlegacy_drv_modinfo[] +__attribute__((section(".modinfo"),unused)) = + "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH); +#else +const char vmwlegacy_drv_modinfo[] +__attribute__((section(".modinfo"),unused)) = + "version=" VMWARE_DRIVER_VERSION_STRING ".0"; +#endif /*VMW_SUBPATCH*/ +#endif + +#ifndef XSERVER_LIBPCIACCESS +static resRange vmwareLegacyRes[] = { + { ResExcIoBlock, SVGA_LEGACY_BASE_PORT, + SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)}, + _VGA_EXCLUSIVE, _END +}; +#else +#define vmwareLegacyRes NULL +#endif + +#if XSERVER_LIBPCIACCESS +#define VENDOR_ID(p) (p)->vendor_id +#define DEVICE_ID(p) (p)->device_id +#define SUBVENDOR_ID(p) (p)->subvendor_id +#define SUBSYS_ID(p) (p)->subdevice_id +#define CHIP_REVISION(p) (p)->revision +#else +#define VENDOR_ID(p) (p)->vendor +#define DEVICE_ID(p) (p)->chipType +#define SUBVENDOR_ID(p) (p)->subsysVendor +#define SUBSYS_ID(p) (p)->subsysCard +#define CHIP_REVISION(p) (p)->chipRev +#endif + +#if XSERVER_LIBPCIACCESS + +#define VMWARE_DEVICE_MATCH(d, i) \ + {PCI_VENDOR_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) } + +static const struct pci_id_match VMwareDeviceMatch[] = { + VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0405, 0 ), + VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0710, 0 ), + { 0, 0, 0 }, +}; +#endif + +/* + * 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 SymTabRec VMWAREChipsets[] = { + { PCI_CHIP_VMWARE0405, "vmware0405" }, + { PCI_CHIP_VMWARE0710, "vmware0710" }, + { -1, NULL } +}; + +#ifdef XFree86LOADER +static XF86ModuleVersionInfo vmwlegacyVersRec = { + VMWARE_DRIVER_NAME, + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + { 0, 0, 0, 0} +}; +#endif /* XFree86LOADER */ + +static const OptionInfoRec VMWAREOptions[] = { + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE }, + { OPTION_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +OptionInfoPtr VMWARECopyOptions(void) +{ + OptionInfoPtr options; + if (!(options = malloc(sizeof(VMWAREOptions)))) + return NULL; + + memcpy(options, VMWAREOptions, sizeof(VMWAREOptions)); + return options; +} + +static Bool +VMwarePreinitStub(ScrnInfoPtr pScrn, int flags) +{ +#if XSERVER_LIBPCIACCESS + struct pci_device *pciInfo; +#else + pciVideoPtr pciInfo; +#endif /* XSERVER_LIBPCIACCESS */ + EntityInfoPtr pEnt; + + pScrn->PreInit = pScrn->driverPrivate; + pScrn->driverPrivate = NULL; + + pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if (pEnt->location.type != BUS_PCI) + return FALSE; + + pciInfo = xf86GetPciInfoForEntity(pEnt->index); + if (pciInfo == NULL) + return FALSE; + + pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets, + DEVICE_ID(pciInfo)); + + ErrorF("Stub bitsperpixel is %d\n", pScrn->bitsPerPixel); + + return (*pScrn->PreInit)(pScrn, flags); +}; + +#if XSERVER_LIBPCIACCESS +static Bool +VMwarePciProbe (DriverPtr drv, + int entity_num, + struct pci_device *device, + intptr_t match_data) +{ + ScrnInfoPtr scrn = NULL; + EntityInfoPtr entity; + + scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets, + NULL, NULL, NULL, NULL, NULL); + if (scrn != NULL) { + scrn->driverVersion = VMWARE_DRIVER_VERSION; + scrn->driverName = VMWARE_DRIVER_NAME; + scrn->name = VMWARE_NAME; + scrn->Probe = NULL; + } + + entity = xf86GetEntityInfo(entity_num); + switch (DEVICE_ID(device)) { + case PCI_CHIP_VMWARE0405: + case PCI_CHIP_VMWARE0710: + xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n"); + vmwlegacy_hookup(scrn); + scrn->driverPrivate = scrn->PreInit; + scrn->PreInit = VMwarePreinitStub; + break; + default: + xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n"); + } + return scrn != NULL; +} +#else + +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); + free(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 = VMWARE_DRIVER_VERSION; + pScrn->driverName = VMWARE_DRIVER_NAME; + pScrn->name = VMWARE_NAME; + pScrn->Probe = VMWAREProbe; + pScrn->PreInit = VMWAREPreInit; + vmwlegacy_hookup(scrn); + scrn->driverPrivate = scrn->PreInit; + scrn->PreInit = VMwarePreinitStub; + foundScreen = TRUE; + } + } + free(usedChips); + } + return foundScreen; +} +#endif + +static void +VMWAREIdentify(int flags) +{ + xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets); +} + +static const OptionInfoRec * +VMWAREAvailableOptions(int chipid, int busid) +{ + return VMWAREOptions; +} + +#if VMWARE_DRIVER_FUNC +static Bool +VMWareDriverFunc(ScrnInfoPtr pScrn, + xorgDriverFuncOp op, + pointer data) +{ + CARD32 *flag; + xorgRRModeMM *modemm; + + switch (op) { + case GET_REQUIRED_HW_INTERFACES: + flag = (CARD32 *)data; + + if (flag) { + *flag = HW_IO | HW_MMIO; + } + return TRUE; + case RR_GET_MODE_MM: + modemm = (xorgRRModeMM *)data; + + /* + * Because changing the resolution of the guest is usually changing the size + * of a window on the host desktop, the real physical DPI will not change. To + * keep the guest in sync, we scale the 'physical' screen dimensions to + * keep the DPI constant. + */ + if (modemm && modemm->mode) { + modemm->mmWidth = (modemm->mode->HDisplay * VMWARE_INCHTOMM + + pScrn->xDpi / 2) / pScrn->xDpi; + modemm->mmHeight = (modemm->mode->VDisplay * VMWARE_INCHTOMM + + pScrn->yDpi / 2) / pScrn->yDpi; + } + return TRUE; + default: + return FALSE; + } +} +#endif + + +_X_EXPORT DriverRec vmwlegacy = { + VMWARE_DRIVER_VERSION, + VMWARE_DRIVER_NAME, + VMWAREIdentify, +#if XSERVER_LIBPCIACCESS + NULL, +#else + VMWAREProbe, +#endif + VMWAREAvailableOptions, + NULL, + 0, +#if VMWARE_DRIVER_FUNC + VMWareDriverFunc, +#endif +#if XSERVER_LIBPCIACCESS + VMwareDeviceMatch, + VMwarePciProbe, +#endif +}; + +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5) + +#define xf86LoaderReqSymLists(...) do {} while (0) +#define LoaderRefSymLists(...) do {} while (0) + +#else + +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 +}; +#endif + +#ifdef XFree86LOADER +static MODULESETUPPROTO(vmwlegacySetup); + +_X_EXPORT XF86ModuleData vmwlegacyModuleData = { + &vmwlegacyVersRec, + vmwlegacySetup, + NULL +}; + +static pointer +vmwlegacySetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + if (!setupDone) { + setupDone = TRUE; + + xf86AddDriver(&vmwlegacy, module, VMWARE_DRIVER_FUNC); + + LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols, + shadowfbSymbols, NULL); + + return (pointer)1; + } + if (errmaj) { + *errmaj = LDR_ONCEONLY; + } + return NULL; +} +#endif /* XFree86LOADER */ diff --git a/src/vmware_bootstrap.h b/src/vmware_bootstrap.h new file mode 100644 index 0000000..611fd8e --- /dev/null +++ b/src/vmware_bootstrap.h @@ -0,0 +1,48 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Thomas Hellstrom + */ +#ifndef _VMWARE_BOOTSTRAP_H_ +#define _VMWARE_BOOTSTRAP_H_ + +#include + +#define VMWARE_INCHTOMM 25.4 + +typedef enum { + OPTION_HW_CURSOR, + OPTION_XINERAMA, + OPTION_STATIC_XINERAMA, + OPTION_DEFAULT_MODE, +} VMWAREOpts; + +OptionInfoPtr VMWARECopyOptions(void); +const char **vgahwSymbols; + +void +vmwlegacy_hookup(ScrnInfoPtr pScrn); + + +#endif -- cgit v1.2.3 From 1c77e3d7434f04c59233ce7e497a949e386e1630 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 22 Nov 2011 19:56:20 +0100 Subject: vmware: Hook up vmwgfx to be tried before falling back to legacy Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- Makefile.am | 2 +- configure.ac | 18 ++-- src/Makefile.am | 21 ++-- src/vmware_bootstrap.c | 65 +++++++++--- src/vmware_bootstrap.h | 10 ++ src/vmwaremodule.c | 256 ---------------------------------------------- vmwgfx/Makefile.am | 11 +- vmwgfx/vmwgfx_bootstrap.c | 199 ----------------------------------- vmwgfx/vmwgfx_dri2.c | 2 +- vmwgfx/vmwgfx_driver.c | 50 ++------- 10 files changed, 93 insertions(+), 541 deletions(-) delete mode 100644 src/vmwaremodule.c delete mode 100644 vmwgfx/vmwgfx_bootstrap.c diff --git a/Makefile.am b/Makefile.am index 3208a23..1203715 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,7 +18,7 @@ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -SUBDIRS = src man vmwarectrl @VMWGFX_DIRS@ +SUBDIRS = @VMWGFX_DIRS@ src man vmwarectrl MAINTAINERCLEANFILES = ChangeLog INSTALL .PHONY: ChangeLog INSTALL diff --git a/configure.ac b/configure.ac index 2c4f959..9af67a4 100644 --- a/configure.ac +++ b/configure.ac @@ -72,11 +72,6 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto) # Obtain compiler/linker options for the driver dependencies PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.1 xproto fontsproto $REQUIRED_MODULES]) -PKG_CHECK_MODULES(LIBDRM, - [libdrm], - [AC_DEFINE([HAVE_LIBDRM], 1, [Has libdrm])], - [echo "Will not try support for 3D or kernel modesetting."]) - PKG_CHECK_EXISTS([xorg-server >= 1.1.0], [AC_DEFINE([HAVE_XORG_SERVER_1_1_0], 1, [Has version 1.1.0 or greater of the Xserver])]) @@ -114,6 +109,9 @@ AM_CONDITIONAL(XSERVER_LIBPCIACCESS, test "x$XSERVER_LIBPCIACCESS" = xyes) AC_SUBST([moduledir]) +if test x$BUILD_VMWGFX = xyes; then + PKG_CHECK_MODULES([LIBDRM], [libdrm],[],[BUILD_VMWGFX=no]) +fi if test x$BUILD_VMWGFX = xyes; then PKG_CHECK_MODULES([XATRACKER], [xatracker >= 0.4.0],[],[BUILD_VMWGFX=no]) fi @@ -121,21 +119,25 @@ fi DRIVER_NAME=vmware AC_SUBST([DRIVER_NAME]) - +AC_MSG_CHECKING([whether to build Kernel Mode Setting and 3D]) VMWGFX_DIRS= if test x$BUILD_VMWGFX = xyes; then + AC_MSG_RESULT([yes]) AC_SYS_LARGEFILE VMWGFX_DIRS="saa vmwgfx" + VMWGFX_LIBADD='$(top_srcdir)/vmwgfx/libvmwgfx.la' AC_CONFIG_FILES([ saa/Makefile vmwgfx/Makefile ]) - echo "Will build the vmwgfx driver." + AC_DEFINE([BUILD_VMWGFX], 1, + [Building the vmwgfx driver path]) else - echo "Will not build the vmwgfx driver." + AC_MSG_RESULT([no]) fi AC_SUBST([VMWGFX_DIRS]) +AC_SUBST([VMWGFX_LIBADD]) AC_CONFIG_FILES([ Makefile src/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index c035757..60bc15a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,12 +24,13 @@ # _ladir passes a dummy rpath to libtool so the thing will actually link # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. -vmwlegacy_drv_la_LTLIBRARIES = vmwlegacy_drv.la -vmwlegacy_drv_la_LDFLAGS = -module -avoid-version -vmwlegacy_drv_la_CFLAGS = @XORG_CFLAGS@ -vmwlegacy_drv_ladir = @moduledir@/drivers +vmware_drv_la_LTLIBRARIES = vmware_drv.la +vmware_drv_la_LDFLAGS = -module -avoid-version +vmware_drv_la_CFLAGS = @XORG_CFLAGS@ +vmware_drv_ladir = @moduledir@/drivers +vmware_drv_la_LIBADD = @VMWGFX_LIBADD@ -vmwlegacy_drv_la_SOURCES = \ +vmware_drv_la_SOURCES = \ bits2pixels.c \ bits2pixels.h \ guest_os.h \ @@ -51,13 +52,5 @@ vmwlegacy_drv_la_SOURCES = \ vmwarexinerama.c \ vmwarevideo.c \ vmwaremodes.c \ + vmware_bootstrap.h \ vmware_bootstrap.c - -vmware_drv_la_LTLIBRARIES = vmware_drv.la -vmware_drv_la_LDFLAGS = -module -avoid-version -vmware_drv_la_CFLAGS = @XORG_CFLAGS@ @LIBDRM_CFLAGS@ -vmware_drv_la_LIBADD = @LIBDRM_LIBS@ -vmware_drv_ladir = @moduledir@/drivers - -vmware_drv_la_SOURCES = \ - vmwaremodule.c diff --git a/src/vmware_bootstrap.c b/src/vmware_bootstrap.c index 45f8cc2..92eb3c5 100644 --- a/src/vmware_bootstrap.c +++ b/src/vmware_bootstrap.c @@ -81,8 +81,8 @@ #define VMW_INNERSTRINGIFY(s) #s #define VMW_STRING(str) VMW_INNERSTRINGIFY(str) -#define VMWARE_NAME "vmwlegacy" -#define VMWARE_DRIVER_NAME "vmwlegacy" +#define VMWARE_NAME "vmware" +#define VMWARE_DRIVER_NAME "vmware" #define VMWARE_DRIVER_VERSION \ (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL) #define VMWARE_DRIVER_VERSION_STRING \ @@ -101,11 +101,11 @@ static const char VMWAREBuildStr[] = "VMware Guest X Server " #ifdef __GNUC__ #ifdef VMW_SUBPATCH -const char vmwlegacy_drv_modinfo[] +const char vmware_drv_modinfo[] __attribute__((section(".modinfo"),unused)) = "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH); #else -const char vmwlegacy_drv_modinfo[] +const char vmware_drv_modinfo[] __attribute__((section(".modinfo"),unused)) = "version=" VMWARE_DRIVER_VERSION_STRING ".0"; #endif /*VMW_SUBPATCH*/ @@ -167,7 +167,7 @@ static SymTabRec VMWAREChipsets[] = { }; #ifdef XFree86LOADER -static XF86ModuleVersionInfo vmwlegacyVersRec = { +static XF86ModuleVersionInfo vmwareVersRec = { VMWARE_DRIVER_NAME, MODULEVENDORSTRING, MODINFOSTRING1, @@ -185,7 +185,12 @@ static const OptionInfoRec VMWAREOptions[] = { { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE }, + { OPTION_GUI_LAYOUT, "GuiLayout", OPTV_STRING, {0}, FALSE }, { OPTION_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_DIRECT_PRESENTS, "DirectPresents", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_HW_PRESENTS, "HWPresents", OPTV_BOOLEAN, {0}, FALSE}, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -210,8 +215,30 @@ VMwarePreinitStub(ScrnInfoPtr pScrn, int flags) EntityInfoPtr pEnt; pScrn->PreInit = pScrn->driverPrivate; + +#ifdef BUILD_VMWGFX pScrn->driverPrivate = NULL; + /* + * Try vmwgfx path. + */ + if ((*pScrn->PreInit)(pScrn, flags)) + return TRUE; + +#else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Driver was compiled without KMS- and 3D support.\n"); +#endif /* defined(BUILD_VMWGFX) */ + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling 3D support.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling Render Acceleration.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling RandR12+ support.\n"); + + pScrn->driverPrivate = NULL; + vmwlegacy_hookup(pScrn); + pEnt = xf86GetEntityInfo(pScrn->entityList[0]); if (pEnt->location.type != BUS_PCI) return FALSE; @@ -223,8 +250,6 @@ VMwarePreinitStub(ScrnInfoPtr pScrn, int flags) pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets, DEVICE_ID(pciInfo)); - ErrorF("Stub bitsperpixel is %d\n", pScrn->bitsPerPixel); - return (*pScrn->PreInit)(pScrn, flags); }; @@ -252,7 +277,13 @@ VMwarePciProbe (DriverPtr drv, case PCI_CHIP_VMWARE0405: case PCI_CHIP_VMWARE0710: xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n"); + +#ifdef BUILD_VMWGFX + vmwgfx_hookup(scrn); +#else vmwlegacy_hookup(scrn); +#endif /* defined(BUILD_VMWGFX) */ + scrn->driverPrivate = scrn->PreInit; scrn->PreInit = VMwarePreinitStub; break; @@ -308,7 +339,13 @@ VMWAREProbe(DriverPtr drv, int flags) pScrn->name = VMWARE_NAME; pScrn->Probe = VMWAREProbe; pScrn->PreInit = VMWAREPreInit; + +#ifdef BUILD_VMWGFX + vmwgfx_hookup(scrn); +#else vmwlegacy_hookup(scrn); +#endif /* defined(BUILD_VMWGFX) */ + scrn->driverPrivate = scrn->PreInit; scrn->PreInit = VMwarePreinitStub; foundScreen = TRUE; @@ -372,7 +409,7 @@ VMWareDriverFunc(ScrnInfoPtr pScrn, #endif -_X_EXPORT DriverRec vmwlegacy = { +_X_EXPORT DriverRec vmware = { VMWARE_DRIVER_VERSION, VMWARE_DRIVER_NAME, VMWAREIdentify, @@ -434,23 +471,23 @@ static const char *shadowfbSymbols[] = { #endif #ifdef XFree86LOADER -static MODULESETUPPROTO(vmwlegacySetup); +static MODULESETUPPROTO(vmwareSetup); -_X_EXPORT XF86ModuleData vmwlegacyModuleData = { - &vmwlegacyVersRec, - vmwlegacySetup, +_X_EXPORT XF86ModuleData vmwareModuleData = { + &vmwareVersRec, + vmwareSetup, NULL }; static pointer -vmwlegacySetup(pointer module, pointer opts, int *errmaj, int *errmin) +vmwareSetup(pointer module, pointer opts, int *errmaj, int *errmin) { static Bool setupDone = FALSE; if (!setupDone) { setupDone = TRUE; - xf86AddDriver(&vmwlegacy, module, VMWARE_DRIVER_FUNC); + xf86AddDriver(&vmware, module, VMWARE_DRIVER_FUNC); LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols, shadowfbSymbols, NULL); diff --git a/src/vmware_bootstrap.h b/src/vmware_bootstrap.h index 611fd8e..1a1ee9e 100644 --- a/src/vmware_bootstrap.h +++ b/src/vmware_bootstrap.h @@ -35,7 +35,12 @@ typedef enum { OPTION_HW_CURSOR, OPTION_XINERAMA, OPTION_STATIC_XINERAMA, + OPTION_GUI_LAYOUT, OPTION_DEFAULT_MODE, + OPTION_RENDER_ACCEL, + OPTION_DRI, + OPTION_DIRECT_PRESENTS, + OPTION_HW_PRESENTS } VMWAREOpts; OptionInfoPtr VMWARECopyOptions(void); @@ -44,5 +49,10 @@ const char **vgahwSymbols; void vmwlegacy_hookup(ScrnInfoPtr pScrn); +#ifdef BUILD_VMWGFX +void +vmwgfx_hookup(ScrnInfoPtr pScrn); +#endif /* defined(BUILD_VMWGFX) */ + #endif diff --git a/src/vmwaremodule.c b/src/vmwaremodule.c deleted file mode 100644 index 0da2440..0000000 --- a/src/vmwaremodule.c +++ /dev/null @@ -1,256 +0,0 @@ -/********************************************************** - * Copyright 2010 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - **********************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_LIBDRM -#include -#endif - -#include -#include - -#ifndef HAVE_XORG_SERVER_1_5_0 -#include -#include -#endif - -/* - * Defines and exported module info. - */ - -#define VMWARE_DRIVER_NAME "vmware" -#define VMWGFX_DRIVER_NAME "vmwgfx" -#define VMWGFX_MODULE_NAME "vmwgfx" -#define VMWGFX_COMPAT_MAJOR 11 -#define VMWGFX_REQUIRED_MAJOR 11 -#define VMWGFX_REQUIRED_MINOR 0 -#define VMWLEGACY_DRIVER_NAME "vmwlegacy" - -#define VMW_STRING_INNER(s) #s -#define VMW_STRING(str) VMW_STRING_INNER(str) - -#define VMWARE_DRIVER_VERSION \ - (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL) -#define VMWARE_DRIVER_VERSION_STRING \ - VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \ - "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL) - -/* - * Standard four digit version string expected by VMware Tools installer. - * As the driver's version is only {major, minor, patchlevel}, - * the fourth digit may describe the commit number relative to the - * last version tag as output from `git describe` - */ - -#ifdef __GNUC__ -#ifdef VMW_SUBPATCH -const char vmware_drv_modinfo[] __attribute__((section(".modinfo"),unused)) = - "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH); -#else -const char vmware_drv_modinfo[] __attribute__((section(".modinfo"),unused)) = - "version=" VMWARE_DRIVER_VERSION_STRING ".0"; -#endif /*VMW_SUBPATCH*/ -#endif - -static XF86ModuleVersionInfo vmware_version; -static MODULESETUPPROTO(vmware_setup); - -_X_EXPORT XF86ModuleData vmwareModuleData = { - &vmware_version, - vmware_setup, - NULL -}; - -extern XF86ModuleData *VMWGFX_MODULE_DATA; - -/* - * Chain loading functions - */ - -static Bool -vmware_check_kernel_module() -{ -#ifdef HAVE_LIBDRM - /* Super simple way of knowing if the kernel driver is loaded */ - int ret = drmOpen(VMWGFX_MODULE_NAME, NULL); - if (ret < 0) { - /* This shouldn't go in the log as the original message does not */ - fprintf(stderr, "%s: Please ignore above \"FATAL: Module %s not found." - "\"\n", VMWARE_DRIVER_NAME, VMWGFX_MODULE_NAME); - /* This is what goes into the log on the other hand */ - xf86DrvMsg(-1, X_PROBED, "%s: Please ignore above \"[drm] failed to " - "load kernel module \"%s\"\"\n", VMWARE_DRIVER_NAME, - VMWGFX_MODULE_NAME); - return FALSE; - } - - drmClose(ret); - - return TRUE; -#else - return FALSE; -#endif /* HAVE_LIBDRM */ -} - -static Bool -vmware_check_vmwgfx_driver(int matched, pointer opts) -{ -#ifdef HAVE_LIBDRM - int major; int minor; - pointer module; - CARD32 version; - - if (matched) { - xf86DrvMsg(-1, X_PROBED, "%s: X configured to use %s X driver assume " - "who ever did that knows what they are doing\n", - VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME); - /* Also how did they end up here, if the configured X to use vmwgfx and - * X should load that driver for that hardware. And since there is only - * one SVGA device this driver shouldn't be loaded. Weird... - */ - return TRUE; - } - - module = xf86LoadOneModule(VMWGFX_DRIVER_NAME, opts); - if (!module) { - xf86DrvMsg(-1, X_ERROR, "%s: Please ignore the above warnings about " - "not being able to to load module/driver %s\n", - VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME); - return FALSE; - } - - version = xf86GetModuleVersion(module); - major = GET_MODULE_MAJOR_VERSION(version); - minor = GET_MODULE_MINOR_VERSION(version); - - if (major > VMWGFX_COMPAT_MAJOR || - major < VMWGFX_REQUIRED_MAJOR || - (major == VMWGFX_REQUIRED_MAJOR && minor < VMWGFX_REQUIRED_MINOR)) { - xf86DrvMsg(-1, X_PROBED, "%s: The %s X driver failed version " - "checking.\n", VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME); - goto err; - } - - return TRUE; - -err: - /* XXX We should drop the reference on the module here */ -#endif /* HAVE_LIBDRM */ - return FALSE; -} - -static Bool -vmware_chain_module(pointer opts) -{ - int vmwlegacy_devices; - int vmwgfx_devices; - int vmware_devices; - int matched; - char *driver_name; - GDevPtr *gdevs; - GDevPtr gdev; - int i; - - vmware_devices = xf86MatchDevice(VMWARE_DRIVER_NAME, &gdevs); - vmwgfx_devices = xf86MatchDevice(VMWGFX_DRIVER_NAME, NULL); - vmwlegacy_devices = xf86MatchDevice(VMWLEGACY_DRIVER_NAME, NULL); - - if (vmware_check_vmwgfx_driver(vmwgfx_devices, opts) && - vmware_check_kernel_module()) { - xf86DrvMsg(-1, X_INFO, "%s: Using %s X driver.\n", - VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME); - driver_name = VMWGFX_DRIVER_NAME; - matched = 1; - } else { - xf86DrvMsg(-1, X_INFO, "%s: Using %s driver everything is fine.\n", - VMWARE_DRIVER_NAME, VMWLEGACY_DRIVER_NAME); - driver_name = VMWLEGACY_DRIVER_NAME; - matched = vmwlegacy_devices; - } - - /* Xorg -configure returns 1 from xf86MatchDevice with NULL gdevs */ - for (i = 0; gdevs && i < vmware_devices; i++) { - gdev = gdevs[i]; - gdev->driver = driver_name; - } - - free(gdevs); - - if (!matched) { - if (xf86LoadOneModule(driver_name, opts) == NULL) { - xf86DrvMsg(-1, X_ERROR, "%s: Unexpected failure while " - "loading the \"%s\" driver. Giving up.\n", - VMWARE_DRIVER_NAME, driver_name); - return FALSE; - } - } - - return TRUE; -} - - -/* - * Module info - */ - -static XF86ModuleVersionInfo vmware_version = { - VMWARE_DRIVER_NAME, - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, - ABI_CLASS_VIDEODRV, - ABI_VIDEODRV_VERSION, - MOD_CLASS_VIDEODRV, - {0, 0, 0, 0} -}; - -static pointer -vmware_setup(pointer module, pointer opts, int *errmaj, int *errmin) -{ - static Bool setupDone = 0; - - /* This module should be loaded only once, but check to be sure. */ - if (!setupDone) { - setupDone = 1; - - /* Chain load the real driver */ - if (vmware_chain_module(opts)) - return (pointer) 1; - else { - if (errmaj) - *errmaj = LDR_NOSUBENT; - return NULL; - } - } else { - if (errmaj) - *errmaj = LDR_ONCEONLY; - return NULL; - } -} diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am index e956b64..8fe3e71 100644 --- a/vmwgfx/Makefile.am +++ b/vmwgfx/Makefile.am @@ -1,11 +1,9 @@ -vmwgfx_drv_la_LTLIBRARIES = vmwgfx_drv.la -vmwgfx_drv_la_LDFLAGS = -module -avoid-version -vmwgfx_drv_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) @LIBDRM_CFLAGS@ @XATRACKER_CFLAGS@ -I$(top_srcdir)/src -I$(top_srcdir)/saa -vmwgfx_drv_la_LIBADD = @LIBDRM_LIBS@ $(top_srcdir)/saa/libsaa.la\ +noinst_LTLIBRARIES = libvmwgfx.la +libvmwgfx_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) @LIBDRM_CFLAGS@ @XATRACKER_CFLAGS@ -I$(top_srcdir)/src -I$(top_srcdir)/saa +libvmwgfx_la_LIBADD = @LIBDRM_LIBS@ $(top_srcdir)/saa/libsaa.la\ @XATRACKER_LIBS@ -vmwgfx_drv_ladir = @moduledir@/drivers -vmwgfx_drv_la_SOURCES = \ +libvmwgfx_la_SOURCES = \ vmwgfx_driver.c \ vmwgfx_driver.h \ vmwgfx_crtc.c \ @@ -16,7 +14,6 @@ vmwgfx_drv_la_SOURCES = \ vmwgfx_saa.h \ vmwgfx_drmi.c \ vmwgfx_drmi.h \ - vmwgfx_bootstrap.c \ vmwgfx_overlay.c \ vmwgfx_ctrl.c \ vmwgfx_ctrl.h \ diff --git a/vmwgfx/vmwgfx_bootstrap.c b/vmwgfx/vmwgfx_bootstrap.c deleted file mode 100644 index 5e8e9e1..0000000 --- a/vmwgfx/vmwgfx_bootstrap.c +++ /dev/null @@ -1,199 +0,0 @@ -/********************************************************** - * Copyright 2008-2011 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - **********************************************************/ - -/** - * @file - * Bootstrap file for the vmwgfx xorg driver. - * - * @author Alan Hourihane - * @author Jakob Bornecrantz - * @author Thomas Hellstrom - */ - -#include "xorg-server.h" -#include "xf86.h" -#include "pciaccess.h" - -#ifndef XSERVER_LIBPCIACCESS -#error "libpciaccess needed" -#endif - -void xorg_tracker_set_functions(ScrnInfoPtr scrn); -const OptionInfoRec * xorg_tracker_available_options(int chipid, int busid); - - -/* - * Defines and modinfo - */ - -#define VMWGFX_DRIVER_NAME "vmwgfx" - -#define VMW_STRING_INNER(s) #s -#define VMW_STRING(str) VMW_STRING_INNER(str) - -#define VMWGFX_VERSION_MAJOR 11 -#define VMWGFX_VERSION_MINOR 0 -#define VMWGFX_VERSION_PATCH 0 -#define VMWGFX_VERSION_STRING_MAJOR VMW_STRING(VMWGFX_VERSION_MAJOR) -#define VMWGFX_VERSION_STRING_MINOR VMW_STRING(VMWGFX_VERSION_MINOR) -#define VMWGFX_VERSION_STRING_PATCH VMW_STRING(VMWGFX_VERSION_PATCH) - -#define VMWGFX_DRIVER_VERSION \ - (VMWGFX_VERSION_MAJOR * 65536 + VMWGFX_VERSION_MINOR * 256 + VMWGFX_VERSION_PATCH) -#define VMWGFX_DRIVER_VERSION_STRING \ - VMWGFX_VERSION_STRING_MAJOR "." VMWGFX_VERSION_STRING_MINOR \ - "." VMWGFX_VERSION_STRING_PATCH - -/* - * Standard four digit version string expected by VMware Tools installer. - * As the driver's version is only {major, minor, patchlevel}, simply append an - * extra zero for the fourth digit. - */ -#ifdef __GNUC__ -_X_EXPORT const char vmwgfx_drv_modinfo[] __attribute__((section(".modinfo"),unused)) = - "version=" VMWGFX_DRIVER_VERSION_STRING ".0"; -#endif - -static void vmw_xorg_identify(int flags); -_X_EXPORT Bool vmw_xorg_pci_probe(DriverPtr driver, - int entity_num, - struct pci_device *device, - intptr_t match_data); - - -/* - * Tables - */ - -static const struct pci_id_match vmw_xorg_device_match[] = { - {0x15ad, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0}, -}; - -static SymTabRec vmw_xorg_chipsets[] = { - {PCI_MATCH_ANY, "VMware SVGA Device"}, - {-1, NULL} -}; - -static PciChipsets vmw_xorg_pci_devices[] = { - {PCI_MATCH_ANY, PCI_MATCH_ANY, NULL}, - {-1, -1, NULL} -}; - -static XF86ModuleVersionInfo vmw_xorg_version = { - VMWGFX_DRIVER_NAME, - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - VMWGFX_VERSION_MAJOR, VMWGFX_VERSION_MINOR, VMWGFX_VERSION_PATCH, - ABI_CLASS_VIDEODRV, - ABI_VIDEODRV_VERSION, - MOD_CLASS_VIDEODRV, - {0, 0, 0, 0} -}; - -/* - * Xorg driver exported structures - */ - -_X_EXPORT DriverRec vmwgfx = { - 1, - VMWGFX_DRIVER_NAME, - vmw_xorg_identify, - NULL, - xorg_tracker_available_options, - NULL, - 0, - NULL, - vmw_xorg_device_match, - vmw_xorg_pci_probe -}; - -static MODULESETUPPROTO(vmw_xorg_setup); - -_X_EXPORT XF86ModuleData vmwgfxModuleData = { - &vmw_xorg_version, - vmw_xorg_setup, - NULL -}; - - -/* - * Xorg driver functions - */ - -static pointer -vmw_xorg_setup(pointer module, pointer opts, int *errmaj, int *errmin) -{ - static Bool setupDone = 0; - - /* This module should be loaded only once, but check to be sure. - */ - if (!setupDone) { - setupDone = 1; - xf86AddDriver(&vmwgfx, module, HaveDriverFuncs); - - /* - * The return value must be non-NULL on success even though there - * is no TearDownProc. - */ - return (pointer) 1; - } else { - if (errmaj) - *errmaj = LDR_ONCEONLY; - return NULL; - } -} - -static void -vmw_xorg_identify(int flags) -{ - xf86PrintChipsets("vmwgfx", "Driver for VMware SVGA device", - vmw_xorg_chipsets); -} - -_X_EXPORT Bool -vmw_xorg_pci_probe(DriverPtr driver, - int entity_num, struct pci_device *device, intptr_t match_data) -{ - ScrnInfoPtr scrn = NULL; - EntityInfoPtr entity; - - scrn = xf86ConfigPciEntity(scrn, 0, entity_num, vmw_xorg_pci_devices, - NULL, NULL, NULL, NULL, NULL); - if (scrn != NULL) { - scrn->driverVersion = 1; - scrn->driverName = "vmwgfx"; - scrn->name = "vmwgfx"; - scrn->Probe = NULL; - - entity = xf86GetEntityInfo(entity_num); - - /* Use all the functions from the xorg tracker */ - xorg_tracker_set_functions(scrn); - } - return scrn != NULL; -} diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index b3fb1e8..ddeaf1d 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -376,7 +376,7 @@ xorg_dri2_init(ScreenPtr pScreen) dri2info.version = min(DRI2INFOREC_VERSION, 3); dri2info.fd = ms->fd; - dri2info.driverName = pScrn->driverName; + dri2info.driverName = "vmwgfx"; dri2info.deviceName = "/dev/dri/card0"; /* FIXME */ dri2info.CreateBuffer = dri2_create_buffer; diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index a3d7860..69fef8c 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -58,6 +58,7 @@ #include #include "vmwgfx_saa.h" +#include "../src/vmware_bootstrap.h" #define XA_VERSION_MINOR_REQUIRED 0 #define DRM_VERSION_MAJOR_REQUIRED 2 @@ -97,47 +98,15 @@ static ModeStatus drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbos int flags); extern void xorg_tracker_set_functions(ScrnInfoPtr scrn); -extern const OptionInfoRec * xorg_tracker_available_options(int chipid, - int busid); - - -typedef enum -{ - OPTION_SW_CURSOR, - OPTION_RENDER_ACCEL, - OPTION_DRI, - OPTION_DIRECT_PRESENTS, - OPTION_HW_PRESENTS -} drv_option_enums; - -static const OptionInfoRec drv_options[] = { - {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_DIRECT_PRESENTS, "DirectPresents", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_HW_PRESENTS, "HWPresents", OPTV_BOOLEAN, {0}, FALSE}, - {-1, NULL, OPTV_NONE, {0}, FALSE} -}; - - -/* - * Exported Xorg driver functions to winsys - */ - -const OptionInfoRec * -xorg_tracker_available_options(int chipid, int busid) -{ - return drv_options; -} void -xorg_tracker_set_functions(ScrnInfoPtr scrn) +vmwgfx_hookup(ScrnInfoPtr pScrn) { - scrn->PreInit = drv_pre_init; - scrn->ScreenInit = drv_screen_init; - scrn->SwitchMode = drv_switch_mode; - scrn->FreeScreen = drv_free_screen; - scrn->ValidMode = drv_valid_mode; + pScrn->PreInit = drv_pre_init; + pScrn->ScreenInit = drv_screen_init; + pScrn->SwitchMode = drv_switch_mode; + pScrn->FreeScreen = drv_free_screen; + pScrn->ValidMode = drv_valid_mode; } /* @@ -399,9 +368,8 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) /* Process the options */ xf86CollectOptions(pScrn, NULL); - if (!(ms->Options = malloc(sizeof(drv_options)))) + if (!(ms->Options = VMWARECopyOptions())) return FALSE; - memcpy(ms->Options, drv_options, sizeof(drv_options)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options); ms->accelerate_render = TRUE; @@ -461,7 +429,7 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) } - if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) { + if (!xf86ReturnOptValBool(ms->Options, OPTION_HW_CURSOR, TRUE)) { ms->SWCursor = TRUE; } -- cgit v1.2.3 From e52b1505cfc4a7d0507e14c3b6335a9b9652c50f Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 25 Nov 2011 09:15:32 +0100 Subject: vmware: Update the vmware register definition Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- src/svga_reg.h | 304 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 255 insertions(+), 49 deletions(-) diff --git a/src/svga_reg.h b/src/svga_reg.h index 5d36029..6757aa6 100644 --- a/src/svga_reg.h +++ b/src/svga_reg.h @@ -38,6 +38,15 @@ #define PCI_VENDOR_ID_VMWARE 0x15AD #define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405 +/* + * SVGA_REG_ENABLE bit definitions. + */ +#define SVGA_REG_ENABLE_DISABLE 0 +#define SVGA_REG_ENABLE_ENABLE 1 +#define SVGA_REG_ENABLE_HIDE 2 +#define SVGA_REG_ENABLE_ENABLE_HIDE (SVGA_REG_ENABLE_ENABLE |\ + SVGA_REG_ENABLE_HIDE) + /* * Legal values for the SVGA_REG_CURSOR_ON register in old-fashioned * cursor bypass mode. This is still supported, but no new guest @@ -161,7 +170,9 @@ enum { SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44, SVGA_REG_TRACES = 45, /* Enable trace-based updates even when FIFO is on */ - SVGA_REG_TOP = 46, /* Must be 1 more than the last register */ + SVGA_REG_GMRS_MAX_PAGES = 46, /* Maximum number of 4KB pages for all GMRs */ + SVGA_REG_MEMORY_SIZE = 47, /* Total dedicated device memory excluding FIFO */ + SVGA_REG_TOP = 48, /* Must be 1 more than the last register */ SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ /* Next 768 (== 256*3) registers exist for colormap */ @@ -276,7 +287,7 @@ enum { * possible. */ #define SVGA_GMR_NULL ((uint32) -1) -#define SVGA_GMR_FRAMEBUFFER ((uint32) -2) // Guest Framebuffer (GFB) +#define SVGA_GMR_FRAMEBUFFER ((uint32) -2) /* Guest Framebuffer (GFB) */ typedef struct SVGAGuestMemDescriptor { @@ -317,13 +328,35 @@ struct SVGAGMRImageFormat { struct { uint32 bitsPerPixel : 8; uint32 colorDepth : 8; - uint32 reserved : 16; // Must be zero + uint32 reserved : 16; /* Must be zero */ }; uint32 value; }; } SVGAGMRImageFormat; +typedef +struct SVGAGuestImage { + SVGAGuestPtr ptr; + + /* + * A note on interpretation of pitch: This value of pitch is the + * number of bytes between vertically adjacent image + * blocks. Normally this is the number of bytes between the first + * pixel of two adjacent scanlines. With compressed textures, + * however, this may represent the number of bytes between + * compression blocks rather than between rows of pixels. + * + * XXX: Compressed textures currently must be tightly packed in guest memory. + * + * If the image is 1-dimensional, pitch is ignored. + * + * If 'pitch' is zero, the SVGA3D device calculates a pitch value + * assuming each row of blocks is tightly packed. + */ + uint32 pitch; +} SVGAGuestImage; + /* * SVGAColorBGRX -- * @@ -339,7 +372,7 @@ struct SVGAColorBGRX { uint32 b : 8; uint32 g : 8; uint32 r : 8; - uint32 x : 8; // Unused + uint32 x : 8; /* Unused */ }; uint32 value; @@ -381,23 +414,34 @@ struct SVGASignedPoint { * Note the holes in the bitfield. Missing bits have been deprecated, * and must not be reused. Those capabilities will never be reported * by new versions of the SVGA device. + * + * SVGA_CAP_GMR2 -- + * Provides asynchronous commands to define and remap guest memory + * regions. Adds device registers SVGA_REG_GMRS_MAX_PAGES and + * SVGA_REG_MEMORY_SIZE. + * + * SVGA_CAP_SCREEN_OBJECT_2 -- + * Allow screen object support, and require backing stores from the + * guest for each screen object. */ #define SVGA_CAP_NONE 0x00000000 #define SVGA_CAP_RECT_COPY 0x00000002 #define SVGA_CAP_CURSOR 0x00000020 -#define SVGA_CAP_CURSOR_BYPASS 0x00000040 // Legacy (Use Cursor Bypass 3 instead) -#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 // Legacy (Use Cursor Bypass 3 instead) +#define SVGA_CAP_CURSOR_BYPASS 0x00000040 /* Legacy (Use Cursor Bypass 3 instead) */ +#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 /* Legacy (Use Cursor Bypass 3 instead) */ #define SVGA_CAP_8BIT_EMULATION 0x00000100 #define SVGA_CAP_ALPHA_CURSOR 0x00000200 #define SVGA_CAP_3D 0x00004000 #define SVGA_CAP_EXTENDED_FIFO 0x00008000 -#define SVGA_CAP_MULTIMON 0x00010000 // Legacy multi-monitor support +#define SVGA_CAP_MULTIMON 0x00010000 /* Legacy multi-monitor support */ #define SVGA_CAP_PITCHLOCK 0x00020000 #define SVGA_CAP_IRQMASK 0x00040000 -#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 // Legacy multi-monitor support +#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 /* Legacy multi-monitor support */ #define SVGA_CAP_GMR 0x00100000 #define SVGA_CAP_TRACES 0x00200000 +#define SVGA_CAP_GMR2 0x00400000 +#define SVGA_CAP_SCREEN_OBJECT_2 0x00800000 /* @@ -442,7 +486,7 @@ enum { SVGA_FIFO_CAPABILITIES = 4, SVGA_FIFO_FLAGS, - // Valid with SVGA_FIFO_CAP_FENCE: + /* Valid with SVGA_FIFO_CAP_FENCE: */ SVGA_FIFO_FENCE, /* @@ -455,32 +499,46 @@ enum { * extended FIFO. */ - // Valid if exists (i.e. if extended FIFO enabled): + /* Valid if exists (i.e. if extended FIFO enabled): */ SVGA_FIFO_3D_HWVERSION, /* See SVGA3dHardwareVersion in svga3d_reg.h */ - // Valid with SVGA_FIFO_CAP_PITCHLOCK: + /* Valid with SVGA_FIFO_CAP_PITCHLOCK: */ SVGA_FIFO_PITCHLOCK, - // Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: + /* Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: */ SVGA_FIFO_CURSOR_ON, /* Cursor bypass 3 show/hide register */ SVGA_FIFO_CURSOR_X, /* Cursor bypass 3 x register */ SVGA_FIFO_CURSOR_Y, /* Cursor bypass 3 y register */ SVGA_FIFO_CURSOR_COUNT, /* Incremented when any of the other 3 change */ SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */ - // Valid with SVGA_FIFO_CAP_RESERVE: + /* Valid with SVGA_FIFO_CAP_RESERVE: */ SVGA_FIFO_RESERVED, /* Bytes past NEXT_CMD with real contents */ /* - * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT: + * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2: * * By default this is SVGA_ID_INVALID, to indicate that the cursor * coordinates are specified relative to the virtual root. If this * is set to a specific screen ID, cursor position is reinterpreted - * as a signed offset relative to that screen's origin. This is the - * only way to place the cursor on a non-rooted screen. + * as a signed offset relative to that screen's origin. */ SVGA_FIFO_CURSOR_SCREEN_ID, + /* + * Valid with SVGA_FIFO_CAP_DEAD + * + * An arbitrary value written by the host, drivers should not use it. + */ + SVGA_FIFO_DEAD, + + /* + * Valid with SVGA_FIFO_CAP_3D_HWVERSION_REVISED: + * + * Contains 3D HWVERSION (see SVGA3dHardwareVersion in svga3d_reg.h) + * on platforms that can enforce graphics resource limits. + */ + SVGA_FIFO_3D_HWVERSION_REVISED, + /* * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new * registers, but this must be done carefully and with judicious use of @@ -519,7 +577,7 @@ enum { * sets SVGA_FIFO_MIN high enough to leave room for them. */ - // Valid if register exists: + /* Valid if register exists: */ SVGA_FIFO_GUEST_3D_HWVERSION, /* Guest driver's 3D version */ SVGA_FIFO_FENCE_GOAL, /* Matching target for SVGA_IRQFLAG_FENCE_GOAL */ SVGA_FIFO_BUSY, /* See "FIFO Synchronization Registers" */ @@ -720,6 +778,37 @@ enum { * * - When a screen is resized, either using Screen Object commands or * legacy multimon registers, its contents are preserved. + * + * SVGA_FIFO_CAP_GMR2 -- + * + * Provides new commands to define and remap guest memory regions (GMR). + * + * New 2D commands: + * DEFINE_GMR2, REMAP_GMR2. + * + * SVGA_FIFO_CAP_3D_HWVERSION_REVISED -- + * + * Indicates new register SVGA_FIFO_3D_HWVERSION_REVISED exists. + * This register may replace SVGA_FIFO_3D_HWVERSION on platforms + * that enforce graphics resource limits. This allows the platform + * to clear SVGA_FIFO_3D_HWVERSION and disable 3D in legacy guest + * drivers that do not limit their resources. + * + * Note this is an alias to SVGA_FIFO_CAP_GMR2 because these indicators + * are codependent (and thus we use a single capability bit). + * + * SVGA_FIFO_CAP_SCREEN_OBJECT_2 -- + * + * Modifies the DEFINE_SCREEN command to include a guest provided + * backing store in GMR memory and the bytesPerLine for the backing + * store. This capability requires the use of a backing store when + * creating screen objects. However if SVGA_FIFO_CAP_SCREEN_OBJECT + * is present then backing stores are optional. + * + * SVGA_FIFO_CAP_DEAD -- + * + * Drivers should not use this cap bit. This cap bit can not be + * reused since some hosts already expose it. */ #define SVGA_FIFO_CAP_NONE 0 @@ -731,6 +820,10 @@ enum { #define SVGA_FIFO_CAP_ESCAPE (1<<5) #define SVGA_FIFO_CAP_RESERVE (1<<6) #define SVGA_FIFO_CAP_SCREEN_OBJECT (1<<7) +#define SVGA_FIFO_CAP_GMR2 (1<<8) +#define SVGA_FIFO_CAP_3D_HWVERSION_REVISED SVGA_FIFO_CAP_GMR2 +#define SVGA_FIFO_CAP_SCREEN_OBJECT_2 (1<<9) +#define SVGA_FIFO_CAP_DEAD (1<<10) /* @@ -741,7 +834,7 @@ enum { #define SVGA_FIFO_FLAG_NONE 0 #define SVGA_FIFO_FLAG_ACCELFRONT (1<<0) -#define SVGA_FIFO_FLAG_RESERVED (1<<31) // Internal use only +#define SVGA_FIFO_FLAG_RESERVED (1<<31) /* Internal use only */ /* * FIFO reservation sentinel value @@ -774,22 +867,22 @@ enum { SVGA_VIDEO_DATA_OFFSET, SVGA_VIDEO_FORMAT, SVGA_VIDEO_COLORKEY, - SVGA_VIDEO_SIZE, // Deprecated + SVGA_VIDEO_SIZE, /* Deprecated */ SVGA_VIDEO_WIDTH, SVGA_VIDEO_HEIGHT, SVGA_VIDEO_SRC_X, SVGA_VIDEO_SRC_Y, SVGA_VIDEO_SRC_WIDTH, SVGA_VIDEO_SRC_HEIGHT, - SVGA_VIDEO_DST_X, // Signed int32 - SVGA_VIDEO_DST_Y, // Signed int32 + SVGA_VIDEO_DST_X, /* Signed int32 */ + SVGA_VIDEO_DST_Y, /* Signed int32 */ SVGA_VIDEO_DST_WIDTH, SVGA_VIDEO_DST_HEIGHT, SVGA_VIDEO_PITCH_1, SVGA_VIDEO_PITCH_2, SVGA_VIDEO_PITCH_3, - SVGA_VIDEO_DATA_GMRID, // Optional, defaults to SVGA_GMR_FRAMEBUFFER - SVGA_VIDEO_DST_SCREEN_ID, // Optional, defaults to virtual coords (SVGA_ID_INVALID) + SVGA_VIDEO_DATA_GMRID, /* Optional, defaults to SVGA_GMR_FRAMEBUFFER */ + SVGA_VIDEO_DST_SCREEN_ID, /* Optional, defaults to virtual coords (SVGA_ID_INVALID) */ SVGA_VIDEO_NUM_REGS }; @@ -840,15 +933,51 @@ typedef struct SVGAOverlayUnit { * compatibility. New flags can be added, and the struct may grow, * but existing fields must retain their meaning. * + * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2 are required fields of + * a SVGAGuestPtr that is used to back the screen contents. This + * memory must come from the GFB. The guest is not allowed to + * access the memory and doing so will have undefined results. The + * backing store is required to be page aligned and the size is + * padded to the next page boundry. The number of pages is: + * (bytesPerLine * size.width * 4 + PAGE_SIZE - 1) / PAGE_SIZE + * + * The pitch in the backingStore is required to be at least large + * enough to hold a 32bbp scanline. It is recommended that the + * driver pad bytesPerLine for a potential performance win. + * + * The cloneCount field is treated as a hint from the guest that + * the user wants this display to be cloned, countCount times. A + * value of zero means no cloning should happen. + */ + +#define SVGA_SCREEN_MUST_BE_SET (1 << 0) /* Must be set or results undefined */ +#define SVGA_SCREEN_HAS_ROOT SVGA_SCREEN_MUST_BE_SET /* Deprecated */ +#define SVGA_SCREEN_IS_PRIMARY (1 << 1) /* Guest considers this screen to be 'primary' */ +#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) /* Guest is running a fullscreen app here */ + +/* + * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When the screen is + * deactivated the base layer is defined to lose all contents and + * become black. When a screen is deactivated the backing store is + * optional. When set backingPtr and bytesPerLine will be ignored. */ +#define SVGA_SCREEN_DEACTIVATE (1 << 3) -#define SVGA_SCREEN_HAS_ROOT (1 << 0) // Screen is present in the virtual coord space -#define SVGA_SCREEN_IS_PRIMARY (1 << 1) // Guest considers this screen to be 'primary' -#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) // Guest is running a fullscreen app here +/* + * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When this flag is set + * the screen contents will be outputted as all black to the user + * though the base layer contents is preserved. The screen base layer + * can still be read and written to like normal though the no visible + * effect will be seen by the user. When the flag is changed the + * screen will be blanked or redrawn to the current contents as needed + * without any extra commands from the driver. This flag only has an + * effect when the screen is not deactivated. + */ +#define SVGA_SCREEN_BLANKING (1 << 4) typedef struct SVGAScreenObject { - uint32 structSize; // sizeof(SVGAScreenObject) + uint32 structSize; /* sizeof(SVGAScreenObject) */ uint32 id; uint32 flags; struct { @@ -858,7 +987,14 @@ struct SVGAScreenObject { struct { int32 x; int32 y; - } root; // Only used if SVGA_SCREEN_HAS_ROOT is set. + } root; + + /* + * Added and required by SVGA_FIFO_CAP_SCREEN_OBJECT_2, optional + * with SVGA_FIFO_CAP_SCREEN_OBJECT. + */ + SVGAGuestImage backingStore; + uint32 cloneCount; } SVGAScreenObject; @@ -896,6 +1032,8 @@ typedef enum { SVGA_CMD_BLIT_SCREEN_TO_GMRFB = 38, SVGA_CMD_ANNOTATION_FILL = 39, SVGA_CMD_ANNOTATION_COPY = 40, + SVGA_CMD_DEFINE_GMR2 = 41, + SVGA_CMD_REMAP_GMR2 = 42, SVGA_CMD_MAX } SVGAFifoCmdId; @@ -931,7 +1069,7 @@ typedef enum { */ typedef -struct { +struct SVGAFifoCmdUpdate { uint32 x; uint32 y; uint32 width; @@ -950,7 +1088,7 @@ struct { */ typedef -struct { +struct SVGAFifoCmdRectCopy { uint32 srcX; uint32 srcY; uint32 destX; @@ -974,14 +1112,14 @@ struct { */ typedef -struct { - uint32 id; // Reserved, must be zero. +struct SVGAFifoCmdDefineCursor { + uint32 id; /* Reserved, must be zero. */ uint32 hotspotX; uint32 hotspotY; uint32 width; uint32 height; - uint32 andMaskDepth; // Value must be 1 or equal to BITS_PER_PIXEL - uint32 xorMaskDepth; // Value must be 1 or equal to BITS_PER_PIXEL + uint32 andMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */ + uint32 xorMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */ /* * Followed by scanline data for AND mask, then XOR mask. * Each scanline is padded to a 32-bit boundary. @@ -1003,8 +1141,8 @@ struct { */ typedef -struct { - uint32 id; // Reserved, must be zero. +struct SVGAFifoCmdDefineAlphaCursor { + uint32 id; /* Reserved, must be zero. */ uint32 hotspotX; uint32 hotspotY; uint32 width; @@ -1026,7 +1164,7 @@ struct { */ typedef -struct { +struct SVGAFifoCmdUpdateVerbose { uint32 x; uint32 y; uint32 width; @@ -1053,13 +1191,13 @@ struct { #define SVGA_INVALID_DISPLAY_ID ((uint32)-1) typedef -struct { - uint32 color; // In the same format as the GFB +struct SVGAFifoCmdFrontRopFill { + uint32 color; /* In the same format as the GFB */ uint32 x; uint32 y; uint32 width; uint32 height; - uint32 rop; // Must be SVGA_ROP_COPY + uint32 rop; /* Must be SVGA_ROP_COPY */ } SVGAFifoCmdFrontRopFill; @@ -1096,7 +1234,7 @@ struct { */ typedef -struct { +struct SVGAFifoCmdEscape { uint32 nsid; uint32 size; /* followed by 'size' bytes of data */ @@ -1126,12 +1264,12 @@ struct { * registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*). * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 */ typedef struct { - SVGAScreenObject screen; // Variable-length according to version + SVGAScreenObject screen; /* Variable-length according to version */ } SVGAFifoCmdDefineScreen; @@ -1142,7 +1280,7 @@ struct { * re-use. * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 */ typedef @@ -1195,7 +1333,7 @@ struct { * GMRFB. * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 */ typedef @@ -1232,7 +1370,7 @@ struct { * SVGA_CMD_ANNOTATION_* commands for details. * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 */ typedef @@ -1280,7 +1418,7 @@ struct { * the time any subsequent FENCE commands are reached. * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 */ typedef @@ -1315,7 +1453,7 @@ struct { * user's display is being remoted over a network connection. * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 */ typedef @@ -1347,7 +1485,7 @@ struct { * undefined. * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 */ typedef @@ -1356,4 +1494,72 @@ struct { uint32 srcScreenId; } SVGAFifoCmdAnnotationCopy; + +/* + * SVGA_CMD_DEFINE_GMR2 -- + * + * Define guest memory region v2. See the description of GMRs above. + * + * Availability: + * SVGA_CAP_GMR2 + */ + +typedef +struct { + uint32 gmrId; + uint32 numPages; +} SVGAFifoCmdDefineGMR2; + + +/* + * SVGA_CMD_REMAP_GMR2 -- + * + * Remap guest memory region v2. See the description of GMRs above. + * + * This command allows guest to modify a portion of an existing GMR by + * invalidating it or reassigning it to different guest physical pages. + * The pages are identified by physical page number (PPN). The pages + * are assumed to be pinned and valid for DMA operations. + * + * Description of command flags: + * + * SVGA_REMAP_GMR2_VIA_GMR: If enabled, references a PPN list in a GMR. + * The PPN list must not overlap with the remap region (this can be + * handled trivially by referencing a separate GMR). If flag is + * disabled, PPN list is appended to SVGARemapGMR command. + * + * SVGA_REMAP_GMR2_PPN64: If set, PPN list is in PPN64 format, otherwise + * it is in PPN32 format. + * + * SVGA_REMAP_GMR2_SINGLE_PPN: If set, PPN list contains a single entry. + * A single PPN can be used to invalidate a portion of a GMR or + * map it to to a single guest scratch page. + * + * Availability: + * SVGA_CAP_GMR2 + */ + +typedef enum { + SVGA_REMAP_GMR2_PPN32 = 0, + SVGA_REMAP_GMR2_VIA_GMR = (1 << 0), + SVGA_REMAP_GMR2_PPN64 = (1 << 1), + SVGA_REMAP_GMR2_SINGLE_PPN = (1 << 2), +} SVGARemapGMR2Flags; + +typedef +struct { + uint32 gmrId; + SVGARemapGMR2Flags flags; + uint32 offsetPages; /* offset in pages to begin remap */ + uint32 numPages; /* number of pages to remap */ + /* + * Followed by additional data depending on SVGARemapGMR2Flags. + * + * If flag SVGA_REMAP_GMR2_VIA_GMR is set, single SVGAGuestPtr follows. + * Otherwise an array of page descriptors in PPN32 or PPN64 format + * (according to flag SVGA_REMAP_GMR2_PPN64) follows. If flag + * SVGA_REMAP_GMR2_SINGLE_PPN is set, array contains a single entry. + */ +} SVGAFifoCmdRemapGMR2; + #endif -- cgit v1.2.3 From da29c648051208b98704860f851564a80bd3b123 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 22 Nov 2011 21:06:24 +0100 Subject: vmwgfx: Pre-init fixes A bunch of fixes that makes the fallback from vmwgfx to vmwlegacy easier. 1) Allow only 16 and 24 bit depths with vmwgfx. We may revisit this later. 2) Try to reclaim some resources if pre_init fails. 3) Print error messages so the user understands what happens on fallback. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_dri2.c | 2 - vmwgfx/vmwgfx_driver.c | 145 +++++++++++++++++++++++++++---------------------- vmwgfx/vmwgfx_drmi.c | 2 +- vmwgfx/vmwgfx_drmi.h | 2 + 4 files changed, 82 insertions(+), 69 deletions(-) diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index ddeaf1d..1fb5d0d 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -43,7 +43,6 @@ #include "vmwgfx_saa.h" #include "wsbm_util.h" -#ifdef DRI2 typedef struct { int refcount; PixmapPtr pPixmap; @@ -393,6 +392,5 @@ xorg_dri2_close(ScreenPtr pScreen) { DRI2CloseScreen(pScreen); } -#endif /* vim: set sw=4 ts=8 sts=4: */ diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index 69fef8c..889dae1 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -30,6 +30,7 @@ */ +#include #include "xorg-server.h" #include "xf86.h" #include "xf86_OSproc.h" @@ -60,6 +61,22 @@ #include "vmwgfx_saa.h" #include "../src/vmware_bootstrap.h" +/* + * We can't incude svga_types.h due to conflicting types for Bool. + */ +typedef int64_t int64; +typedef uint64_t uint64; + +typedef int32_t int32; +typedef uint32_t uint32; + +typedef int16_t int16; +typedef uint16_t uint16; + +typedef int8_t int8; +typedef uint8_t uint8; +#include "./src/svga_reg.h" + #define XA_VERSION_MINOR_REQUIRED 0 #define DRM_VERSION_MAJOR_REQUIRED 2 #define DRM_VERSION_MINOR_REQUIRED 3 @@ -254,6 +271,9 @@ drv_init_drm(ScrnInfoPtr pScrn) return TRUE; } + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to open drm.\n"); + return FALSE; } @@ -267,7 +287,7 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) modesettingPtr ms; rgb defaultWeight = { 0, 0, 0 }; EntityInfoPtr pEnt; - EntPtr msEnt = NULL; + uint64_t cap; if (pScrn->numEntities != 1) return FALSE; @@ -282,43 +302,28 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) pScrn->driverPrivate = NULL; /* Allocate driverPrivate */ - if (!drv_get_rec(pScrn)) - return FALSE; + if (!drv_get_rec(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate driver private.\n"); + } ms = modesettingPTR(pScrn); ms->pEnt = pEnt; pScrn->displayWidth = 640; /* default it */ - if (ms->pEnt->location.type != BUS_PCI) - return FALSE; + if (ms->pEnt->location.type != BUS_PCI) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Incorrect bus for device.\n"); + goto out_err_bus; + } ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index); - - /* Allocate an entity private if necessary */ - if (xf86IsEntityShared(pScrn->entityList[0])) { - FatalError("Entity"); -#if 0 - msEnt = xf86GetEntityPrivate(pScrn->entityList[0], - modesettingEntityIndex)->ptr; - ms->entityPrivate = msEnt; -#else - (void)msEnt; -#endif - } else - ms->entityPrivate = NULL; - - if (xf86IsEntityShared(pScrn->entityList[0])) { - if (xf86IsPrimInitDone(pScrn->entityList[0])) { - /* do something */ - } else { - xf86SetPrimInitDone(pScrn->entityList[0]); - } - } + xf86SetPrimInitDone(pScrn->entityList[0]); ms->fd = -1; if (!drv_init_drm(pScrn)) - return FALSE; + goto out_err_bus; if (ms->drm_major != DRM_VERSION_MAJOR_REQUIRED || ms->drm_minor < DRM_VERSION_MINOR_REQUIRED) { @@ -326,10 +331,11 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) "DRM driver version is %d.%d.%d\n", ms->drm_major, ms->drm_minor, ms->drm_patch); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "But this driver needs %d.%d.x to work. Giving up.\n", + "But KMS- and 3D functionality needs at least " + "%d.%d.0 to work.\n", DRM_VERSION_MAJOR_REQUIRED, DRM_VERSION_MINOR_REQUIRED); - return FALSE; + goto out_drm_version; } else { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DRM driver version is %d.%d.%d\n", @@ -344,32 +350,45 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) if (!xf86SetDepthBpp (pScrn, 0, 0, 0, - PreferConvert24to32 | SupportConvert24to32 | Support32bppFb)) - return FALSE; + PreferConvert24to32 | SupportConvert24to32 | Support32bppFb)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set depth and bpp.\n"); + goto out_depth; + } + + if (vmwgfx_get_param(ms->fd, DRM_VMW_PARAM_HW_CAPS, &cap) != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to detect device " + "screen object capability.\n"); + goto out_depth; + } + + if ((cap & SVGA_CAP_SCREEN_OBJECT_2) == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Device is not screen object " + "capable.\n"); + goto out_depth; + } switch (pScrn->depth) { - case 8: case 15: case 16: case 24: break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Given depth (%d) is not supported by the driver\n", + "Given depth (%d) is not supported with KMS enabled.\n", pScrn->depth); - return FALSE; + goto out_depth; } xf86PrintDepthBpp(pScrn); if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) - return FALSE; + goto out_depth; if (!xf86SetDefaultVisual(pScrn, -1)) - return FALSE; + goto out_depth; /* Process the options */ xf86CollectOptions(pScrn, NULL); if (!(ms->Options = VMWARECopyOptions())) - return FALSE; + goto out_depth; xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options); ms->accelerate_render = TRUE; @@ -405,18 +424,6 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) max_width = res->max_width; max_height = res->max_height; -#if 0 /* Gallium fix */ - if (ms->screen) { - int max; - - max = ms->screen->get_param(ms->screen, - PIPE_CAP_MAX_TEXTURE_2D_LEVELS); - max = 1 << (max - 1); - max_width = max < max_width ? max : max_width; - max_height = max < max_height ? max : max_height; - } -#endif - xf86CrtcSetSizeRange(pScrn, res->min_width, res->min_height, max_width, max_height); xf86DrvMsg(pScrn->scrnIndex, X_PROBED, @@ -439,7 +446,7 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) ms->initialization = TRUE; if (!xf86InitialConfiguration(pScrn, TRUE)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); - return FALSE; + goto out_modes; } ms->initialization = FALSE; @@ -450,13 +457,14 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) Gamma zeros = { 0.0, 0.0, 0.0 }; if (!xf86SetGamma(pScrn, zeros)) { - return FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set gamma.\n"); + goto out_modes; } } if (pScrn->modes == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); - return FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No available modes.\n"); + goto out_modes; } pScrn->currentMode = pScrn->modes; @@ -465,18 +473,27 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) xf86SetDpi(pScrn, 0, 0); /* Load the required sub modules */ - if (!xf86LoadSubModule(pScrn, "fb")) - return FALSE; + if (!xf86LoadSubModule(pScrn, "fb")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load fb module.\n"); + goto out_modes; + } -#ifdef DRI2 - if (!xf86LoadSubModule(pScrn, "dri2")) - return FALSE; -#else - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Driver compiled without dri2 support." -#endif + if (!xf86LoadSubModule(pScrn, "dri2")) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load dri2 module.\n"); + goto out_modes; + } return TRUE; + + out_modes: + free(ms->Options); + out_depth: + out_drm_version: + close(ms->fd); + out_err_bus: + drv_free_rec(pScrn); + return FALSE; + } static Bool @@ -908,7 +925,6 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) FatalError("Failed to initialize SAA.\n"); } -#ifdef DRI2 ms->dri2_available = FALSE; if (ms->enable_dri) { if (ms->xat) { @@ -923,7 +939,6 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) ms->from_dri = X_PROBED; } } -#endif xf86DrvMsg(pScrn->scrnIndex, ms->from_render, "Render acceleration is %s.\n", (ms->xat != NULL) ? "enabled" : "disabled"); @@ -1061,10 +1076,8 @@ drv_close_screen(int scrnIndex, ScreenPtr pScreen) ms->cursor = NULL; } -#ifdef DRI2 if (ms->dri2_available) xorg_dri2_close(pScreen); -#endif if (pScrn->vtSema) pScrn->LeaveVT(scrnIndex, 0); diff --git a/vmwgfx/vmwgfx_drmi.c b/vmwgfx/vmwgfx_drmi.c index cc595ab..e326d31 100644 --- a/vmwgfx/vmwgfx_drmi.c +++ b/vmwgfx/vmwgfx_drmi.c @@ -386,7 +386,7 @@ vmwgfx_dma(unsigned int host_x, unsigned int host_y, return 0; } -static int +int vmwgfx_get_param(int drm_fd, uint32_t param, uint64_t *out) { struct drm_vmw_getparam_arg gp_arg; diff --git a/vmwgfx/vmwgfx_drmi.h b/vmwgfx/vmwgfx_drmi.h index 11abf25..2435009 100644 --- a/vmwgfx/vmwgfx_drmi.h +++ b/vmwgfx/vmwgfx_drmi.h @@ -82,4 +82,6 @@ vmwgfx_max_fb_size(int drm_fd, size_t *size); int vmwgfx_update_gui_layout(int drm_fd, unsigned int num_rects, struct drm_vmw_rect *rects); +int +vmwgfx_get_param(int drm_fd, uint32_t param, uint64_t *out); #endif -- cgit v1.2.3 From 31e80b2a609631d85341025d7f2d0fb818f386f5 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 25 Nov 2011 09:42:16 +0100 Subject: vmware: Update library dependencies Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- src/Makefile.am | 1 + vmwgfx/Makefile.am | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 60bc15a..efb962f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,6 +29,7 @@ vmware_drv_la_LDFLAGS = -module -avoid-version vmware_drv_la_CFLAGS = @XORG_CFLAGS@ vmware_drv_ladir = @moduledir@/drivers vmware_drv_la_LIBADD = @VMWGFX_LIBADD@ +vmware_drv_la_DEPENDENCIES = @VMWGFX_LIBADD@ vmware_drv_la_SOURCES = \ bits2pixels.c \ diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am index 8fe3e71..1ee6582 100644 --- a/vmwgfx/Makefile.am +++ b/vmwgfx/Makefile.am @@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libvmwgfx.la libvmwgfx_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) @LIBDRM_CFLAGS@ @XATRACKER_CFLAGS@ -I$(top_srcdir)/src -I$(top_srcdir)/saa libvmwgfx_la_LIBADD = @LIBDRM_LIBS@ $(top_srcdir)/saa/libsaa.la\ @XATRACKER_LIBS@ +libvmwgfx_la_DEPENDENCIES = $(top_srcdir)/saa/libsaa.la libvmwgfx_la_SOURCES = \ vmwgfx_driver.c \ -- cgit v1.2.3 From 2e8aac7031a83f507169f6fe42924c51bdaf7326 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 23 Nov 2011 10:49:33 +0100 Subject: vmwlegacy: Accept option "GuiLayout" as a synonym for "staticXinerama" It's more user-friendly and in line with what it's being used for in the vmwgfx driver. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- src/vmware.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/vmware.c b/src/vmware.c index 0f3e36f..70c6730 100644 --- a/src/vmware.c +++ b/src/vmware.c @@ -344,13 +344,15 @@ VMWAREParseTopologyElement(ScrnInfoPtr pScrn, static xXineramaScreenInfo * VMWAREParseTopologyString(ScrnInfoPtr pScrn, const char *topology, - unsigned int *retNumOutputs) + unsigned int *retNumOutputs, + const char info[]) { xXineramaScreenInfo *extents = NULL; unsigned int numOutputs = 0; const char *str = topology; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Starting...\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Starting...\n", + info); do { unsigned int x, y, width, height; @@ -391,11 +393,13 @@ VMWAREParseTopologyString(ScrnInfoPtr pScrn, extents[numOutputs - 1].height = height; } while (*str != 0); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Succeeded.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Succeeded.\n", + info); goto exit; error: - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Failed.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Failed.\n", + info); free(extents); extents = NULL; @@ -1435,11 +1439,25 @@ VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } - if (useXinerama && xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) { + if (useXinerama && xf86IsOptionSet(options, OPTION_GUI_LAYOUT)) { + char *topology = xf86GetOptValString(options, OPTION_GUI_LAYOUT); + if (topology) { + pVMWARE->xineramaState = + VMWAREParseTopologyString(pScrn, topology, + &pVMWARE->xineramaNumOutputs, "gui"); + + pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL; + + free(topology); + } + } else if (useXinerama && + xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) { char *topology = xf86GetOptValString(options, OPTION_STATIC_XINERAMA); if (topology) { pVMWARE->xineramaState = - VMWAREParseTopologyString(pScrn, topology, &pVMWARE->xineramaNumOutputs); + VMWAREParseTopologyString(pScrn, topology, + &pVMWARE->xineramaNumOutputs, + "static Xinerama"); pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL; -- cgit v1.2.3 From 22d3e58b8810a73c4818d4d3943776a387147b83 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 23 Nov 2011 11:02:00 +0100 Subject: vmwlegacy: Factor out code that can be common for vmwgfx and vmwlegacy In this case it's the parsing of the gui / statix xinerama topology. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- src/Makefile.am | 4 +- src/vmware.c | 128 +---------------------------------------- src/vmware_common.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/vmware_common.h | 41 +++++++++++++ 4 files changed, 208 insertions(+), 128 deletions(-) create mode 100644 src/vmware_common.c create mode 100644 src/vmware_common.h diff --git a/src/Makefile.am b/src/Makefile.am index efb962f..64a9069 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,4 +54,6 @@ vmware_drv_la_SOURCES = \ vmwarevideo.c \ vmwaremodes.c \ vmware_bootstrap.h \ - vmware_bootstrap.c + vmware_bootstrap.c \ + vmware_common.c \ + vmware_common.h diff --git a/src/vmware.c b/src/vmware.c index 70c6730..3f5e486 100644 --- a/src/vmware.c +++ b/src/vmware.c @@ -40,6 +40,7 @@ char rcsId_vmware[] = #include "vm_device_version.h" #include "svga_modes.h" #include "vmware_bootstrap.h" +#include "vmware_common.h" #ifndef HAVE_XORG_SERVER_1_5_0 #include @@ -284,133 +285,6 @@ RewriteTagString(const char *istr, char *ostr, int osize) } #endif -static int -VMWAREParseTopologyElement(ScrnInfoPtr pScrn, - unsigned int output, - const char *elementName, - const char *element, - const char *expectedTerminators, - Bool needTerminator, - unsigned int *outValue) -{ - char buf[10] = {0, }; - size_t i = 0; - int retVal = -1; - const char *str = element; - - for (i = 0; str[i] >= '0' && str[i] <= '9'; i++); - if (i == 0) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: unable to parse %s.\n", - output, elementName); - goto exit; - } - - strncpy(buf, str, i); - *outValue = atoi(buf); - - if (*outValue > (unsigned short)-1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %s must be less than %hu.\n", - output, elementName, (unsigned short)-1); - goto exit; - } - - str += i; - - if (needTerminator || str[0] != '\0') { - Bool unexpected = TRUE; - - for (i = 0; i < strlen(expectedTerminators); i++) { - if (str[0] == expectedTerminators[i]) { - unexpected = FALSE; - } - } - - if (unexpected) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Output %u: unexpected character '%c' after %s.\n", - output, str[0], elementName); - goto exit; - } else { - str++; - } - } - - retVal = str - element; - - exit: - return retVal; -} - -static xXineramaScreenInfo * -VMWAREParseTopologyString(ScrnInfoPtr pScrn, - const char *topology, - unsigned int *retNumOutputs, - const char info[]) -{ - xXineramaScreenInfo *extents = NULL; - unsigned int numOutputs = 0; - const char *str = topology; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Starting...\n", - info); - - do { - unsigned int x, y, width, height; - int i; - - i = VMWAREParseTopologyElement(pScrn, numOutputs, "width", str, "xX", TRUE, &width); - if (i == -1) { - goto error; - } - str += i; - - i = VMWAREParseTopologyElement(pScrn, numOutputs, "height", str, "+", TRUE, &height); - if (i == -1) { - goto error; - } - str += i; - - i= VMWAREParseTopologyElement(pScrn, numOutputs, "X offset", str, "+", TRUE, &x); - if (i == -1) { - goto error; - } - str += i; - - i = VMWAREParseTopologyElement(pScrn, numOutputs, "Y offset", str, ";", FALSE, &y); - if (i == -1) { - goto error; - } - str += i; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %ux%u+%u+%u\n", - numOutputs, width, height, x, y); - - numOutputs++; - extents = realloc(extents, numOutputs * sizeof (xXineramaScreenInfo)); - extents[numOutputs - 1].x_org = x; - extents[numOutputs - 1].y_org = y; - extents[numOutputs - 1].width = width; - extents[numOutputs - 1].height = height; - } while (*str != 0); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Succeeded.\n", - info); - goto exit; - - error: - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Failed.\n", - info); - - free(extents); - extents = NULL; - numOutputs = 0; - - exit: - *retNumOutputs = numOutputs; - return extents; -} - - static Bool VMWAREPreInit(ScrnInfoPtr pScrn, int flags) { diff --git a/src/vmware_common.c b/src/vmware_common.c new file mode 100644 index 0000000..6ef7ca6 --- /dev/null +++ b/src/vmware_common.c @@ -0,0 +1,163 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Unknown at vmware + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "vmware_common.h" + +#ifndef HAVE_XORG_SERVER_1_5_0 +#include +#include +#endif + +static int +VMWAREParseTopologyElement(ScrnInfoPtr pScrn, + unsigned int output, + const char *elementName, + const char *element, + const char *expectedTerminators, + Bool needTerminator, + unsigned int *outValue) +{ + char buf[10] = {0, }; + size_t i = 0; + int retVal = -1; + const char *str = element; + + for (i = 0; str[i] >= '0' && str[i] <= '9'; i++); + if (i == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: unable to parse %s.\n", + output, elementName); + goto exit; + } + + strncpy(buf, str, i); + *outValue = atoi(buf); + + if (*outValue > (unsigned short)-1) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %s must be less than %hu.\n", + output, elementName, (unsigned short)-1); + goto exit; + } + + str += i; + + if (needTerminator || str[0] != '\0') { + Bool unexpected = TRUE; + + for (i = 0; i < strlen(expectedTerminators); i++) { + if (str[0] == expectedTerminators[i]) { + unexpected = FALSE; + } + } + + if (unexpected) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Output %u: unexpected character '%c' after %s.\n", + output, str[0], elementName); + goto exit; + } else { + str++; + } + } + + retVal = str - element; + + exit: + return retVal; +} + +xXineramaScreenInfo * +VMWAREParseTopologyString(ScrnInfoPtr pScrn, + const char *topology, + unsigned int *retNumOutputs, + const char info[]) +{ + xXineramaScreenInfo *extents = NULL; + unsigned int numOutputs = 0; + const char *str = topology; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Starting...\n", + info); + + do { + unsigned int x, y, width, height; + int i; + + i = VMWAREParseTopologyElement(pScrn, numOutputs, "width", str, "xX", TRUE, &width); + if (i == -1) { + goto error; + } + str += i; + + i = VMWAREParseTopologyElement(pScrn, numOutputs, "height", str, "+", TRUE, &height); + if (i == -1) { + goto error; + } + str += i; + + i= VMWAREParseTopologyElement(pScrn, numOutputs, "X offset", str, "+", TRUE, &x); + if (i == -1) { + goto error; + } + str += i; + + i = VMWAREParseTopologyElement(pScrn, numOutputs, "Y offset", str, ";", FALSE, &y); + if (i == -1) { + goto error; + } + str += i; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %ux%u+%u+%u\n", + numOutputs, width, height, x, y); + + numOutputs++; + extents = realloc(extents, numOutputs * sizeof (xXineramaScreenInfo)); + extents[numOutputs - 1].x_org = x; + extents[numOutputs - 1].y_org = y; + extents[numOutputs - 1].width = width; + extents[numOutputs - 1].height = height; + } while (*str != 0); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Succeeded.\n", + info); + goto exit; + + error: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Failed.\n", + info); + + free(extents); + extents = NULL; + numOutputs = 0; + + exit: + *retNumOutputs = numOutputs; + return extents; +} diff --git a/src/vmware_common.h b/src/vmware_common.h new file mode 100644 index 0000000..9cd7194 --- /dev/null +++ b/src/vmware_common.h @@ -0,0 +1,41 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Unknown at vmware + * Author: Thomas Hellstrom + */ + +#ifndef _VMWARE_COMMON_H_ +#define _VMWARE_COMMON_H_ + +#include +#include + +xXineramaScreenInfo * +VMWAREParseTopologyString(ScrnInfoPtr pScrn, + const char *topology, + unsigned int *retNumOutputs, + const char info[]); + +#endif -- cgit v1.2.3 From d7576c2c50dd0f3b7f70f97d9bde4e8b859e89e5 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 25 Nov 2011 11:27:26 +0100 Subject: vmwgfx: Use config options to optionally set GUI topology Use option "StaticXinerama" or "GuiLayout" to set initial GUI topology, similar to how these options are used with the legacy driver. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_driver.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++-- vmwgfx/vmwgfx_driver.h | 2 -- vmwgfx/vmwgfx_output.c | 20 +------------ 3 files changed, 79 insertions(+), 23 deletions(-) diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index 889dae1..fe98bca 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -60,6 +60,7 @@ #include #include "vmwgfx_saa.h" #include "../src/vmware_bootstrap.h" +#include "../src/vmware_common.h" /* * We can't incude svga_types.h due to conflicting types for Bool. @@ -280,6 +281,57 @@ drv_init_drm(ScrnInfoPtr pScrn) return TRUE; } +/** + * vmwgfx_set_topology - Set the GUI topology according to an option string + * + * @pScrn: Pointer to a ScrnInfo struct. + * @topology: String containing the topology description. + * @info: Info describing the option used to invoke this function. + * + * This function reads a GUI topology according from @topology, and + * calls into the kernel to set that topology. + */ +static Bool +vmwgfx_set_topology(ScrnInfoPtr pScrn, const char *topology, const char *info) +{ + modesettingPtr ms = modesettingPTR(pScrn); + unsigned int num_outputs; + xXineramaScreenInfo *screen_info; + struct drm_vmw_rect *rects; + int ret; + unsigned int i; + + screen_info = VMWAREParseTopologyString(pScrn, topology, &num_outputs, + info); + + if (screen_info == NULL) + return FALSE; + + rects = calloc(num_outputs, sizeof(*rects)); + if (rects == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate topology data.\n"); + goto out_no_rects; + } + + for(i = 0; i < num_outputs; ++i) { + rects[i].x = screen_info[i].x_org; + rects[i].y = screen_info[i].y_org; + rects[i].w = screen_info[i].width; + rects[i].h = screen_info[i].height; + } + + ret = vmwgfx_update_gui_layout(ms->fd, num_outputs, rects); + free(rects); + free(screen_info); + + return (ret == 0); + + out_no_rects: + free(screen_info); + return FALSE; +} + static Bool drv_pre_init(ScrnInfoPtr pScrn, int flags) { @@ -288,6 +340,7 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) rgb defaultWeight = { 0, 0, 0 }; EntityInfoPtr pEnt; uint64_t cap; + Bool ret = TRUE; if (pScrn->numEntities != 1) return FALSE; @@ -440,15 +493,38 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) ms->SWCursor = TRUE; } + if (xf86IsOptionSet(ms->Options, OPTION_GUI_LAYOUT)) { + char *topology = + xf86GetOptValString(ms->Options, OPTION_GUI_LAYOUT); + + ret = FALSE; + if (topology) { + ret = vmwgfx_set_topology(pScrn, topology, "gui"); + free(topology); + } + + } else if (xf86IsOptionSet(ms->Options, OPTION_STATIC_XINERAMA)) { + char *topology = + xf86GetOptValString(ms->Options, OPTION_STATIC_XINERAMA); + + ret = FALSE; + if (topology) { + ret = vmwgfx_set_topology(pScrn, topology, "static Xinerama"); + free(topology); + } + } + + if (!ret) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Falied parsing or setting " + "gui topology from config file.\n"); + xorg_crtc_init(pScrn); xorg_output_init(pScrn); - ms->initialization = TRUE; if (!xf86InitialConfiguration(pScrn, TRUE)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); goto out_modes; } - ms->initialization = FALSE; /* * If the driver can do gamma correction, it should call xf86SetGamma() here. diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h index d0d4e52..aaa95f1 100644 --- a/vmwgfx/vmwgfx_driver.h +++ b/vmwgfx/vmwgfx_driver.h @@ -120,8 +120,6 @@ typedef struct _modesettingRec #ifdef DRI2 Bool dri2_available; #endif - - Bool initialization; } modesettingRec, *modesettingPtr; #define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate)) diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c index 1a0835d..4f52f1d 100644 --- a/vmwgfx/vmwgfx_output.c +++ b/vmwgfx/vmwgfx_output.c @@ -109,25 +109,7 @@ output_detect(xf86OutputPtr output) switch (drm_connector->connection) { case DRM_MODE_CONNECTED: - /* - * Hack to avoid enabling outputs during the intial - * configuration that are connected but that we don't - * really want to have enabled just yet. - * - * If we are in initial config, and - * an output higher than Virtual1 is connected, - * and it has no monitor section in the config file, - * status will be reported as unknown, which means - * the xorg modesetting code will think it is - * disconnected. - */ - - if (ms->initialization && - drm_connector->connector_type_id != 1 && - !output->conf_monitor) - status = XF86OutputStatusUnknown; - else - status = XF86OutputStatusConnected; + status = XF86OutputStatusConnected; break; case DRM_MODE_DISCONNECTED: status = XF86OutputStatusDisconnected; -- cgit v1.2.3 From 08ca819238f2c2a0494b0bd8452393fc62907cc1 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 25 Nov 2011 14:38:45 +0100 Subject: vmwgfx: Get the drm device name from the open file descriptor Rather than hardcoding it. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_dri2.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index 1fb5d0d..cca686a 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -42,6 +42,7 @@ #include "gc.h" #include "vmwgfx_saa.h" #include "wsbm_util.h" +#include typedef struct { int refcount; @@ -363,6 +364,9 @@ xorg_dri2_init(ScreenPtr pScreen) modesettingPtr ms = modesettingPTR(pScrn); DRI2InfoRec dri2info; int major, minor; + char deviceName[80]; + char fdPath[80]; + ssize_t numChar; if (xf86LoaderCheckSymbol("DRI2Version")) { DRI2Version(&major, &minor); @@ -374,9 +378,24 @@ xorg_dri2_init(ScreenPtr pScreen) dri2info.version = min(DRI2INFOREC_VERSION, 3); dri2info.fd = ms->fd; - dri2info.driverName = "vmwgfx"; - dri2info.deviceName = "/dev/dri/card0"; /* FIXME */ + + /* + * This way of obtaining the DRM device name is a bit + * os-specific. It would be better to obtain it from + * drmOpen. Currently this works only for Linux. + */ + snprintf(fdPath, 80, "/proc/self/fd/%d", ms->fd); + numChar = readlink(fdPath, deviceName, 80); + if (numChar <= 0 || numChar >= 80) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not find the drm device name. Disabling dri2.\n"); + return FALSE; + } + deviceName[numChar] = 0; + dri2info.deviceName = deviceName; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Path of drm device is \"%s\".\n", deviceName); dri2info.CreateBuffer = dri2_create_buffer; dri2info.DestroyBuffer = dri2_destroy_buffer; -- cgit v1.2.3 From 995d86ceb0ae8cf2904100405ba6710c89f7f1b7 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 28 Nov 2011 14:51:36 +0100 Subject: vmwgfx: Make the drm device name persistent The DRI2 code doesn't copy the device name, but assumes the storage is persistent. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Reviewed-by: Alan Hourihane --- vmwgfx/vmwgfx_dri2.c | 18 ++++++++++-------- vmwgfx/vmwgfx_driver.h | 3 +++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index cca686a..3f9d00a 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -44,6 +44,8 @@ #include "wsbm_util.h" #include +#define VMWGFX_FD_PATH_LEN 80 + typedef struct { int refcount; PixmapPtr pPixmap; @@ -364,8 +366,7 @@ xorg_dri2_init(ScreenPtr pScreen) modesettingPtr ms = modesettingPTR(pScrn); DRI2InfoRec dri2info; int major, minor; - char deviceName[80]; - char fdPath[80]; + char fdPath[VMWGFX_FD_PATH_LEN]; ssize_t numChar; if (xf86LoaderCheckSymbol("DRI2Version")) { @@ -385,17 +386,18 @@ xorg_dri2_init(ScreenPtr pScreen) * os-specific. It would be better to obtain it from * drmOpen. Currently this works only for Linux. */ - snprintf(fdPath, 80, "/proc/self/fd/%d", ms->fd); - numChar = readlink(fdPath, deviceName, 80); - if (numChar <= 0 || numChar >= 80) { + memset(fdPath, 0, VMWGFX_FD_PATH_LEN); + snprintf(fdPath, VMWGFX_FD_PATH_LEN - 1, "/proc/self/fd/%d", ms->fd); + numChar = readlink(fdPath, ms->dri2_device_name, VMWGFX_DRI_DEVICE_LEN); + if (numChar <= 0 || numChar >= VMWGFX_DRI_DEVICE_LEN) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not find the drm device name. Disabling dri2.\n"); return FALSE; } - deviceName[numChar] = 0; - dri2info.deviceName = deviceName; + ms->dri2_device_name[numChar] = 0; + dri2info.deviceName = ms->dri2_device_name; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Path of drm device is \"%s\".\n", deviceName); + "Path of drm device is \"%s\".\n", ms->dri2_device_name); dri2info.CreateBuffer = dri2_create_buffer; dri2info.DestroyBuffer = dri2_destroy_buffer; diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h index aaa95f1..f6c9ec0 100644 --- a/vmwgfx/vmwgfx_driver.h +++ b/vmwgfx/vmwgfx_driver.h @@ -55,6 +55,8 @@ #define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg); #define debug_printf(...) +#define VMWGFX_DRI_DEVICE_LEN 80 + typedef struct { int lastInstance; @@ -119,6 +121,7 @@ typedef struct _modesettingRec struct xa_tracker *xat; #ifdef DRI2 Bool dri2_available; + char dri2_device_name[VMWGFX_DRI_DEVICE_LEN]; #endif } modesettingRec, *modesettingPtr; -- cgit v1.2.3 From 3c2486e05e98f2ff8f4e3d2633d91e14140a676e Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 1 Dec 2011 16:47:41 +0100 Subject: vmwgfx: Include drm.h from correct path Reviewed-by: Thomas Hellstrom Signed-off-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_drm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vmwgfx/vmwgfx_drm.h b/vmwgfx/vmwgfx_drm.h index f10f09e..906a41c 100644 --- a/vmwgfx/vmwgfx_drm.h +++ b/vmwgfx/vmwgfx_drm.h @@ -27,7 +27,7 @@ #ifndef __VMWGFX_DRM_H__ #define __VMWGFX_DRM_H__ -#include +#include #define DRM_VMW_MAX_SURFACE_FACES 6 #define DRM_VMW_MAX_MIP_LEVELS 24 -- cgit v1.2.3 From fb35176958bba2f86d6d466ccb7baadcff806512 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 5 Dec 2011 20:58:45 +0100 Subject: vmwgfx: Don't register back buffers as "hw_is_dri2_fronts" v2 That is reserved for dri2 front or fake front pixmaps that need immediate flushing of software contents to hardware. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_dri2.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index 3f9d00a..bf6e178 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -182,14 +182,16 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for return FALSE; srf = vpix->hw; + private->refcount++; + private->dri2_depth = depth; /* * Compiz workaround. See vmwgfx_dirty(); */ - vpix->hw_is_dri2_fronts++; - private->refcount++; - private->dri2_depth = depth; + if (buffer->attachment == DRI2BufferFrontLeft || + buffer->attachment == DRI2BufferFakeFrontLeft) + vpix->hw_is_dri2_fronts++; } private->srf = srf; @@ -211,6 +213,7 @@ dri2_do_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer) BufferPrivatePtr private = buffer->driverPrivate; struct xa_surface *srf = private->srf; ScreenPtr pScreen = pDraw->pScreen; + struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(private->pPixmap); if (--private->refcount == 0 && srf) { xa_surface_destroy(srf); @@ -220,11 +223,11 @@ dri2_do_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer) * Compiz workaround. See vmwgfx_dirty(); */ - if (private->refcount == 1) { - struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(private->pPixmap); - if (--vpix->hw_is_dri2_fronts == 0) - WSBMLISTDELINIT(&vpix->sync_x_head); - } + if ((buffer->attachment == DRI2BufferFrontLeft || + buffer->attachment == DRI2BufferFakeFrontLeft) && + private->refcount == 1 && + --vpix->hw_is_dri2_fronts == 0) + WSBMLISTDELINIT(&vpix->sync_x_head); private->srf = NULL; pScreen->DestroyPixmap(private->pPixmap); -- cgit v1.2.3 From 1736a76246f0a0dab01f5a1066332168d34b2803 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 6 Dec 2011 09:21:25 +0100 Subject: vmwgfx: Adapt to the dri state tracker sending depth instead of bpp Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_dri2.c | 14 ++++++++++---- vmwgfx/vmwgfx_xa_surface.c | 3 ++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c index bf6e178..1b82ac4 100644 --- a/vmwgfx/vmwgfx_dri2.c +++ b/vmwgfx/vmwgfx_dri2.c @@ -157,10 +157,16 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int for case DRI2BufferDepth: depth = (format) ? vmwgfx_z_format_to_depth(format) : pDraw->bitsPerPixel; - srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height, - depth, - xa_type_z, xa_format_unknown, - XA_FLAG_SHARED); + + if (depth == 24) + srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height, + depth, xa_type_zs, xa_format_unknown, + XA_FLAG_SHARED ); + else + srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height, + depth, + xa_type_z, xa_format_unknown, + XA_FLAG_SHARED); if (!srf) return FALSE; diff --git a/vmwgfx/vmwgfx_xa_surface.c b/vmwgfx/vmwgfx_xa_surface.c index 7542413..2a18762 100644 --- a/vmwgfx/vmwgfx_xa_surface.c +++ b/vmwgfx/vmwgfx_xa_surface.c @@ -225,8 +225,9 @@ vmwgfx_choose_accel_format(unsigned int depth) { switch(depth) { case 32: - case 24: return xa_format_a8r8g8b8; + case 24: + return xa_format_x8r8g8b8; case 16: return xa_format_r5g6b5; case 15: -- cgit v1.2.3 From 2c438ad8b82f47ac3252403052df16655184acbd Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 6 Dec 2011 09:53:16 +0100 Subject: vmwgfx: Add an option to enable rendercheck mode Rendercheck mode is used to enable acceleration of all supported composite operations, regardless of the current data location. The mode is off by default, but could be turned on to test the hardware composite operation implementation. Due to excessive data migration, rendercheck mode will be slow. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- src/vmware_bootstrap.c | 1 + src/vmware_bootstrap.h | 3 ++- vmwgfx/vmwgfx_driver.c | 19 ++++++++++++++++++- vmwgfx/vmwgfx_driver.h | 2 ++ vmwgfx/vmwgfx_saa.c | 11 +++++++++-- vmwgfx/vmwgfx_saa.h | 3 ++- vmwgfx/vmwgfx_saa_priv.h | 1 + 7 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/vmware_bootstrap.c b/src/vmware_bootstrap.c index 92eb3c5..522fec0 100644 --- a/src/vmware_bootstrap.c +++ b/src/vmware_bootstrap.c @@ -191,6 +191,7 @@ static const OptionInfoRec VMWAREOptions[] = { { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, { OPTION_DIRECT_PRESENTS, "DirectPresents", OPTV_BOOLEAN, {0}, FALSE}, { OPTION_HW_PRESENTS, "HWPresents", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_RENDERCHECK, "RenderCheck", OPTV_BOOLEAN, {0}, FALSE}, { -1, NULL, OPTV_NONE, {0}, FALSE } }; diff --git a/src/vmware_bootstrap.h b/src/vmware_bootstrap.h index 1a1ee9e..172deb8 100644 --- a/src/vmware_bootstrap.h +++ b/src/vmware_bootstrap.h @@ -40,7 +40,8 @@ typedef enum { OPTION_RENDER_ACCEL, OPTION_DRI, OPTION_DIRECT_PRESENTS, - OPTION_HW_PRESENTS + OPTION_HW_PRESENTS, + OPTION_RENDERCHECK } VMWAREOpts; OptionInfoPtr VMWARECopyOptions(void); diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index fe98bca..088ac3d 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -449,6 +449,11 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) &ms->accelerate_render) ? X_CONFIG : X_PROBED; + ms->rendercheck = FALSE; + ms->from_rendercheck = xf86GetOptValBool(ms->Options, OPTION_RENDERCHECK, + &ms->rendercheck) ? + X_CONFIG : X_DEFAULT; + ms->enable_dri = ms->accelerate_render; ms->from_dri = xf86GetOptValBool(ms->Options, OPTION_DRI, &ms->enable_dri) ? @@ -993,11 +998,18 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) ms->from_render = X_PROBED; } } + if (ms->xat == NULL && ms->rendercheck) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Turning off renercheck mode.\n"); + ms->rendercheck = FALSE; + ms->from_rendercheck = X_PROBED; + } } if (!vmwgfx_saa_init(pScreen, ms->fd, ms->xat, &xorg_flush, ms->direct_presents, - ms->only_hw_presents)) { + ms->only_hw_presents, + ms->rendercheck)) { FatalError("Failed to initialize SAA.\n"); } @@ -1018,6 +1030,11 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86DrvMsg(pScrn->scrnIndex, ms->from_render, "Render acceleration is %s.\n", (ms->xat != NULL) ? "enabled" : "disabled"); + + xf86DrvMsg(pScrn->scrnIndex, ms->from_rendercheck, + "Rendercheck mode is %s.\n", + (ms->rendercheck) ? "enabled" : "disabled"); + xf86DrvMsg(pScrn->scrnIndex, ms->from_dri, "Direct rendering (3D) is %s.\n", (ms->dri2_available) ? "enabled" : "disabled"); if (ms->xat != NULL) { diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h index f6c9ec0..4589550 100644 --- a/vmwgfx/vmwgfx_driver.h +++ b/vmwgfx/vmwgfx_driver.h @@ -90,6 +90,8 @@ typedef struct _modesettingRec /* Accel */ Bool accelerate_render; Bool from_render; + Bool rendercheck; + MessageType from_rendercheck; Bool SWCursor; CursorPtr cursor; Bool enable_dri; diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index d14c551..7788ed5 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -1070,7 +1070,12 @@ vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op, valid_hw = (valid_hw && tmp_valid_hw); } - if (!valid_hw && !dirty_hw) + /* + * In rendercheck mode we try to accelerate all supported + * composite operations. + */ + + if (!valid_hw && !dirty_hw && !vsaa->rendercheck) goto out_err; /* @@ -1320,7 +1325,8 @@ Bool vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, void (*present_flush)(ScreenPtr pScreen), Bool direct_presents, - Bool only_hw_presents) + Bool only_hw_presents, + Bool rendercheck) { struct vmwgfx_saa *vsaa; @@ -1342,6 +1348,7 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, vsaa->can_optimize_dma = FALSE; vsaa->use_present_opt = direct_presents; vsaa->only_hw_presents = only_hw_presents; + vsaa->rendercheck = rendercheck; WSBMINITLISTHEAD(&vsaa->sync_x_list); vsaa->driver = vmwgfx_saa_driver; diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h index 1276768..bb8ec96 100644 --- a/vmwgfx/vmwgfx_saa.h +++ b/vmwgfx/vmwgfx_saa.h @@ -82,7 +82,8 @@ extern Bool vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat, void (*present_flush)(ScreenPtr pScreen), Bool direct_presents, - Bool only_hw_presents); + Bool only_hw_presents, + Bool rendercheck); extern uint32_t vmwgfx_scanout_ref(struct vmwgfx_screen_entry *box); diff --git a/vmwgfx/vmwgfx_saa_priv.h b/vmwgfx/vmwgfx_saa_priv.h index b48ef18..5f46dee 100644 --- a/vmwgfx/vmwgfx_saa_priv.h +++ b/vmwgfx/vmwgfx_saa_priv.h @@ -53,6 +53,7 @@ struct vmwgfx_saa { Bool can_optimize_dma; Bool use_present_opt; Bool only_hw_presents; + Bool rendercheck; void (*present_flush) (ScreenPtr pScreen); struct _WsbmListHead sync_x_list; struct vmwgfx_composite *vcomp; -- cgit v1.2.3 From dba7b865d36ebe06b54987176b1a83cdbc2f846a Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 6 Dec 2011 10:00:00 +0100 Subject: vmwgfx: Fix MessageType members that are incorrectly typed as Bool Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_driver.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h index 4589550..3290f0e 100644 --- a/vmwgfx/vmwgfx_driver.h +++ b/vmwgfx/vmwgfx_driver.h @@ -89,17 +89,17 @@ typedef struct _modesettingRec /* Accel */ Bool accelerate_render; - Bool from_render; + MessageType from_render; Bool rendercheck; MessageType from_rendercheck; Bool SWCursor; CursorPtr cursor; Bool enable_dri; - Bool from_dri; + MessageType from_dri; Bool direct_presents; - Bool from_dp; + MessageType from_dp; Bool only_hw_presents; - Bool from_hwp; + MessageType from_hwp; Bool isMaster; -- cgit v1.2.3 From 8bdc6004d34e274d815bb3f3e0aa223085ea848c Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 7 Dec 2011 14:17:45 +0100 Subject: vmwgfx: Adapt to new interface of xa_yuv_planar_blit Also make it easier to modify the color conversion matrix based on yuv encoding properties. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_driver.c | 7 ++-- vmwgfx/vmwgfx_tex_video.c | 105 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 82 insertions(+), 30 deletions(-) diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c index 088ac3d..dcb6c83 100644 --- a/vmwgfx/vmwgfx_driver.c +++ b/vmwgfx/vmwgfx_driver.c @@ -78,7 +78,7 @@ typedef int8_t int8; typedef uint8_t uint8; #include "./src/svga_reg.h" -#define XA_VERSION_MINOR_REQUIRED 0 +#define XA_VERSION_MINOR_REQUIRED 6 #define DRM_VERSION_MAJOR_REQUIRED 2 #define DRM_VERSION_MINOR_REQUIRED 3 @@ -984,8 +984,9 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) ms->xat = NULL; ms->from_render = X_PROBED; } - } else if (major != XA_TRACKER_VERSION_MAJOR || - minor < XA_VERSION_MINOR_REQUIRED) { + } + if (major != XA_TRACKER_VERSION_MAJOR || + minor < XA_VERSION_MINOR_REQUIRED) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Expecting %d.%d.x >= XA version < %d.0.0.\n", XA_TRACKER_VERSION_MAJOR, diff --git a/vmwgfx/vmwgfx_tex_video.c b/vmwgfx/vmwgfx_tex_video.c index 801b066..b2c5472 100644 --- a/vmwgfx/vmwgfx_tex_video.c +++ b/vmwgfx/vmwgfx_tex_video.c @@ -45,36 +45,28 @@ #define RES_720P_Y 720 -/* The ITU-R BT.601 conversion matrix for SDTV. */ -/* original, matrix, but we transpose it to - * make the shader easier -static const float bt_601[] = { - 1.0, 0.0, 1.4075, , - 1.0, -0.3455, -0.7169, 0, - 1.0, 1.7790, 0., 0, -};*/ +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +/* + * ITU-R BT.601, BT.709 transfer matrices. + * [R', G', B'] values are in the range [0, 1], Y' is in the range [0,1] + * and [Pb, Pr] components are in the range [-0.5, 0.5]. + * + * The matrices are transposed to fit the xa conversion matrix format. + */ + static const float bt_601[] = { - 1.0, 1.0, 1.0, 0.5, - 0.0, -0.3455, 1.7790, 0, - 1.4075, -0.7169, 0., 0, + 1.f, 1.f, 1.f, 0.f, + 0.f, -0.344136f, 1.772f, 0.f, + 1.402f, -0.714136f, 0.f, 0.f }; -/* The ITU-R BT.709 conversion matrix for HDTV. */ -/* original, but we transpose to make the conversion - * in the shader easier static const float bt_709[] = { - 1.0, 0.0, 1.581, 0, - 1.0, -0.1881, -0.47, 0, - 1.0, 1.8629, 0., 0, -};*/ -static const float bt_709[] = { - 1.0, 1.0, 1.0, 0.5, - 0.0, -0.1881, 1.8629, 0, - 1.581,-0.47 , 0.0, 0, + 1.f, 1.f, 1.f, 0.f, + 0.f, -0.187324f, 1.8556f, 0.f, + 1.5748f, -0.468124f, 0.f, 0.f }; -#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) - static Atom xvBrightness, xvContrast; #define NUM_TEXTURED_ATTRIBUTES 2 @@ -119,8 +111,56 @@ struct xorg_xv_port_priv { struct xa_surface *yuv[3]; int drm_fd; + + Bool hdtv; + float uv_offset; + float uv_scale; + float y_offset; + float y_scale; + float rgb_offset; + float rgb_scale; + float cm[16]; }; +/* + * vmwgfx_update_conversion_matrix - Compute the effective color conversion + * matrix. + * + * Applies yuv- and resulting rgb scales and offsets to compute the correct + * color conversion matrix. These scales and offsets are properties of the + * video stream (and might in the future be adjusted using XV properties as well). + */ +static void +vmwgfx_update_conversion_matrix(struct xorg_xv_port_priv *priv) +{ + int i; + float *cm = priv->cm; + + memcpy(cm, ((priv->hdtv) ? bt_709 : bt_601), sizeof(bt_601)); + + /* + * Adjust for yuv scales in input and rgb scale in the converted output. + */ + + for(i = 0; i < 3; ++i) { + cm[i] *= (priv->y_scale*priv->rgb_scale); + cm[i+4] *= (priv->uv_scale*priv->rgb_scale); + cm[i+8] *= (priv->uv_scale*priv->rgb_scale); + } + + /* + * Adjust for yuv offsets in input and rgb offset in the converted output. + */ + for (i = 0; i < 3; ++i) + cm[i+12] = -cm[i]*priv->y_offset - (cm[i+4] + cm[i+8])*priv->uv_offset + - priv->rgb_offset*priv->rgb_scale; + + /* + * Alpha is 1, unconditionally. + */ + cm[15] = 1.f; +} + static void stop_video(ScrnInfoPtr pScrn, pointer data, Bool shutdown) @@ -451,7 +491,6 @@ display_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id, RegionRec reg; int ret = BadAlloc; int blit_ret; - const float *conv_matrix; REGION_NULL(pScreen, ®); @@ -459,7 +498,10 @@ display_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id, goto out_no_dst; hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y)); - conv_matrix = (hdtv ? bt_709 : bt_601); + if (hdtv != pPriv->hdtv) { + pPriv->hdtv = hdtv; + vmwgfx_update_conversion_matrix(pPriv); + } #ifdef COMPOSITE @@ -489,7 +531,7 @@ display_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id, dst_x, dst_y, dst_w, dst_h, (struct xa_box *)REGION_RECTS(dstRegion), REGION_NUM_RECTS(dstRegion), - conv_matrix, + pPriv->cm, vpix->hw, pPriv->yuv); saa_pixmap_dirty(pPixmap, TRUE, dstRegion); @@ -579,6 +621,15 @@ port_priv_create(struct xa_tracker *xat, struct xa_context *r, priv->xat = xat; priv->drm_fd = drm_fd; REGION_NULL(pScreen, &priv->clip); + priv->hdtv = FALSE; + priv->uv_offset = 0.5f; + priv->uv_scale = 1.f; + priv->y_offset = 0.f; + priv->y_scale = 1.f; + priv->rgb_offset = 0.f; + priv->rgb_scale = 1.f; + + vmwgfx_update_conversion_matrix(priv); return priv; } -- cgit v1.2.3 From 121dba0093d24eb0aefa3d27a22f05f85ac66f72 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 7 Dec 2011 20:19:34 +0100 Subject: vmwgfx: Hook up XV color conversion control attributes This enables the standard XV color conversion control attributes contrast, scaling, saturation and hue. Currently the attribute change takes effect on the next image only. If we ever implement a ReputImage callback, we can use it to update the image immediately on attribute change. The attribute ranges follow those used by the proprietary Nvidia driver. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_tex_video.c | 97 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 23 deletions(-) diff --git a/vmwgfx/vmwgfx_tex_video.c b/vmwgfx/vmwgfx_tex_video.c index b2c5472..2cc44bd 100644 --- a/vmwgfx/vmwgfx_tex_video.c +++ b/vmwgfx/vmwgfx_tex_video.c @@ -35,7 +35,7 @@ #include #include #include - +#include /*XXX get these from pipe's texture limits */ #define IMAGE_MAX_WIDTH 2048 @@ -67,12 +67,14 @@ static const float bt_709[] = { 1.5748f, -0.468124f, 0.f, 0.f }; -static Atom xvBrightness, xvContrast; +static Atom xvBrightness, xvContrast, xvSaturation, xvHue; -#define NUM_TEXTURED_ATTRIBUTES 2 +#define NUM_TEXTURED_ATTRIBUTES 4 static XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = { - {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, - {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} + {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"}, + {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"}, + {XvSettable | XvGettable, -1000, 1000, "XV_HUE"} }; #define NUM_FORMATS 3 @@ -105,6 +107,8 @@ struct xorg_xv_port_priv { int brightness; int contrast; + int saturation; + int hue; int current_set; struct vmwgfx_dmabuf *bounce[2][3]; @@ -119,6 +123,8 @@ struct xorg_xv_port_priv { float y_scale; float rgb_offset; float rgb_scale; + float sinhue; + float coshue; float cm[16]; }; @@ -128,20 +134,32 @@ struct xorg_xv_port_priv { * * Applies yuv- and resulting rgb scales and offsets to compute the correct * color conversion matrix. These scales and offsets are properties of the - * video stream (and might in the future be adjusted using XV properties as well). + * video stream and can be adjusted using XV properties as well. */ static void vmwgfx_update_conversion_matrix(struct xorg_xv_port_priv *priv) { int i; float *cm = priv->cm; + static const float *bt; + + bt = (priv->hdtv) ? bt_709 : bt_601; - memcpy(cm, ((priv->hdtv) ? bt_709 : bt_601), sizeof(bt_601)); + memcpy(cm, bt, sizeof(bt_601)); /* - * Adjust for yuv scales in input and rgb scale in the converted output. + * Apply hue rotation */ + cm[4] = priv->coshue * bt[4] - priv->sinhue * bt[8]; + cm[8] = priv->sinhue * bt[4] + priv->coshue * bt[8]; + cm[5] = priv->coshue * bt[5] - priv->sinhue * bt[9]; + cm[9] = priv->sinhue * bt[5] + priv->coshue * bt[9]; + cm[6] = priv->coshue * bt[6] - priv->sinhue * bt[10]; + cm[10] = priv->sinhue * bt[6] + priv->coshue * bt[10]; + /* + * Adjust for yuv scales in input and rgb scale in the converted output. + */ for(i = 0; i < 3; ++i) { cm[i] *= (priv->y_scale*priv->rgb_scale); cm[i+4] *= (priv->uv_scale*priv->rgb_scale); @@ -201,16 +219,41 @@ set_port_attribute(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; if (attribute == xvBrightness) { - if ((value < -128) || (value > 127)) - return BadValue; - priv->brightness = value; + if ((value < -1000) || (value > 1000)) + return BadValue; + + priv->brightness = value; + priv->y_offset = -((float) value)/1000.f; + } else if (attribute == xvContrast) { - if ((value < 0) || (value > 255)) - return BadValue; - priv->contrast = value; + if ((value < -1000) || (value > 1000)) + return BadValue; + + priv->contrast = value; + priv->rgb_scale = ((float) value + 1000.f)/1000.f; + + } else if (attribute == xvSaturation) { + if ((value < -1000) || (value > 1000)) + return BadValue; + + priv->saturation = value; + priv->uv_scale = ((float) value + 1000.f)/1000.f; + + } else if (attribute == xvHue) { + double hue_angle; + + if ((value < -1000) || (value > 1000)) + return BadValue; + + priv->hue = value; + hue_angle = (double) value * M_PI / 1000.; + priv->sinhue = sin(hue_angle); + priv->coshue = cos(hue_angle); + } else return BadMatch; + vmwgfx_update_conversion_matrix(priv); return Success; } @@ -218,16 +261,20 @@ static int get_port_attribute(ScrnInfoPtr pScrn, Atom attribute, INT32 * value, pointer data) { - struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; - - if (attribute == xvBrightness) - *value = priv->brightness; - else if (attribute == xvContrast) - *value = priv->contrast; - else - return BadMatch; + struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data; + + if (attribute == xvBrightness) + *value = priv->brightness; + else if (attribute == xvContrast) + *value = priv->contrast; + else if (attribute == xvSaturation) + *value = priv->saturation; + else if (attribute == xvHue) + *value = priv->hue; + else + return BadMatch; - return Success; + return Success; } static void @@ -628,6 +675,8 @@ port_priv_create(struct xa_tracker *xat, struct xa_context *r, priv->y_scale = 1.f; priv->rgb_offset = 0.f; priv->rgb_scale = 1.f; + priv->sinhue = 0.f; + priv->coshue = 1.f; vmwgfx_update_conversion_matrix(priv); @@ -739,6 +788,8 @@ xorg_xv_init(ScreenPtr pScreen) */ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); xvContrast = MAKE_ATOM("XV_CONTRAST"); + xvSaturation = MAKE_ATOM("XV_SATURATION"); + xvHue = MAKE_ATOM("XV_HUE"); if (ms->xat) { textured_adapter = xorg_setup_textured_adapter(pScreen); -- cgit v1.2.3 From afd2f828b8a8b2ccc6ebe4d56104db3d03d08493 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 8 Dec 2011 13:14:57 +0100 Subject: vmwgfx: Reduce system resource usage with textured video Use U and V textures and corresponding dma buffers that match the size of the input UV data rather than using textures and DMA buffers that match the Y data. This simplifies data copy and reduces the amount of image data transfered to the host by up to 50% (YV12). It also reduces dma buffer- and surface memory usage correspondingly. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- vmwgfx/vmwgfx_tex_video.c | 66 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/vmwgfx/vmwgfx_tex_video.c b/vmwgfx/vmwgfx_tex_video.c index 2cc44bd..cc94c20 100644 --- a/vmwgfx/vmwgfx_tex_video.c +++ b/vmwgfx/vmwgfx_tex_video.c @@ -294,7 +294,8 @@ query_best_size(ScrnInfoPtr pScrn, } static int -check_yuv_surfaces(struct xorg_xv_port_priv *priv, int width, int height) +check_yuv_surfaces(struct xorg_xv_port_priv *priv, int id, + int width, int height) { struct xa_surface **yuv = priv->yuv; struct vmwgfx_dmabuf **bounce = priv->bounce[priv->current_set]; @@ -303,6 +304,25 @@ check_yuv_surfaces(struct xorg_xv_port_priv *priv, int width, int height) size_t size; for (i=0; i<3; ++i) { + + /* + * Adjust u,v texture size and DMA buffer to what's required by + * the format. + */ + if (i == 1) { + switch(id) { + case FOURCC_YV12: + height /= 2; + /* Fall through */ + case FOURCC_YUY2: + case FOURCC_UYVY: + width /= 2; + break; + default: + break; + } + } + if (!yuv[i]) yuv[i] = xa_surface_create(priv->xat, width, height, 8, xa_type_yuv_component, @@ -392,7 +412,7 @@ copy_packed_data(ScrnInfoPtr pScrn, int top, unsigned short w, unsigned short h) { - int i, j; + int i; struct vmwgfx_dmabuf **bounce = port->bounce[port->current_set]; char *ymap, *vmap, *umap; unsigned char y1, y2, u, v; @@ -431,18 +451,11 @@ copy_packed_data(ScrnInfoPtr pScrn, y = buf + offsets[0]; v = buf + offsets[1]; u = buf + offsets[2]; - for (i = 0; i < h; ++i) { - for (j = 0; j < w; ++j) { - int yoffset = (w*i+j); - int ii = (i|1), jj = (j|1); - int vuoffset = (w/2)*(ii/2) + (jj/2); - ymap[yidx++] = y[yoffset]; - umap[uidx++] = u[vuoffset]; - vmap[vidx++] = v[vuoffset]; - } - } - } + memcpy(ymap, y, w*h); + memcpy(vmap, v, w*h/4); + memcpy(umap, u, w*h/4); break; + } case FOURCC_UYVY: for (i = 0; i < y_array_size; i +=2 ) { /* extracting two pixels */ @@ -455,8 +468,6 @@ copy_packed_data(ScrnInfoPtr pScrn, ymap[yidx++] = y1; ymap[yidx++] = y2; umap[uidx++] = u; - umap[uidx++] = u; - vmap[vidx++] = v; vmap[vidx++] = v; } break; @@ -473,8 +484,6 @@ copy_packed_data(ScrnInfoPtr pScrn, ymap[yidx++] = y1; ymap[yidx++] = y2; umap[uidx++] = u; - umap[uidx++] = u; - vmap[vidx++] = v; vmap[vidx++] = v; } break; @@ -509,6 +518,27 @@ copy_packed_data(ScrnInfoPtr pScrn, srf = port->yuv[i]; buf = bounce[i]; + if (i == 1) { + switch(id) { + case FOURCC_YV12: + h /= 2; + /* Fall through */ + case FOURCC_YUY2: + case FOURCC_UYVY: + w /= 2; + break; + default: + break; + } + + box.x1 = 0; + box.x2 = w; + box.y1 = 0; + box.y2 = h; + + REGION_RESET(pScrn->pScreen, ®, &box); + } + if (xa_surface_handle(srf, &handle, &stride) != 0) { ret = BadAlloc; break; @@ -629,7 +659,7 @@ put_image(ScrnInfoPtr pScrn, width, height)) return Success; - ret = check_yuv_surfaces(pPriv, width, height); + ret = check_yuv_surfaces(pPriv, id, width, height); if (ret) return ret; -- cgit v1.2.3 From 0eef22437093d29f572abea845fff9c03fca5e4e Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 14 Dec 2011 10:18:16 +0100 Subject: saa: Only try to accelerate pixmaps that are driver pixmaps Trying to accelerate scratch pixmaps doesn't work currently, and I'm not sure it's a big benefit either. This is in line with what EXA does. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrants --- saa/saa_accel.c | 5 +++++ saa/saa_render.c | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/saa/saa_accel.c b/saa/saa_accel.c index 7bd5d61..5e1501b 100644 --- a/saa/saa_accel.c +++ b/saa/saa_accel.c @@ -61,6 +61,11 @@ saa_hw_copy_nton(DrawablePtr pSrcDrawable, src_spix = saa_pixmap(pSrcPixmap); dst_spix = saa_pixmap(pDstPixmap); + if (src_spix->auth_loc != saa_loc_driver || + dst_spix->auth_loc != saa_loc_driver) + return FALSE; + + ordering = (nbox == 1 || (dx > 0 && dy > 0) || (pDstDrawable != pSrcDrawable && (pDstDrawable->type != DRAWABLE_WINDOW || diff --git a/saa/saa_render.c b/saa/saa_render.c index 6bd58f7..3c441da 100644 --- a/saa/saa_render.c +++ b/saa/saa_render.c @@ -235,11 +235,18 @@ saa_driver_composite(CARD8 op, return FALSE; dst_pix = saa_get_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); + if (saa_pixmap(dst_pix)->auth_loc != saa_loc_driver) + return FALSE; + if (pMask && pMask->pDrawable) { mask_pix = saa_get_pixmap(pMask->pDrawable, &mask_off_x, &mask_off_y); + if (saa_pixmap(mask_pix)->auth_loc != saa_loc_driver) + return FALSE; } if (pSrc->pDrawable) { src_pix = saa_get_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y); + if (saa_pixmap(src_pix)->auth_loc != saa_loc_driver) + return FALSE; } if (!driver->composite_prepare(driver, op, pSrc, pMask, pDst, @@ -304,6 +311,10 @@ saa_copy_composite(CARD8 op, ySrc + height > pSrc->pDrawable->height) return FALSE; + if (saa_pixmap(saa_get_drawable_pixmap(pSrc->pDrawable))->auth_loc != + saa_loc_driver) + return FALSE; + if ((op == PictOpSrc && (pSrc->format == pDst->format || (PICT_FORMAT_COLOR(pDst->format) && @@ -318,8 +329,10 @@ saa_copy_composite(CARD8 op, !PICT_FORMAT_A(pSrc->format))) { Bool ret; int xoff, yoff; + PixmapPtr pixmap = saa_get_pixmap(pDst->pDrawable, &xoff, &yoff); - saa_get_pixmap(pDst->pDrawable, &xoff, &yoff); + if (saa_pixmap(pixmap)->auth_loc != saa_loc_driver) + return FALSE; xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; -- cgit v1.2.3 From f664e31d73bd31594e069d8bcca872687b84d8d9 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 14 Dec 2011 10:22:22 +0100 Subject: saa: Always read back hw contents on poly_fill_rect The damage region may be much larger than the actual area filled, so make sure we read back any hw contents in the damage region since we use it to mark sw dirty. Revisit this in the future since it may increase readbacks in an undesired way. There are workarounds. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- saa/saa_unaccel.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/saa/saa_unaccel.c b/saa/saa_unaccel.c index 8c1d89b..deaf5aa 100644 --- a/saa/saa_unaccel.c +++ b/saa/saa_unaccel.c @@ -389,7 +389,13 @@ saa_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC, SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable))); sscreen->fallback_count++; - if (!saa_pad_write(pDrawable, pGC, TRUE, &access)) + + /* + * TODO: Use @prect for readback / damaging instead of + * the damage region. This may fragment the dirty regions more + * but should avoid unnecessary readbacks. + */ + if (!saa_pad_write(pDrawable, pGC, FALSE, &access)) goto out_no_access;; if (!saa_prepare_access_gc(pGC)) goto out_no_gc; -- cgit v1.2.3 From 5748c33535bc7d3009b9758653885e6ae0e73002 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 14 Dec 2011 12:38:27 +0100 Subject: saa, vmwgfx: Fix saa_copy_composite The traditional accelerated copy methods aren't format aware. Make saa copy format aware,and pass formats on to the driver copy function if available. If the driver can't handle format conversions it needs to return FALSE. This fixes format confusion in the copy composite fastpath. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz --- saa/saa.h | 2 ++ saa/saa_render.c | 38 ++++++++++++++++++-------------------- vmwgfx/vmwgfx_saa.c | 21 +++++++++++++++++---- 3 files changed, 37 insertions(+), 24 deletions(-) diff --git a/saa/saa.h b/saa/saa.h index 3101353..c7aa3b6 100644 --- a/saa/saa.h +++ b/saa/saa.h @@ -74,6 +74,8 @@ struct saa_pixmap { void *addr; void *override; enum saa_pixmap_loc auth_loc; + PictFormatShort src_format; + PictFormatShort dst_format; uint32_t pad[16]; }; diff --git a/saa/saa_render.c b/saa/saa_render.c index 3c441da..c69f2c9 100644 --- a/saa/saa_render.c +++ b/saa/saa_render.c @@ -311,35 +311,29 @@ saa_copy_composite(CARD8 op, ySrc + height > pSrc->pDrawable->height) return FALSE; - if (saa_pixmap(saa_get_drawable_pixmap(pSrc->pDrawable))->auth_loc != - saa_loc_driver) - return FALSE; + if (op == PictOpSrc || + (op == PictOpOver && PICT_FORMAT_A(pSrc->format) == 0 && + pMask == NULL)) { - if ((op == PictOpSrc && - (pSrc->format == pDst->format || - (PICT_FORMAT_COLOR(pDst->format) && - PICT_FORMAT_COLOR(pSrc->format) && - pDst->format == PICT_FORMAT(PICT_FORMAT_BPP(pSrc->format), - PICT_FORMAT_TYPE(pSrc->format), - 0, - PICT_FORMAT_R(pSrc->format), - PICT_FORMAT_G(pSrc->format), - PICT_FORMAT_B(pSrc->format))))) || - (op == PictOpOver && pSrc->format == pDst->format && - !PICT_FORMAT_A(pSrc->format))) { - Bool ret; int xoff, yoff; - PixmapPtr pixmap = saa_get_pixmap(pDst->pDrawable, &xoff, &yoff); - - if (saa_pixmap(pixmap)->auth_loc != saa_loc_driver) + PixmapPtr dst_pix = saa_get_pixmap(pDst->pDrawable, &xoff, &yoff); + struct saa_pixmap *dst_spix = saa_pixmap(dst_pix); + struct saa_pixmap *src_spix = + saa_pixmap(saa_get_drawable_pixmap(pSrc->pDrawable)); + int ret; + + if (src_spix->auth_loc != saa_loc_driver || + dst_spix->auth_loc != saa_loc_driver) return FALSE; + src_spix->src_format = pSrc->format; + dst_spix->dst_format = pDst->format; + xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; xSrc += pSrc->pDrawable->x; ySrc += pSrc->pDrawable->y; - /* * Dst region is in backing pixmap space. We need to * translate it. @@ -350,6 +344,10 @@ saa_copy_composite(CARD8 op, REGION_NUM_RECTS(dst_region), xSrc - xDst, ySrc - yDst, FALSE, FALSE); REGION_TRANSLATE(pScreen, dst_region, xoff, yoff); + + src_spix->src_format = 0; + dst_spix->dst_format = 0; + if (ret) return TRUE; } diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c index 7788ed5..0a6b98f 100644 --- a/vmwgfx/vmwgfx_saa.c +++ b/vmwgfx/vmwgfx_saa.c @@ -896,10 +896,23 @@ vmwgfx_copy_prepare(struct saa_driver *driver, * Determine surface formats. */ - if (!vmwgfx_hw_accel_stage(src_pixmap, 0, XA_FLAG_RENDER_TARGET, 0)) - return FALSE; - if (!vmwgfx_hw_accel_stage(dst_pixmap, 0, XA_FLAG_RENDER_TARGET, 0)) - return FALSE; + if (src_vpix->base.src_format == 0) { + if (!vmwgfx_hw_accel_stage(src_pixmap, 0, XA_FLAG_RENDER_TARGET, 0)) + return FALSE; + } else { + if (PICT_FORMAT_TYPE(src_vpix->base.src_format) != PICT_TYPE_ARGB || + !vmwgfx_hw_composite_src_stage(src_pixmap, src_vpix->base.src_format)) + return FALSE; + } + + if (dst_vpix->base.dst_format == 0) { + if (!vmwgfx_hw_accel_stage(dst_pixmap, 0, XA_FLAG_RENDER_TARGET, 0)) + return FALSE; + } else { + if (PICT_FORMAT_TYPE(dst_vpix->base.dst_format) != PICT_TYPE_ARGB || + !vmwgfx_hw_composite_dst_stage(dst_pixmap, dst_vpix->base.dst_format)) + return FALSE; + } /* * Create hardware surfaces. -- cgit v1.2.3