mirror of
https://github.com/X11Libre/xf86-video-vmware.git
synced 2026-03-24 01:24:37 +00:00
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 <thellstrom@vmware.com>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -121,5 +121,7 @@ AC_CONFIG_FILES([
|
||||
src/Makefile
|
||||
vmwarectrl/Makefile
|
||||
man/Makefile
|
||||
saa/Makefile
|
||||
vmwgfx/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
13
saa/Makefile.am
Normal file
13
saa/Makefile.am
Normal file
@@ -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
|
||||
|
||||
748
saa/saa.c
Normal file
748
saa/saa.c
Normal file
@@ -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 <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "saa_priv.h"
|
||||
#include <X11/fonts/fontstruct.h>
|
||||
#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;
|
||||
}
|
||||
192
saa/saa.h
Normal file
192
saa/saa.h
Normal file
@@ -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 <thellstrom@vmware.com>
|
||||
*/
|
||||
|
||||
#ifndef _SAA_H_
|
||||
#define _SAA_H_
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#else
|
||||
#include <xorg-server.h>
|
||||
#endif
|
||||
#include <xf86.h>
|
||||
#include <damage.h>
|
||||
|
||||
#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
|
||||
141
saa/saa_accel.c
Normal file
141
saa/saa_accel.c
Normal file
@@ -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 <eric@anholt.net>
|
||||
* Author: Michel Dänzer <michel@tungstengraphics.com>
|
||||
* Author: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
222
saa/saa_pixmap.c
Normal file
222
saa/saa_pixmap.c
Normal file
@@ -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 <thellstrom@vmware.com>
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
263
saa/saa_priv.h
Normal file
263
saa/saa_priv.h
Normal file
@@ -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 <thellstrom@vmware.com>
|
||||
*/
|
||||
|
||||
#ifndef _SAA_PRIV_H
|
||||
#define _SAA_PRIV_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#else
|
||||
#include <xorg-server.h>
|
||||
#endif
|
||||
#include "xf86.h"
|
||||
|
||||
#include "saa.h"
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xproto.h>
|
||||
#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
|
||||
313
saa/saa_render.c
Normal file
313
saa/saa_render.c
Normal file
@@ -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 <eric@anholt.net>
|
||||
* Author: Michel Dänzer <michel@tungstengraphics.com>
|
||||
* Author: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
*/
|
||||
#include "saa.h"
|
||||
#include "saa_priv.h"
|
||||
|
||||
#ifdef RENDER
|
||||
#include <mipict.h>
|
||||
|
||||
/**
|
||||
* 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
|
||||
896
saa/saa_unaccel.c
Normal file
896
saa/saa_unaccel.c
Normal file
@@ -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 <thellstrom@vmware.com>
|
||||
*/
|
||||
|
||||
#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,
|
||||
};
|
||||
1319
src/svga_reg.h
1319
src/svga_reg.h
File diff suppressed because it is too large
Load Diff
24
vmwgfx/Makefile.am
Normal file
24
vmwgfx/Makefile.am
Normal file
@@ -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
|
||||
|
||||
|
||||
|
||||
1801
vmwgfx/svga3d_reg.h
Normal file
1801
vmwgfx/svga3d_reg.h
Normal file
File diff suppressed because it is too large
Load Diff
199
vmwgfx/vmwgfx_bootstrap.c
Normal file
199
vmwgfx/vmwgfx_bootstrap.c
Normal file
@@ -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 <alanh@tungstengraphics.com>
|
||||
* @author Jakob Bornecrantz <wallbraker@gmail.com>
|
||||
* @author Thomas Hellstrom <thellstrom@vmware.com>
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
456
vmwgfx/vmwgfx_crtc.c
Normal file
456
vmwgfx/vmwgfx_crtc.c
Normal file
@@ -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 <alanh@tungstengraphics.com>
|
||||
* Author: Jakob Bornecrantz <wallbraker@gmail.com>
|
||||
* Author: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "xorg-server.h"
|
||||
#include <xf86.h>
|
||||
#include <xf86i2c.h>
|
||||
#include <xf86Crtc.h>
|
||||
#include <cursorstr.h>
|
||||
#include "vmwgfx_driver.h"
|
||||
#include "xf86Modes.h"
|
||||
#include "vmwgfx_saa.h"
|
||||
|
||||
#ifdef HAVE_XEXTPROTO_71
|
||||
#include <X11/extensions/dpmsconst.h>
|
||||
#else
|
||||
#define DPMS_SERVER
|
||||
#include <X11/extensions/dpms.h>
|
||||
#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: */
|
||||
525
vmwgfx/vmwgfx_ctrl.c
Normal file
525
vmwgfx/vmwgfx_ctrl.c
Normal file
@@ -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 <xorg-server.h>
|
||||
#include "dixstruct.h"
|
||||
#include "extnsionst.h"
|
||||
#include <X11/X.h>
|
||||
#include <X11/extensions/panoramiXproto.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
48
vmwgfx/vmwgfx_ctrl.h
Normal file
48
vmwgfx/vmwgfx_ctrl.h
Normal file
@@ -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_ */
|
||||
373
vmwgfx/vmwgfx_dri2.c
Normal file
373
vmwgfx/vmwgfx_dri2.c
Normal file
@@ -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 <alanh@tungstengraphics.com>
|
||||
* Author: Jakob Bornecrantz <wallbraker@gmail.com>
|
||||
* Author: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#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: */
|
||||
947
vmwgfx/vmwgfx_driver.c
Normal file
947
vmwgfx/vmwgfx_driver.c
Normal file
@@ -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 <alanh@tungstengraphics.com>
|
||||
* Author: Jakob Bornecrantz <wallbraker@gmail.com>
|
||||
* Author: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
*/
|
||||
|
||||
|
||||
#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 <X11/extensions/randr.h>
|
||||
#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 <pciaccess.h>
|
||||
|
||||
#include "vmwgfx_driver.h"
|
||||
|
||||
#include <saa.h>
|
||||
#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; i<config->num_crtc; ++i) {
|
||||
crtc = config->crtc[i];
|
||||
if (crtc->enabled) {
|
||||
pixmap = crtc_get_scanout(crtc);
|
||||
if (pixmap) {
|
||||
unsigned int j;
|
||||
|
||||
/*
|
||||
* Remove duplicates.
|
||||
*/
|
||||
for (j=0; j<num_scanout; ++j) {
|
||||
if (pixmap == pixmaps[j])
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == num_scanout)
|
||||
pixmaps[num_scanout++] = pixmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!num_scanout)
|
||||
return;
|
||||
|
||||
for (j=0; j<num_scanout; ++j) {
|
||||
pixmap = pixmaps[j];
|
||||
vpix = vmwgfx_saa_pixmap(pixmap);
|
||||
|
||||
if (vpix->fb_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: */
|
||||
167
vmwgfx/vmwgfx_driver.h
Normal file
167
vmwgfx/vmwgfx_driver.h
Normal file
@@ -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<otice 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 <alanh@tungstengraphics.com>
|
||||
* Author: Jakob Bornecrantz <wallbraker@gmail.com>
|
||||
* Author: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
*/
|
||||
|
||||
#ifndef _VMWGFX_DRIVER_H_
|
||||
#define _VMWGFX_DRIVER_H_
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <drm.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <xorg-server.h>
|
||||
#include <xf86.h>
|
||||
#include <xf86Crtc.h>
|
||||
#include <xf86xv.h>
|
||||
#include <xa_tracker.h>
|
||||
|
||||
#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_ */
|
||||
507
vmwgfx/vmwgfx_drmi.c
Normal file
507
vmwgfx/vmwgfx_drmi.c
Normal file
@@ -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 <wallbraker@gmail.com>
|
||||
* Author: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <drm/vmwgfx_drm.h>
|
||||
#include <xf86drm.h>
|
||||
#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;
|
||||
}
|
||||
81
vmwgfx/vmwgfx_drmi.h
Normal file
81
vmwgfx/vmwgfx_drmi.h
Normal file
@@ -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 <wallbraker@gmail.com>
|
||||
* Author: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
*/
|
||||
|
||||
#ifndef _VMWGFX_DRMI_H_
|
||||
#define _VMWGFX_DRMI_H_
|
||||
|
||||
#include <xorg-server.h>
|
||||
#include <regionstr.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
||||
304
vmwgfx/vmwgfx_output.c
Normal file
304
vmwgfx/vmwgfx_output.c
Normal file
@@ -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 <alanh@tungstengraphics.com>
|
||||
* Author: Jakob Bornecrantz <wallbraker@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xorg-server.h"
|
||||
#include <xf86.h>
|
||||
#include <xf86i2c.h>
|
||||
#include <xf86Crtc.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_XEXTPROTO_71
|
||||
#include <X11/extensions/dpmsconst.h>
|
||||
#else
|
||||
#define DPMS_SERVER
|
||||
#include <X11/extensions/dpms.h>
|
||||
#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: */
|
||||
893
vmwgfx/vmwgfx_overlay.c
Normal file
893
vmwgfx/vmwgfx_overlay.c
Normal file
@@ -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 <X11/extensions/Xv.h>
|
||||
|
||||
#include "xf86drm.h"
|
||||
#include <drm/vmwgfx_drm.h>
|
||||
#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; i<adaptor->nPorts; ++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;
|
||||
}
|
||||
1208
vmwgfx/vmwgfx_saa.c
Normal file
1208
vmwgfx/vmwgfx_saa.c
Normal file
File diff suppressed because it is too large
Load Diff
94
vmwgfx/vmwgfx_saa.h
Normal file
94
vmwgfx/vmwgfx_saa.h
Normal file
@@ -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 <thellstrom@vmware.com>
|
||||
*/
|
||||
|
||||
#ifndef _VMWGFX_SAA_H_
|
||||
#define _VMWGFX_SAA_H_
|
||||
|
||||
#include "saa.h"
|
||||
#include <xa_tracker.h>
|
||||
#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
|
||||
723
vmwgfx/vmwgfx_tex_video.c
Normal file
723
vmwgfx/vmwgfx_tex_video.c
Normal file
@@ -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 <thellstrom@vmware.com>
|
||||
* Author: Zack Rusin <zackr@vmware.com>
|
||||
*/
|
||||
|
||||
#include "vmwgfx_driver.h"
|
||||
#include "vmwgfx_drmi.h"
|
||||
#include "vmwgfx_saa.h"
|
||||
|
||||
#include <xf86xv.h>
|
||||
#include <X11/extensions/Xv.h>
|
||||
#include <fourcc.h>
|
||||
#include <xa_tracker.h>
|
||||
#include <xa_context.h>
|
||||
|
||||
|
||||
/*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; i<adaptor->nPorts; ++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);
|
||||
}
|
||||
Reference in New Issue
Block a user