summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2011-12-19 20:25:43 +0100
committerThomas Hellstrom <thellstrom@vmware.com>2011-12-19 20:25:43 +0100
commitb5546fb1de3f3859151a91e98ab0bd24b6789e2e (patch)
tree8e5283d6610e87d796e0d64b0a06c42469422b0d
parentabf9cb75630cb27bb4741d194cb23014fe3d09b1 (diff)
parent5748c33535bc7d3009b9758653885e6ae0e73002 (diff)
Merge branch 'vmwgfx_branch'
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac35
-rw-r--r--saa/Makefile.am13
-rw-r--r--saa/saa.c748
-rw-r--r--saa/saa.h209
-rw-r--r--saa/saa_accel.c153
-rw-r--r--saa/saa_pixmap.c222
-rw-r--r--saa/saa_priv.h279
-rw-r--r--saa/saa_render.c424
-rw-r--r--saa/saa_unaccel.c935
-rw-r--r--src/Makefile.am27
-rw-r--r--src/svga_reg.h1433
-rw-r--r--src/vmware.c547
-rw-r--r--src/vmware_bootstrap.c503
-rw-r--r--src/vmware_bootstrap.h59
-rw-r--r--src/vmware_common.c163
-rw-r--r--src/vmware_common.h41
-rw-r--r--src/vmwaremodule.c256
-rw-r--r--vmwgfx/Makefile.am26
-rw-r--r--vmwgfx/svga3d_reg.h1801
-rw-r--r--vmwgfx/vmwgfx_crtc.c455
-rw-r--r--vmwgfx/vmwgfx_ctrl.c523
-rw-r--r--vmwgfx/vmwgfx_ctrl.h48
-rw-r--r--vmwgfx/vmwgfx_dri2.c426
-rw-r--r--vmwgfx/vmwgfx_driver.c1200
-rw-r--r--vmwgfx/vmwgfx_driver.h186
-rw-r--r--vmwgfx/vmwgfx_drm.h792
-rw-r--r--vmwgfx/vmwgfx_drmi.c502
-rw-r--r--vmwgfx/vmwgfx_drmi.h87
-rw-r--r--vmwgfx/vmwgfx_output.c393
-rw-r--r--vmwgfx/vmwgfx_overlay.c893
-rw-r--r--vmwgfx/vmwgfx_saa.c1514
-rw-r--r--vmwgfx/vmwgfx_saa.h110
-rw-r--r--vmwgfx/vmwgfx_saa_priv.h125
-rw-r--r--vmwgfx/vmwgfx_tex_video.c855
-rw-r--r--vmwgfx/vmwgfx_xa_composite.c277
-rw-r--r--vmwgfx/vmwgfx_xa_surface.c368
-rw-r--r--vmwgfx/wsbm_util.h79
38 files changed, 15548 insertions, 1161 deletions
diff --git a/Makefile.am b/Makefile.am
index 093e9f5..1203715 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,7 +18,7 @@
18# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 20
21SUBDIRS = src man vmwarectrl 21SUBDIRS = @VMWGFX_DIRS@ src man vmwarectrl
22MAINTAINERCLEANFILES = ChangeLog INSTALL 22MAINTAINERCLEANFILES = ChangeLog INSTALL
23.PHONY: ChangeLog INSTALL 23.PHONY: ChangeLog INSTALL
24 24
diff --git a/configure.ac b/configure.ac
index 74fd1b9..3aec9af 100644
--- a/configure.ac
+++ b/configure.ac
@@ -72,11 +72,6 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto)
72 72
73# Obtain compiler/linker options for the driver dependencies 73# Obtain compiler/linker options for the driver dependencies
74PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.1 xproto fontsproto $REQUIRED_MODULES]) 74PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.1 xproto fontsproto $REQUIRED_MODULES])
75PKG_CHECK_MODULES(LIBDRM,
76 [libdrm],
77 [AC_DEFINE([HAVE_LIBDRM], 1, [Has libdrm])],
78 [echo "Will not try support for 3D or kernel modesetting."])
79
80PKG_CHECK_EXISTS([xorg-server >= 1.1.0], 75PKG_CHECK_EXISTS([xorg-server >= 1.1.0],
81 [AC_DEFINE([HAVE_XORG_SERVER_1_1_0], 1, 76 [AC_DEFINE([HAVE_XORG_SERVER_1_1_0], 1,
82 [Has version 1.1.0 or greater of the Xserver])]) 77 [Has version 1.1.0 or greater of the Xserver])])
@@ -91,7 +86,8 @@ PKG_CHECK_EXISTS([xorg-server >= 1.4.99],
91 86
92PKG_CHECK_EXISTS([xorg-server >= 1.7.0], 87PKG_CHECK_EXISTS([xorg-server >= 1.7.0],
93 [AC_DEFINE([HAVE_XORG_SERVER_1_7_0], 1, 88 [AC_DEFINE([HAVE_XORG_SERVER_1_7_0], 1,
94 [Has version 1.7.0 or greater of the Xserver])]) 89 [Has version 1.7.0 or greater of the Xserver])
90 BUILD_VMWGFX=yes],[BUILD_VMWGFX=no])
95 91
96# Obtain compiler/linker options for the vmwarectrl client tool 92# Obtain compiler/linker options for the vmwarectrl client tool
97PKG_CHECK_MODULES(X11, x11 xext) 93PKG_CHECK_MODULES(X11, x11 xext)
@@ -113,13 +109,40 @@ AM_CONDITIONAL(XSERVER_LIBPCIACCESS, test "x$XSERVER_LIBPCIACCESS" = xyes)
113 109
114AC_SUBST([moduledir]) 110AC_SUBST([moduledir])
115 111
112if test x$BUILD_VMWGFX = xyes; then
113 PKG_CHECK_MODULES([LIBDRM], [libdrm],[],[BUILD_VMWGFX=no])
114fi
115if test x$BUILD_VMWGFX = xyes; then
116 PKG_CHECK_MODULES([XATRACKER], [xatracker >= 0.4.0],[],[BUILD_VMWGFX=no])
117fi
118
116DRIVER_NAME=vmware 119DRIVER_NAME=vmware
117AC_SUBST([DRIVER_NAME]) 120AC_SUBST([DRIVER_NAME])
118 121
122AC_MSG_CHECKING([whether to build Kernel Mode Setting and 3D])
123VMWGFX_DIRS=
124if test x$BUILD_VMWGFX = xyes; then
125 AC_MSG_RESULT([yes])
126 AC_SYS_LARGEFILE
127 VMWGFX_DIRS="saa vmwgfx"
128 VMWGFX_LIBADD='$(top_srcdir)/vmwgfx/libvmwgfx.la'
129 AC_CONFIG_FILES([
130 saa/Makefile
131 vmwgfx/Makefile
132 ])
133 AC_DEFINE([BUILD_VMWGFX], 1,
134 [Building the vmwgfx driver path])
135else
136 AC_MSG_RESULT([no])
137fi
138
139AC_SUBST([VMWGFX_DIRS])
140AC_SUBST([VMWGFX_LIBADD])
119AC_CONFIG_FILES([ 141AC_CONFIG_FILES([
120 Makefile 142 Makefile
121 src/Makefile 143 src/Makefile
122 vmwarectrl/Makefile 144 vmwarectrl/Makefile
123 man/Makefile 145 man/Makefile
124]) 146])
147
125AC_OUTPUT 148AC_OUTPUT
diff --git a/saa/Makefile.am b/saa/Makefile.am
new file mode 100644
index 0000000..849ced9
--- /dev/null
+++ b/saa/Makefile.am
@@ -0,0 +1,13 @@
1noinst_LTLIBRARIES = libsaa.la
2
3libsaa_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS)
4libsaa_la_LDFLAGS = -static
5libsaa_la_SOURCES = \
6 saa.c \
7 saa_pixmap.c \
8 saa_unaccel.c \
9 saa_priv.h \
10 saa_render.c \
11 saa_accel.c \
12 saa.h
13
diff --git a/saa/saa.c b/saa/saa.c
new file mode 100644
index 0000000..173c090
--- /dev/null
+++ b/saa/saa.c
@@ -0,0 +1,748 @@
1/*
2 * Copyright © 2001 Keith Packard
3 *
4 * Partly based on code that is Copyright © The XFree86 Project Inc.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
15 *
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25/** @file
26 * This file covers the initialization and teardown of SAA, and has various
27 * functions not responsible for performing rendering, pixmap migration, or
28 * memory management.
29 */
30
31#ifdef HAVE_DIX_CONFIG_H
32#include <dix-config.h>
33#endif
34
35#include <stdlib.h>
36
37#include "saa_priv.h"
38#include <X11/fonts/fontstruct.h>
39#include "regionstr.h"
40#include "saa.h"
41#include "saa_priv.h"
42
43#ifdef SAA_DEVPRIVATEKEYREC
44DevPrivateKeyRec saa_screen_index;
45DevPrivateKeyRec saa_pixmap_index;
46DevPrivateKeyRec saa_gc_index;
47#else
48int saa_screen_index = -1;
49int saa_pixmap_index = -1;
50int saa_gc_index = -1;
51#endif
52
53/**
54 * saa_get_drawable_pixmap() returns a backing pixmap for a given drawable.
55 *
56 * @param pDrawable the drawable being requested.
57 *
58 * This function returns the backing pixmap for a drawable, whether it is a
59 * redirected window, unredirected window, or already a pixmap. Note that
60 * coordinate translation is needed when drawing to the backing pixmap of a
61 * redirected window, and the translation coordinates are provided by calling
62 * saa_get_drawable_pixmap() on the drawable.
63 */
64PixmapPtr
65saa_get_drawable_pixmap(DrawablePtr pDrawable)
66{
67 if (pDrawable->type == DRAWABLE_WINDOW)
68 return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable);
69 else
70 return (PixmapPtr) pDrawable;
71}
72
73/**
74 * Sets the offsets to add to coordinates to make them address the same bits in
75 * the backing drawable. These coordinates are nonzero only for redirected
76 * windows.
77 */
78void
79saa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap,
80 int *xp, int *yp)
81{
82#ifdef COMPOSITE
83 if (pDrawable->type == DRAWABLE_WINDOW) {
84 *xp = -pPixmap->screen_x;
85 *yp = -pPixmap->screen_y;
86 return;
87 }
88#endif
89
90 *xp = 0;
91 *yp = 0;
92}
93
94/**
95 * Returns the pixmap which backs a drawable, and the offsets to add to
96 * coordinates to make them address the same bits in the backing drawable.
97 */
98PixmapPtr
99saa_get_pixmap(DrawablePtr drawable, int *xp, int *yp)
100{
101 PixmapPtr pixmap = saa_get_drawable_pixmap(drawable);
102
103 saa_get_drawable_deltas(drawable, pixmap, xp, yp);
104
105 return pixmap;
106}
107
108static Bool
109saa_download_from_hw(PixmapPtr pix, RegionPtr readback)
110{
111 struct saa_screen_priv *sscreen = saa_screen(pix->drawable.pScreen);
112 struct saa_driver *driver = sscreen->driver;
113 struct saa_pixmap *spix = saa_pixmap(pix);
114 void *addr;
115 Bool ret;
116
117 if (spix->mapped_access)
118 driver->release_from_cpu(driver, pix, spix->mapped_access);
119
120 ret = driver->download_from_hw(driver, pix, readback);
121
122 if (spix->mapped_access) {
123 addr = driver->sync_for_cpu(driver, pix, spix->mapped_access);
124 if (addr != NULL)
125 spix->addr = addr;
126 }
127
128 return ret;
129}
130
131Bool
132saa_prepare_access_pixmap(PixmapPtr pix, saa_access_t access,
133 RegionPtr read_reg)
134{
135 ScreenPtr pScreen = pix->drawable.pScreen;
136 struct saa_screen_priv *sscreen = saa_screen(pScreen);
137 struct saa_driver *driver = sscreen->driver;
138 struct saa_pixmap *spix = saa_pixmap(pix);
139 saa_access_t map_access = 0;
140 Bool ret = TRUE;
141
142 if (read_reg && REGION_NOTEMPTY(pScreen, read_reg))
143 ret = saa_download_from_hw(pix, read_reg);
144
145 if (!ret) {
146 LogMessage(X_ERROR, "Prepare access pixmap failed.\n");
147 return ret;
148 }
149
150 if ((access & SAA_ACCESS_R) != 0 && spix->read_access++ == 0)
151 map_access = SAA_ACCESS_R;
152 if ((access & SAA_ACCESS_W) != 0 && spix->write_access++ == 0)
153 map_access |= SAA_ACCESS_W;
154
155 if (map_access) {
156 if (spix->auth_loc != saa_loc_override) {
157 (void)driver->sync_for_cpu(driver, pix, map_access);
158 spix->addr = driver->map(driver, pix, map_access);
159 } else
160 spix->addr = spix->override;
161 spix->mapped_access |= map_access;
162 }
163
164 pix->devPrivate.ptr = spix->addr;
165 return TRUE;
166}
167
168void
169saa_finish_access_pixmap(PixmapPtr pix, saa_access_t access)
170{
171 struct saa_screen_priv *sscreen = saa_screen(pix->drawable.pScreen);
172 struct saa_driver *driver = sscreen->driver;
173 struct saa_pixmap *spix = saa_pixmap(pix);
174 saa_access_t unmap_access = 0;
175
176 if ((access & SAA_ACCESS_R) != 0 && --spix->read_access == 0)
177 unmap_access = SAA_ACCESS_R;
178 if ((access & SAA_ACCESS_W) != 0 && --spix->write_access == 0)
179 unmap_access |= SAA_ACCESS_W;
180
181 if (spix->read_access < 0)
182 LogMessage(X_ERROR, "Incorrect read access.\n");
183 if (spix->write_access < 0)
184 LogMessage(X_ERROR, "Incorrect write access.\n");
185
186 if (unmap_access) {
187 if (spix->auth_loc != saa_loc_override) {
188 driver->unmap(driver, pix, unmap_access);
189 driver->release_from_cpu(driver, pix, unmap_access);
190 }
191 spix->mapped_access &= ~unmap_access;
192 }
193 if (!spix->mapped_access) {
194 spix->addr = NULL;
195 pix->devPrivate.ptr = SAA_INVALID_ADDRESS;
196 }
197}
198
199/*
200 * Callback that is called after a rendering operation. We try to
201 * determine whether it's a shadow damage or a hw damage and call the
202 * driver callback.
203 */
204
205static void
206saa_report_damage(DamagePtr damage, RegionPtr reg, void *closure)
207{
208 PixmapPtr pixmap = (PixmapPtr) closure;
209 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
210 struct saa_driver *driver = saa_screen(pixmap->drawable.pScreen)->driver;
211
212 if (spix->read_access || spix->write_access)
213 LogMessage(X_ERROR, "Damage report inside prepare access.\n");
214
215 driver->operation_complete(driver, pixmap);
216 DamageEmpty(damage);
217}
218
219Bool
220saa_add_damage(PixmapPtr pixmap)
221{
222 ScreenPtr pScreen = pixmap->drawable.pScreen;
223 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
224
225 if (spix->damage)
226 return TRUE;
227
228 spix->damage = DamageCreate(saa_report_damage, NULL,
229 DamageReportRawRegion, TRUE, pScreen, pixmap);
230 if (!spix->damage)
231 return FALSE;
232
233 DamageRegister(&pixmap->drawable, spix->damage);
234 DamageSetReportAfterOp(spix->damage, TRUE);
235
236 return TRUE;
237}
238
239static inline RegionPtr
240saa_pix_damage_region(struct saa_pixmap *spix)
241{
242 return (spix->damage ? DamageRegion(spix->damage) : NULL);
243}
244
245Bool
246saa_pad_read(DrawablePtr draw)
247{
248 ScreenPtr pScreen = draw->pScreen;
249 PixmapPtr pix;
250 int xp;
251 int yp;
252 BoxRec box;
253 RegionRec entire;
254 Bool ret;
255
256 (void)pScreen;
257 pix = saa_get_pixmap(draw, &xp, &yp);
258
259 box.x1 = draw->x + xp;
260 box.y1 = draw->y + yp;
261 box.x2 = box.x1 + draw->width;
262 box.y2 = box.y1 + draw->height;
263
264 REGION_INIT(pScreen, &entire, &box, 1);
265 ret = saa_prepare_access_pixmap(pix, SAA_ACCESS_R, &entire);
266 REGION_UNINIT(pScreen, &entire);
267 return ret;
268}
269
270Bool
271saa_pad_read_box(DrawablePtr draw, int x, int y, int w, int h)
272{
273 ScreenPtr pScreen = draw->pScreen;
274 PixmapPtr pix;
275 int xp;
276 int yp;
277 BoxRec box;
278 RegionRec entire;
279 Bool ret;
280
281 (void)pScreen;
282 pix = saa_get_pixmap(draw, &xp, &yp);
283
284 box.x1 = x + xp;
285 box.y1 = y + yp;
286 box.x2 = box.x1 + w;
287 box.y2 = box.y1 + h;
288
289 REGION_INIT(pScreen, &entire, &box, 1);
290 ret = saa_prepare_access_pixmap(pix, SAA_ACCESS_R, &entire);
291 REGION_UNINIT(pScreen, &entire);
292 return ret;
293}
294
295/**
296 * Prepares a drawable destination for access, and maps it read-write.
297 * If check_read is TRUE, pGC should point to a valid GC. The drawable
298 * may then be mapped write-only if the pending operation admits.
299 */
300
301Bool
302saa_pad_write(DrawablePtr draw, GCPtr pGC, Bool check_read,
303 saa_access_t * access)
304{
305 int xp;
306 int yp;
307 PixmapPtr pixmap = saa_get_pixmap(draw, &xp, &yp);
308 struct saa_pixmap *spix = saa_pixmap(pixmap);
309
310 *access = SAA_ACCESS_W;
311
312 /*
313 * If the to-be-damaged area doesn't depend at all on previous
314 * rendered contents, we don't need to do any readback.
315 */
316
317 if (check_read && !saa_gc_reads_destination(draw, pGC))
318 return saa_prepare_access_pixmap(pixmap, *access, NULL);
319
320 *access |= SAA_ACCESS_R;
321
322 /*
323 * Read back the area to be damaged.
324 */
325
326 return saa_prepare_access_pixmap(pixmap, *access,
327 saa_pix_damage_pending(spix));
328}
329
330void
331saa_fad_read(DrawablePtr draw)
332{
333 saa_finish_access_pixmap(saa_get_drawable_pixmap(draw), SAA_ACCESS_R);
334}
335
336void
337saa_fad_write(DrawablePtr draw, saa_access_t access)
338{
339 PixmapPtr pix = saa_get_drawable_pixmap(draw);
340 struct saa_pixmap *spix = saa_pixmap(pix);
341
342 saa_finish_access_pixmap(pix, access);
343 if (spix->damage)
344 saa_pixmap_dirty(pix, FALSE, saa_pix_damage_pending(spix));
345}
346
347Bool
348saa_gc_reads_destination(DrawablePtr pDrawable, GCPtr pGC)
349{
350 return ((pGC->alu != GXcopy && pGC->alu != GXclear && pGC->alu != GXset &&
351 pGC->alu != GXcopyInverted) || pGC->fillStyle == FillStippled ||
352 pGC->clientClipType != CT_NONE ||
353 !SAA_PM_IS_SOLID(pDrawable, pGC->planemask));
354}
355
356Bool
357saa_op_reads_destination(CARD8 op)
358{
359 /* FALSE (does not read destination) is the list of ops in the protocol
360 * document with "0" in the "Fb" column and no "Ab" in the "Fa" column.
361 * That's just Clear and Src. ReduceCompositeOp() will already have
362 * converted con/disjoint clear/src to Clear or Src.
363 */
364 switch (op) {
365 case PictOpClear:
366 case PictOpSrc:
367 return FALSE;
368 default:
369 return TRUE;
370 }
371}
372
373static void
374saa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
375{
376 /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
377 * Do a few smart things so fbValidateGC can do it's work.
378 */
379
380 ScreenPtr pScreen = pDrawable->pScreen;
381 struct saa_screen_priv *sscreen = saa_screen(pScreen);
382 struct saa_gc_priv *sgc = saa_gc(pGC);
383 PixmapPtr pTile = NULL;
384 Bool finish_current_tile = FALSE;
385
386 /* Either of these conditions is enough to trigger access to a tile pixmap. */
387 /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */
388 if (pGC->fillStyle == FillTiled
389 || ((changes & GCTile) && !pGC->tileIsPixel)) {
390 pTile = pGC->tile.pixmap;
391
392 /* Sometimes tile pixmaps are swapped, you need access to:
393 * - The current tile if it depth matches.
394 * - Or the rotated tile if that one matches depth and !(changes & GCTile).
395 * - Or the current tile pixmap and a newly created one.
396 */
397 if (pTile && pTile->drawable.depth != pDrawable->depth
398 && !(changes & GCTile)) {
399 PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC);
400
401 if (pRotatedTile
402 && pRotatedTile->drawable.depth == pDrawable->depth)
403 pTile = pRotatedTile;
404 else
405 finish_current_tile = TRUE; /* CreatePixmap will be called. */
406 }
407 }
408
409 if (pGC->stipple && !saa_pad_read(&pGC->stipple->drawable)) {
410 LogMessage(X_ERROR, "Failed stipple prepareaccess.\n");
411 return;
412 }
413
414 if (pTile && !saa_pad_read(&pTile->drawable)) {
415 LogMessage(X_ERROR, "Failed stipple prepareaccess.\n");
416 goto out_no_tile;
417 }
418
419 /* Calls to Create/DestroyPixmap have to be identified as special, so
420 * up sscreen->fallback_count.
421 */
422
423 sscreen->fallback_count++;
424 saa_swap(sgc, pGC, funcs);
425 (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
426 saa_swap(sgc, pGC, funcs);
427
428 if (finish_current_tile && pGC->tile.pixmap)
429 saa_fad_write(&pGC->tile.pixmap->drawable, SAA_ACCESS_W);
430 sscreen->fallback_count--;
431
432 if (pTile)
433 saa_fad_read(&pTile->drawable);
434 out_no_tile:
435 if (pGC->stipple)
436 saa_fad_read(&pGC->stipple->drawable);
437}
438
439static void
440saa_destroy_gc(GCPtr pGC)
441{
442 struct saa_gc_priv *sgc = saa_gc(pGC);
443
444 saa_swap(sgc, pGC, funcs);
445 (*pGC->funcs->DestroyGC) (pGC);
446 saa_swap(sgc, pGC, funcs);
447}
448
449static void
450saa_change_gc(GCPtr pGC, unsigned long mask)
451{
452 struct saa_gc_priv *sgc = saa_gc(pGC);
453
454 saa_swap(sgc, pGC, funcs);
455 (*pGC->funcs->ChangeGC) (pGC, mask);
456 saa_swap(sgc, pGC, funcs);
457}
458
459static void
460saa_copy_gc(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
461{
462 struct saa_gc_priv *sgc = saa_gc(pGCDst);
463
464 saa_swap(sgc, pGCDst, funcs);
465 (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
466 saa_swap(sgc, pGCDst, funcs);
467}
468
469static void
470saa_change_clip(GCPtr pGC, int type, pointer pvalue, int nrects)
471{
472 struct saa_gc_priv *sgc = saa_gc(pGC);
473
474 saa_swap(sgc, pGC, funcs);
475 (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
476 saa_swap(sgc, pGC, funcs);
477}
478
479static void
480saa_copy_clip(GCPtr pGCDst, GCPtr pGCSrc)
481{
482 struct saa_gc_priv *sgc = saa_gc(pGCDst);
483
484 saa_swap(sgc, pGCDst, funcs);
485 (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc);
486 saa_swap(sgc, pGCDst, funcs);
487}
488
489static void
490saa_destroy_clip(GCPtr pGC)
491{
492 struct saa_gc_priv *sgc = saa_gc(pGC);
493
494 saa_swap(sgc, pGC, funcs);
495 (*pGC->funcs->DestroyClip) (pGC);
496 saa_swap(sgc, pGC, funcs);
497}
498
499static GCFuncs saa_gc_funcs = {
500 saa_validate_gc,
501 saa_change_gc,
502 saa_copy_gc,
503 saa_destroy_gc,
504 saa_change_clip,
505 saa_destroy_clip,
506 saa_copy_clip
507};
508
509/**
510 * saa_create_gc makes a new GC and hooks up its funcs handler, so that
511 * saa_validate_gc() will get called.
512 */
513int
514saa_create_gc(GCPtr pGC)
515{
516 ScreenPtr pScreen = pGC->pScreen;
517 struct saa_screen_priv *sscreen = saa_screen(pScreen);
518 struct saa_gc_priv *sgc = saa_gc(pGC);
519 Bool ret;
520
521 saa_swap(sscreen, pScreen, CreateGC);
522 ret = pScreen->CreateGC(pGC);
523 if (ret) {
524 saa_wrap(sgc, pGC, funcs, &saa_gc_funcs);
525 saa_wrap(sgc, pGC, ops, &saa_gc_ops);
526 }
527 saa_swap(sscreen, pScreen, CreateGC);
528
529 return ret;
530}
531
532static Bool
533saa_prepare_access_window(WindowPtr pWin)
534{
535 if (pWin->backgroundState == BackgroundPixmap) {
536 if (!saa_pad_read(&pWin->background.pixmap->drawable))
537 return FALSE;
538 }
539
540 if (pWin->borderIsPixel == FALSE) {
541 if (!saa_pad_read(&pWin->border.pixmap->drawable)) {
542 if (pWin->backgroundState == BackgroundPixmap)
543 saa_fad_read(&pWin->background.pixmap->drawable);
544 return FALSE;
545 }
546 }
547 return TRUE;
548}
549
550static void
551saa_finish_access_window(WindowPtr pWin)
552{
553 if (pWin->backgroundState == BackgroundPixmap)
554 saa_fad_read(&pWin->background.pixmap->drawable);
555
556 if (pWin->borderIsPixel == FALSE)
557 saa_fad_read(&pWin->border.pixmap->drawable);
558}
559
560static Bool
561saa_change_window_attributes(WindowPtr pWin, unsigned long mask)
562{
563 Bool ret;
564
565 if (!saa_prepare_access_window(pWin))
566 return FALSE;
567 ret = fbChangeWindowAttributes(pWin, mask);
568 saa_finish_access_window(pWin);
569 return ret;
570}
571
572RegionPtr
573saa_bitmap_to_region(PixmapPtr pPix)
574{
575 RegionPtr ret;
576
577 if (!saa_pad_read(&pPix->drawable))
578 return NULL;
579 ret = fbPixmapToRegion(pPix);
580 saa_fad_read(&pPix->drawable);
581 return ret;
582}
583
584void
585saa_set_fallback_debug(ScreenPtr screen, Bool enable)
586{
587 struct saa_screen_priv *sscreen = saa_screen(screen);
588
589 sscreen->fallback_debug = enable;
590}
591
592/**
593 * saa_close_screen() unwraps its wrapped screen functions and tears down SAA's
594 * screen private, before calling down to the next CloseScreen.
595 */
596Bool
597saa_close_screen(int i, ScreenPtr pScreen)
598{
599 struct saa_screen_priv *sscreen = saa_screen(pScreen);
600 struct saa_driver *driver = sscreen->driver;
601
602 if (pScreen->devPrivate) {
603 /* Destroy the pixmap created by miScreenInit() *before*
604 * chaining up as we finalize ourselves here and so this
605 * is the last chance we have of releasing our resources
606 * associated with the Pixmap. So do it first.
607 */
608 (void)(*pScreen->DestroyPixmap) (pScreen->devPrivate);
609 pScreen->devPrivate = NULL;
610 }
611
612 saa_unwrap(sscreen, pScreen, CloseScreen);
613 saa_unwrap(sscreen, pScreen, CreateGC);
614 saa_unwrap(sscreen, pScreen, ChangeWindowAttributes);
615 saa_unwrap(sscreen, pScreen, CreatePixmap);
616 saa_unwrap(sscreen, pScreen, DestroyPixmap);
617 saa_unwrap(sscreen, pScreen, ModifyPixmapHeader);
618 saa_unwrap(sscreen, pScreen, BitmapToRegion);
619#ifdef RENDER
620 saa_render_takedown(pScreen);
621#endif
622 saa_unaccel_takedown(pScreen);
623 driver->takedown(driver);
624
625 free(sscreen);
626
627 return (*pScreen->CloseScreen) (i, pScreen);
628}
629
630struct saa_driver *
631saa_get_driver(ScreenPtr pScreen)
632{
633 return saa_screen(pScreen)->driver;
634}
635
636/**
637 * @param pScreen screen being initialized
638 * @param pScreenInfo SAA driver record
639 *
640 * saa_driver_init sets up SAA given a driver record filled in by the driver.
641 * pScreenInfo should have been allocated by saa_driver_alloc(). See the
642 * comments in _SaaDriver for what must be filled in and what is optional.
643 *
644 * @return TRUE if SAA was successfully initialized.
645 */
646Bool
647saa_driver_init(ScreenPtr screen, struct saa_driver * saa_driver)
648{
649 struct saa_screen_priv *sscreen;
650
651 if (!saa_driver)
652 return FALSE;
653
654 if (saa_driver->saa_major != SAA_VERSION_MAJOR ||
655 saa_driver->saa_minor > SAA_VERSION_MINOR) {
656 LogMessage(X_ERROR,
657 "SAA(%d): driver's SAA version requirements "
658 "(%d.%d) are incompatible with SAA version (%d.%d)\n",
659 screen->myNum, saa_driver->saa_major,
660 saa_driver->saa_minor, SAA_VERSION_MAJOR, SAA_VERSION_MINOR);
661 return FALSE;
662 }
663#if 0
664 if (!saa_driver->prepare_solid) {
665 LogMessage(X_ERROR,
666 "SAA(%d): saa_driver_t::prepare_solid must be "
667 "non-NULL\n", screen->myNum);
668 return FALSE;
669 }
670
671 if (!saa_driver->prepare_copy) {
672 LogMessage(X_ERROR,
673 "SAA(%d): saa_driver_t::prepare_copy must be "
674 "non-NULL\n", screen->myNum);
675 return FALSE;
676 }
677#endif
678#ifdef SAA_DEVPRIVATEKEYREC
679 if (!dixRegisterPrivateKey(&saa_screen_index, PRIVATE_SCREEN, 0)) {
680 LogMessage(X_ERROR, "Failed to register SAA screen private.\n");
681 return FALSE;
682 }
683 if (!dixRegisterPrivateKey(&saa_pixmap_index, PRIVATE_PIXMAP,
684 saa_driver->pixmap_size)) {
685 LogMessage(X_ERROR, "Failed to register SAA pixmap private.\n");
686 return FALSE;
687 }
688 if (!dixRegisterPrivateKey(&saa_gc_index, PRIVATE_GC,
689 sizeof(struct saa_gc_priv))) {
690 LogMessage(X_ERROR, "Failed to register SAA gc private.\n");
691 return FALSE;
692 }
693#else
694 if (!dixRequestPrivate(&saa_screen_index, 0)) {
695 LogMessage(X_ERROR, "Failed to register SAA screen private.\n");
696 return FALSE;
697 }
698 if (!dixRequestPrivate(&saa_pixmap_index, saa_driver->pixmap_size)) {
699 LogMessage(X_ERROR, "Failed to register SAA pixmap private.\n");
700 return FALSE;
701 }
702 if (!dixRequestPrivate(&saa_gc_index, sizeof(struct saa_gc_priv))) {
703 LogMessage(X_ERROR, "Failed to register SAA gc private.\n");
704 return FALSE;
705 }
706#endif
707
708 sscreen = calloc(1, sizeof(*sscreen));
709
710 if (!sscreen) {
711 LogMessage(X_WARNING,
712 "SAA(%d): Failed to allocate screen private\n",
713 screen->myNum);
714 return FALSE;
715 }
716
717 sscreen->driver = saa_driver;
718 dixSetPrivate(&screen->devPrivates, &saa_screen_index, sscreen);
719
720 /*
721 * Replace various fb screen functions
722 */
723
724 saa_wrap(sscreen, screen, CloseScreen, saa_close_screen);
725 saa_wrap(sscreen, screen, CreateGC, saa_create_gc);
726 saa_wrap(sscreen, screen, ChangeWindowAttributes,
727 saa_change_window_attributes);
728 saa_wrap(sscreen, screen, CreatePixmap, saa_create_pixmap);
729 saa_wrap(sscreen, screen, DestroyPixmap, saa_destroy_pixmap);
730 saa_wrap(sscreen, screen, ModifyPixmapHeader, saa_modify_pixmap_header);
731
732 saa_wrap(sscreen, screen, BitmapToRegion, saa_bitmap_to_region);
733 saa_unaccel_setup(screen);
734#ifdef RENDER
735 saa_render_setup(screen);
736#endif
737
738 return TRUE;
739}
740
741Bool
742saa_resources_init(ScreenPtr screen)
743{
744/* if (!saa_glyphs_init(screen))
745 return FALSE;
746*/
747 return TRUE;
748}
diff --git a/saa/saa.h b/saa/saa.h
new file mode 100644
index 0000000..c7aa3b6
--- /dev/null
+++ b/saa/saa.h
@@ -0,0 +1,209 @@
1/*
2 *
3 * Copyright (C) 2000 Keith Packard
4 * 2004 Eric Anholt
5 * 2005 Zack Rusin
6 *
7 * Copyright 2011 VMWare, Inc. All rights reserved.
8 *
9 * Permission to use, copy, modify, distribute, and sell this software and its
10 * documentation for any purpose is hereby granted without fee, provided that
11 * the above copyright notice appear in all copies and that both that
12 * copyright notice and this permission notice appear in supporting
13 * documentation, and that the name of copyright holders not be used in
14 * advertising or publicity pertaining to distribution of the software without
15 * specific, written prior permission. Copyright holders make no
16 * representations about the suitability of this software for any purpose. It
17 * is provided "as is" without express or implied warranty.
18 *
19 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
20 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
24 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
25 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26 * SOFTWARE.
27 *
28 * Author: Based on "exa.h"
29 * Author: Thomas Hellstrom <thellstrom@vmware.com>
30 */
31
32#ifndef _SAA_H_
33#define _SAA_H_
34
35#ifdef HAVE_CONFIG_H
36#include <config.h>
37#endif
38#ifdef HAVE_DIX_CONFIG_H
39#include <dix-config.h>
40#else
41#include <xorg-server.h>
42#endif
43#include <xf86.h>
44#include <damage.h>
45#include <picturestr.h>
46
47#define SAA_VERSION_MAJOR 0
48#define SAA_VERSION_MINOR 1
49
50#define SAA_ACCESS_R (1 << 0)
51#define SAA_ACCESS_W (1 << 1)
52#define SAA_ACCESS_RW (SAA_ACCESS_R | SAA_ACCESS_W)
53
54#define SAA_PIXMAP_HINT_CREATE_HW (1 << 25)
55#define SAA_PIXMAP_PREFER_SHADOW (1 << 0)
56
57typedef unsigned int saa_access_t;
58
59enum saa_pixmap_loc {
60 saa_loc_driver,
61 saa_loc_override,
62};
63
64struct saa_pixmap {
65 PixmapPtr pixmap;
66 int read_access;
67 int write_access;
68 unsigned int mapped_access;
69 Bool fallback_created;
70 RegionRec dirty_shadow;
71 RegionRec dirty_hw;
72 RegionRec shadow_damage;
73 DamagePtr damage;
74 void *addr;
75 void *override;
76 enum saa_pixmap_loc auth_loc;
77 PictFormatShort src_format;
78 PictFormatShort dst_format;
79 uint32_t pad[16];
80};
81
82struct saa_driver {
83 unsigned int saa_major;
84 unsigned int saa_minor;
85 size_t pixmap_size;
86 Bool(*damage) (struct saa_driver * driver, PixmapPtr pixmap,
87 Bool hw, RegionPtr damage);
88 void (*operation_complete) (struct saa_driver * driver, PixmapPtr pixmap);
89 Bool(*download_from_hw) (struct saa_driver * driver, PixmapPtr pixmap,
90 RegionPtr readback);
91 void (*release_from_cpu) (struct saa_driver * driver, PixmapPtr pixmap,
92 saa_access_t access);
93 void *(*sync_for_cpu) (struct saa_driver * driver, PixmapPtr pixmap,
94 saa_access_t access);
95 void *(*map) (struct saa_driver * driver, PixmapPtr pixmap,
96 saa_access_t access);
97 void (*unmap) (struct saa_driver * driver, PixmapPtr pixmap,
98 saa_access_t access);
99 Bool(*create_pixmap) (struct saa_driver * driver, struct saa_pixmap * spix,
100 int w, int h, int depth, unsigned int usage_hint,
101 int bpp, int *new_pitch);
102 void (*destroy_pixmap) (struct saa_driver * driver, PixmapPtr pixmap);
103 Bool (*modify_pixmap_header) (PixmapPtr pixmap, int w, int h, int depth,
104 int bpp, int devkind, void *pPixData);
105
106 Bool (*copy_prepare) (struct saa_driver * driver, PixmapPtr src_pixmap,
107 PixmapPtr dst_pixmap, int dx, int dy, int alu,
108 RegionPtr scr_reg, uint32_t plane_mask);
109 void (*copy) (struct saa_driver * driver, int src_x, int src_y, int dst_x,
110 int dst_y, int w, int h);
111 void (*copy_done) (struct saa_driver * driver);
112 Bool (*composite_prepare) (struct saa_driver *driver, CARD8 op,
113 PicturePtr src_pict, PicturePtr mask_pict,
114 PicturePtr dst_pict,
115 PixmapPtr src_pix, PixmapPtr mask_pix,
116 PixmapPtr dst_pix,
117 RegionPtr src_region,
118 RegionPtr mask_region,
119 RegionPtr dst_region);
120 void (*composite) (struct saa_driver *driver,
121 int src_x, int src_y, int mask_x, int mask_y,
122 int dst_x, int dst_y,
123 int width, int height);
124 void (*composite_done) (struct saa_driver *driver);
125
126 void (*takedown) (struct saa_driver * driver);
127 uint32_t pad[16];
128};
129
130extern _X_EXPORT PixmapPtr
131saa_get_drawable_pixmap(DrawablePtr pDrawable);
132
133extern _X_EXPORT void
134saa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap,
135 int *xp, int *yp);
136
137extern _X_EXPORT PixmapPtr
138saa_get_pixmap(DrawablePtr drawable, int *xp, int *yp);
139
140extern _X_EXPORT Bool
141saa_prepare_access_pixmap(PixmapPtr pix, saa_access_t access,
142 RegionPtr read_reg);
143
144extern _X_EXPORT Bool
145saa_pad_read(DrawablePtr draw);
146
147Bool
148saa_pad_read_box(DrawablePtr draw, int x, int y, int w, int h);
149
150extern _X_EXPORT Bool
151saa_pad_write(DrawablePtr draw, GCPtr pGC, Bool check_read,
152 saa_access_t * access);
153
154extern _X_EXPORT void
155saa_finish_access_pixmap(PixmapPtr pix, saa_access_t access);
156
157extern _X_EXPORT void
158saa_fad_read(DrawablePtr draw);
159
160extern _X_EXPORT void
161saa_fad_write(DrawablePtr draw, saa_access_t access);
162
163extern _X_EXPORT Bool
164saa_resources_init(ScreenPtr screen);
165
166extern _X_EXPORT void
167saa_driver_fini(ScreenPtr pScreen);
168
169extern _X_EXPORT int
170saa_create_gc(GCPtr pGC);
171
172extern _X_EXPORT RegionPtr
173saa_bitmap_to_region(PixmapPtr pPix);
174
175extern _X_EXPORT Bool
176saa_close_screen(int i, ScreenPtr pScreen);
177
178extern _X_EXPORT Bool
179saa_gc_reads_destination(DrawablePtr pDrawable, GCPtr pGC);
180
181extern _X_EXPORT Bool
182saa_op_reads_destination(CARD8 op);
183
184extern _X_EXPORT void
185saa_set_fallback_debug(ScreenPtr screen, Bool enable);
186
187extern _X_EXPORT
188struct saa_pixmap *saa_get_saa_pixmap(PixmapPtr pPixmap);
189
190extern _X_EXPORT Bool
191saa_add_damage(PixmapPtr pixmap);
192
193extern _X_EXPORT struct saa_driver *
194saa_get_driver(ScreenPtr pScreen);
195
196extern _X_EXPORT Bool
197saa_driver_init(ScreenPtr screen, struct saa_driver *saa_driver);
198
199extern _X_EXPORT void
200saa_pixmap_dirty(PixmapPtr pixmap, Bool hw, RegionPtr reg);
201
202extern _X_EXPORT void
203saa_drawable_dirty(DrawablePtr draw, Bool hw, RegionPtr reg);
204
205#define SAA_PM_IS_SOLID(_pDrawable, _pm) \
206 (((_pm) & FbFullMask((_pDrawable)->depth)) == \
207 FbFullMask((_pDrawable)->depth))
208
209#endif
diff --git a/saa/saa_accel.c b/saa/saa_accel.c
new file mode 100644
index 0000000..5e1501b
--- /dev/null
+++ b/saa/saa_accel.c
@@ -0,0 +1,153 @@
1/*
2 * Copyright © 2001 Keith Packard
3 * Copyright 2011 VMWare, Inc. All Rights Reserved.
4 * May partly be based on code that is Copyright © The XFree86 Project Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * Author: Eric Anholt <eric@anholt.net>
27 * Author: Michel Dänzer <michel@tungstengraphics.com>
28 * Author: Thomas Hellstrom <thellstrom@vmware.com>
29 */
30
31#include "saa.h"
32#include "saa_priv.h"
33#include <mi.h>
34
35Bool
36saa_hw_copy_nton(DrawablePtr pSrcDrawable,
37 DrawablePtr pDstDrawable,
38 GCPtr pGC,
39 BoxPtr pbox,
40 int nbox, int dx, int dy, Bool reverse, Bool upsidedown)
41{
42 ScreenPtr pScreen = pDstDrawable->pScreen;
43 struct saa_screen_priv *sscreen = saa_screen(pDstDrawable->pScreen);
44 struct saa_driver *driver = sscreen->driver;
45 PixmapPtr pSrcPixmap, pDstPixmap;
46 struct saa_pixmap *src_spix, *dst_spix;
47 int src_off_x, src_off_y;
48 int dst_off_x, dst_off_y;
49 RegionRec dst_reg, *src_reg;
50 int ordering;
51 Bool ret = TRUE;
52
53 (void)pScreen;
54
55 /* avoid doing copy operations if no boxes */
56 if (nbox == 0)
57 return TRUE;
58
59 pSrcPixmap = saa_get_pixmap(pSrcDrawable, &src_off_x, &src_off_y);
60 pDstPixmap = saa_get_pixmap(pDstDrawable, &dst_off_x, &dst_off_y);
61 src_spix = saa_pixmap(pSrcPixmap);
62 dst_spix = saa_pixmap(pDstPixmap);
63
64 if (src_spix->auth_loc != saa_loc_driver ||
65 dst_spix->auth_loc != saa_loc_driver)
66 return FALSE;
67
68
69 ordering = (nbox == 1 || (dx > 0 && dy > 0) ||
70 (pDstDrawable != pSrcDrawable &&
71 (pDstDrawable->type != DRAWABLE_WINDOW ||
72 pSrcDrawable->type != DRAWABLE_WINDOW))) ?
73 CT_YXBANDED : CT_UNSORTED;
74
75 src_reg = saa_boxes_to_region(pScreen, nbox, pbox, ordering);
76 if (!src_reg)
77 return FALSE;
78
79 REGION_NULL(pScreen, &dst_reg);
80 REGION_COPY(pScreen, &dst_reg, src_reg);
81 REGION_TRANSLATE(pScreen, src_reg, dx + src_off_x, dy + src_off_y);
82 REGION_TRANSLATE(pScreen, &dst_reg, dst_off_x, dst_off_y);
83
84 if (!(driver->copy_prepare) (driver, pSrcPixmap, pDstPixmap,
85 reverse ? -1 : 1,
86 upsidedown ? -1 : 1,
87 pGC ? pGC->alu : GXcopy,
88 src_reg, pGC ? pGC->planemask : FB_ALLONES)) {
89 goto fallback;
90 }
91
92 while (nbox--) {
93 (driver->copy) (driver,
94 pbox->x1 + dx + src_off_x,
95 pbox->y1 + dy + src_off_y,
96 pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
97 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
98 pbox++;
99 }
100
101 (driver->copy_done) (driver);
102 saa_pixmap_dirty(pDstPixmap, TRUE, &dst_reg);
103 goto out;
104
105 fallback:
106 ret = FALSE;
107
108 out:
109 REGION_UNINIT(pScreen, &dst_reg);
110 REGION_DESTROY(pScreen, src_reg);
111
112 return ret;
113}
114
115static void
116saa_copy_nton(DrawablePtr pSrcDrawable,
117 DrawablePtr pDstDrawable,
118 GCPtr pGC,
119 BoxPtr pbox,
120 int nbox,
121 int dx,
122 int dy,
123 Bool reverse, Bool upsidedown, Pixel bitplane, void *closure)
124{
125 if (saa_hw_copy_nton(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy,
126 reverse, upsidedown))
127 return;
128
129 saa_check_copy_nton(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy,
130 reverse, upsidedown, bitplane, closure);
131}
132
133RegionPtr
134saa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
135 int srcx, int srcy, int width, int height, int dstx, int dsty)
136{
137 struct saa_screen_priv *sscreen = saa_screen(pDstDrawable->pScreen);
138
139 if (sscreen->fallback_count) {
140 return saa_check_copy_area(pSrcDrawable, pDstDrawable, pGC,
141 srcx, srcy, width, height, dstx, dsty);
142 }
143
144#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 6)
145 return miDoCopy(pSrcDrawable, pDstDrawable, pGC,
146 srcx, srcy, width, height,
147 dstx, dsty, saa_copy_nton, 0, NULL);
148#else
149 return fbDoCopy(pSrcDrawable, pDstDrawable, pGC,
150 srcx, srcy, width, height,
151 dstx, dsty, saa_copy_nton, 0, NULL);
152#endif
153}
diff --git a/saa/saa_pixmap.c b/saa/saa_pixmap.c
new file mode 100644
index 0000000..0d63091
--- /dev/null
+++ b/saa/saa_pixmap.c
@@ -0,0 +1,222 @@
1/*
2 * Copyright © 2009 Maarten Maathuis
3 * Copyright 2011 VMWare, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Based on "exa_driver.c"
26 * Author: Thomas Hellstrom <thellstrom@vmware.com>
27 */
28
29#include "saa_priv.h"
30#include "saa.h"
31
32PixmapPtr
33saa_create_pixmap(ScreenPtr pScreen, int w, int h, int depth,
34 unsigned usage_hint)
35{
36 PixmapPtr pPixmap;
37 struct saa_pixmap *spix;
38 int bpp;
39 size_t paddedWidth;
40 struct saa_screen_priv *sscreen = saa_screen(pScreen);
41 int new_pitch = 0;
42 struct saa_driver *driver = sscreen->driver;
43
44 if (w > 32767 || h > 32767)
45 return NullPixmap;
46
47 /*
48 * Create a scratch pixmap without backing storage (w and h are zero)
49 */
50
51 saa_swap(sscreen, pScreen, CreatePixmap);
52 pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
53 saa_swap(sscreen, pScreen, CreatePixmap);
54
55 if (!pPixmap)
56 goto out_no_pix;
57
58 spix = saa_pixmap(pPixmap);
59 memset(spix, 0, driver->pixmap_size);
60 REGION_NULL(pScreen, &spix->dirty_shadow);
61 REGION_NULL(pScreen, &spix->dirty_hw);
62 REGION_NULL(pScreen, &spix->shadow_damage);
63 spix->read_access = 0;
64 spix->write_access = 0;
65 spix->mapped_access = 0;
66 spix->addr = NULL;
67 spix->auth_loc = saa_loc_override;
68 spix->override = SAA_INVALID_ADDRESS;
69 spix->pixmap = pPixmap;
70 bpp = pPixmap->drawable.bitsPerPixel;
71
72 if (!driver->create_pixmap(driver, spix, w, h, depth,
73 usage_hint, bpp, &new_pitch))
74 goto out_no_driver_priv;
75
76 paddedWidth = new_pitch;
77 spix->damage = NULL;
78
79 /*
80 * Now set w and h to the correct value. This might allocate
81 * backing store if w and h are NON-NULL.
82 */
83
84 if (!(*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0,
85 paddedWidth, NULL))
86 goto out_no_pixmap_header;
87
88 /*
89 * During a fallback we must prepare access. This hack is initially used
90 * for pixmaps created during ValidateGC.
91 */
92
93 spix->fallback_created = FALSE;
94 if (sscreen->fallback_count) {
95 if (!saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_W, NULL))
96 goto out_no_access;
97
98 spix->fallback_created = TRUE;
99 }
100
101 return pPixmap;
102 out_no_access:
103 out_no_pixmap_header:
104 driver->destroy_pixmap(driver, pPixmap);
105 out_no_driver_priv:
106 saa_swap(sscreen, pScreen, DestroyPixmap);
107 pScreen->DestroyPixmap(pPixmap);
108 saa_swap(sscreen, pScreen, DestroyPixmap);
109 out_no_pix:
110 LogMessage(X_ERROR, "Failing pixmap creation.\n");
111 return NullPixmap;
112}
113
114Bool
115saa_destroy_pixmap(PixmapPtr pPixmap)
116{
117 ScreenPtr pScreen = pPixmap->drawable.pScreen;
118 struct saa_screen_priv *sscreen = saa_screen(pScreen);
119 Bool ret;
120 struct saa_driver *driver = sscreen->driver;
121
122 if (pPixmap->refcnt == 1) {
123 struct saa_pixmap *spix = saa_pixmap(pPixmap);
124
125 if (spix->fallback_created) {
126 if (!sscreen->fallback_count)
127 LogMessage(X_ERROR, "Fallback pixmap destroyed outside "
128 "fallback.\n");
129
130 saa_finish_access_pixmap(pPixmap, SAA_ACCESS_W);
131 }
132
133 driver->destroy_pixmap(driver, pPixmap);
134
135 REGION_UNINIT(pScreen, &spix->dirty_hw);
136 REGION_UNINIT(pScreen, &spix->dirty_shadow);
137 spix->damage = NULL;
138 }
139
140 saa_swap(sscreen, pScreen, DestroyPixmap);
141 ret = pScreen->DestroyPixmap(pPixmap);
142 saa_swap(sscreen, pScreen, DestroyPixmap);
143
144 return ret;
145}
146
147Bool
148saa_modify_pixmap_header(PixmapPtr pPixmap, int width, int height, int depth,
149 int bitsPerPixel, int devKind, pointer pPixData)
150{
151 ScreenPtr pScreen;
152 struct saa_screen_priv *sscreen;
153 struct saa_pixmap *spix;
154 struct saa_driver *driver;
155 Bool ret = TRUE;
156
157 if (!pPixmap)
158 return FALSE;
159
160 pScreen = pPixmap->drawable.pScreen;
161 sscreen = saa_screen(pScreen);
162 spix = saa_pixmap(pPixmap);
163 driver = sscreen->driver;
164
165 if (spix && driver->modify_pixmap_header &&
166 driver->modify_pixmap_header(pPixmap, width, height, depth,
167 bitsPerPixel, devKind, pPixData)) {
168 spix->auth_loc = saa_loc_driver;
169 spix->override = SAA_INVALID_ADDRESS;
170 goto out;
171 }
172
173 saa_swap(sscreen, pScreen, ModifyPixmapHeader);
174 ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
175 bitsPerPixel, devKind, pPixData);
176 saa_swap(sscreen, pScreen, ModifyPixmapHeader);
177 spix->override = pPixmap->devPrivate.ptr;
178 spix->auth_loc = saa_loc_override;
179
180 out:
181 pPixmap->devPrivate.ptr = NULL;
182 return ret;
183}
184
185struct saa_pixmap *
186saa_get_saa_pixmap(PixmapPtr pPixmap)
187{
188 return saa_pixmap(pPixmap);
189}
190
191void
192saa_pixmap_dirty(PixmapPtr pixmap, Bool hw, RegionPtr reg)
193{
194 struct saa_pixmap *spix = saa_pixmap(pixmap);
195 struct saa_screen_priv *sscreen = saa_screen(pixmap->drawable.pScreen);
196
197 if (hw) {
198 REGION_UNION(pixmap->drawable.pScreen, &spix->dirty_hw,
199 &spix->dirty_hw, reg);
200 REGION_SUBTRACT(pixmap->drawable.pScreen, &spix->dirty_shadow,
201 &spix->dirty_shadow, reg);
202 } else {
203 REGION_UNION(pixmap->drawable.pScreen, &spix->dirty_shadow,
204 &spix->dirty_shadow, reg);
205 REGION_SUBTRACT(pixmap->drawable.pScreen, &spix->dirty_hw,
206 &spix->dirty_hw, reg);
207 }
208
209 sscreen->driver->damage(sscreen->driver, pixmap, hw, reg);
210}
211
212void
213saa_drawable_dirty(DrawablePtr draw, Bool hw, RegionPtr reg)
214{
215 PixmapPtr pixmap;
216 int x_offset, y_offset;
217
218 pixmap = saa_get_pixmap(draw, &x_offset, &y_offset);
219 REGION_TRANSLATE(draw->pScreen, reg, x_offset, y_offset);
220 saa_pixmap_dirty(pixmap, hw, reg);
221 REGION_TRANSLATE(draw->pScreen, reg, -x_offset, -y_offset);
222}
diff --git a/saa/saa_priv.h b/saa/saa_priv.h
new file mode 100644
index 0000000..6652054
--- /dev/null
+++ b/saa/saa_priv.h
@@ -0,0 +1,279 @@
1/*
2 *
3 * Copyright (C) 2000 Keith Packard, member of The XFree86 Project, Inc.
4 * 2005 Zack Rusin, Trolltech
5 * Copyright 2011 VMWare, inc. All rights reserved.
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Keith Packard not be used in
12 * advertising or publicity pertaining to distribution of the software without
13 * specific, written prior permission. Keith Packard makes no
14 * representations about the suitability of this software for any purpose. It
15 * is provided "as is" without express or implied warranty.
16 *
17 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
18 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
19 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
22 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
23 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
24 * SOFTWARE.
25 *
26 * Authors: Based on exa_priv.h
27 * Authors: Thomas Hellstrom <thellstrom@vmware.com>
28 */
29
30#ifndef _SAA_PRIV_H
31#define _SAA_PRIV_H
32
33#ifdef HAVE_CONFIG_H
34#include <config.h>
35#endif
36#ifdef HAVE_DIX_CONFIG_H
37#include <dix-config.h>
38#else
39#include <xorg-server.h>
40#endif
41#include "xf86.h"
42
43#include "saa.h"
44
45#include <X11/X.h>
46#include <X11/Xproto.h>
47#include "scrnintstr.h"
48#include "pixmapstr.h"
49#include "windowstr.h"
50#include "servermd.h"
51#include "mibstore.h"
52#include "colormapst.h"
53#include "gcstruct.h"
54#include "input.h"
55#include "mipointer.h"
56#include "mi.h"
57#include "dix.h"
58#include "fb.h"
59#ifdef RENDER
60#include "glyphstr.h"
61#endif
62#include "damage.h"
63
64#define SAA_INVALID_ADDRESS \
65 ((void *) ((unsigned long) 0xFFFFFFFF - 1024*1024))
66
67struct saa_gc_priv {
68 /* GC values from the layer below. */
69 GCOps *saved_ops;
70 GCFuncs *saved_funcs;
71};
72
73struct saa_screen_priv {
74 struct saa_driver *driver;
75 CreateGCProcPtr saved_CreateGC;
76 CloseScreenProcPtr saved_CloseScreen;
77 GetImageProcPtr saved_GetImage;
78 GetSpansProcPtr saved_GetSpans;
79 CreatePixmapProcPtr saved_CreatePixmap;
80 DestroyPixmapProcPtr saved_DestroyPixmap;
81 CopyWindowProcPtr saved_CopyWindow;
82 ChangeWindowAttributesProcPtr saved_ChangeWindowAttributes;
83 BitmapToRegionProcPtr saved_BitmapToRegion;
84 ModifyPixmapHeaderProcPtr saved_ModifyPixmapHeader;
85#ifdef RENDER
86 CompositeProcPtr saved_Composite;
87 CompositeRectsProcPtr saved_CompositeRects;
88 TrianglesProcPtr saved_Triangles;
89 GlyphsProcPtr saved_Glyphs;
90 TrapezoidsProcPtr saved_Trapezoids;
91 AddTrapsProcPtr saved_AddTraps;
92 UnrealizeGlyphProcPtr saved_UnrealizeGlyph;
93 SourceValidateProcPtr saved_SourceValidate;
94#endif
95 Bool fallback_debug;
96
97 unsigned int fallback_count;
98
99 RegionRec srcReg;
100 RegionRec maskReg;
101 DrawablePtr srcDraw;
102};
103
104extern GCOps saa_gc_ops;
105
106#if DEBUG_TRACE_FALL
107#define SAA_FALLBACK(x) \
108do { \
109 ErrorF("SAA fallback at %s: ", __FUNCTION__); \
110 ErrorF x; \
111} while (0)
112
113#define saa_drawable_location() ("u")
114#else
115#define SAA_FALLBACK(x)
116#endif
117
118/*
119 * Some macros to deal with function wrapping.
120 */
121#define saa_wrap(priv, real, mem, func) {\
122 (priv)->saved_##mem = (real)->mem; \
123 (real)->mem = func; \
124}
125
126#define saa_unwrap(priv, real, mem) {\
127 (real)->mem = (priv)->saved_##mem; \
128}
129
130#define saa_swap(priv, real, mem) {\
131 void *tmp = (priv)->saved_##mem; \
132 (priv)->saved_##mem = (real)->mem; \
133 (real)->mem = tmp; \
134}
135
136#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 8)
137#define SAA_DEVPRIVATEKEYREC 1
138
139extern DevPrivateKeyRec saa_screen_index;
140extern DevPrivateKeyRec saa_pixmap_index;
141extern DevPrivateKeyRec saa_gc_index;
142
143static inline struct saa_screen_priv *
144saa_screen(ScreenPtr screen)
145{
146 return (struct saa_screen_priv *)dixGetPrivate(&screen->devPrivates,
147 &saa_screen_index);
148}
149
150static inline struct saa_gc_priv *
151saa_gc(GCPtr gc)
152{
153 return (struct saa_gc_priv *)dixGetPrivateAddr(&gc->devPrivates,
154 &saa_gc_index);
155}
156
157static inline struct saa_pixmap *
158saa_pixmap(PixmapPtr pix)
159{
160 return (struct saa_pixmap *)dixGetPrivateAddr(&pix->devPrivates,
161 &saa_pixmap_index);
162}
163#else
164#undef SAA_DEVPRIVATEKEYREC
165extern int saa_screen_index;
166extern int saa_pixmap_index;
167extern int saa_gc_index;
168
169static inline struct saa_screen_priv *
170saa_screen(ScreenPtr screen)
171{
172 return (struct saa_screen_priv *)dixLookupPrivate(&screen->devPrivates,
173 &saa_screen_index);
174}
175
176static inline struct saa_gc_priv *
177saa_gc(GCPtr gc)
178{
179 return (struct saa_gc_priv *)dixLookupPrivateAddr(&gc->devPrivates,
180 &saa_gc_index);
181}
182
183static inline struct saa_pixmap *
184saa_pixmap(PixmapPtr pix)
185{
186 return (struct saa_pixmap *)dixLookupPrivateAddr(&pix->devPrivates,
187 &saa_pixmap_index);
188}
189
190#endif
191
192extern void
193saa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
194 DDXPointPtr ppt, int *pwidth, int fSorted);
195extern void
196saa_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC,
197 int nrect, xRectangle * prect);
198extern RegionPtr
199saa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
200 int srcx, int srcy, int w, int h, int dstx, int dsty);
201extern void
202saa_check_copy_nton(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
203 BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
204 Bool upsidedown, Pixel bitplane, void *closure);
205
206extern void
207saa_unaccel_setup(ScreenPtr pScreen);
208
209extern void
210saa_unaccel_takedown(ScreenPtr pScreen);
211
212extern RegionPtr
213saa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
214 int srcx, int srcy, int width, int height, int dstx, int dsty);
215
216extern Bool
217saa_hw_copy_nton(DrawablePtr pSrcDrawable,
218 DrawablePtr pDstDrawable,
219 GCPtr pGC,
220 BoxPtr pbox,
221 int nbox, int dx, int dy, Bool reverse, Bool upsidedown);
222
223#ifdef RENDER
224extern void
225saa_render_setup(ScreenPtr pScreen);
226
227extern void
228saa_render_takedown(ScreenPtr pScreen);
229
230
231extern void
232saa_check_composite(CARD8 op,
233 PicturePtr pSrc,
234 PicturePtr pMask,
235 PicturePtr pDst,
236 INT16 xSrc,
237 INT16 ySrc,
238 INT16 xMask,
239 INT16 yMask,
240 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height,
241 RegionPtr src_region,
242 RegionPtr mask_region,
243 RegionPtr dst_region);
244#endif
245
246extern Bool
247saa_modify_pixmap_header(PixmapPtr pPixmap, int width, int height, int depth,
248 int bitsPerPixel, int devKind, pointer pPixData);
249
250extern PixmapPtr
251saa_create_pixmap(ScreenPtr pScreen, int w, int h, int depth,
252 unsigned usage_hint);
253
254extern Bool
255saa_destroy_pixmap(PixmapPtr pPixmap);
256
257static inline RegionPtr
258saa_pix_damage_pending(struct saa_pixmap *spix)
259{
260 return (spix->damage ? DamagePendingRegion(spix->damage) : NULL);
261}
262
263extern RegionPtr
264saa_boxes_to_region(ScreenPtr pScreen, int nbox, BoxPtr pbox, int ordering);
265
266
267Bool
268saa_compute_composite_regions(ScreenPtr pScreen,
269 PicturePtr pSrc,
270 PicturePtr pMask,
271 PicturePtr pDst,
272 INT16 xSrc, INT16 ySrc, INT16 xMask,
273 INT16 yMask, INT16 xDst,
274 INT16 yDst, INT16 width, INT16 height,
275 RegionPtr dst_reg,
276 RegionPtr *src_reg,
277 RegionPtr *mask_reg);
278
279#endif
diff --git a/saa/saa_render.c b/saa/saa_render.c
new file mode 100644
index 0000000..c69f2c9
--- /dev/null
+++ b/saa/saa_render.c
@@ -0,0 +1,424 @@
1/*
2 * Copyright © 2001 Keith Packard
3 * Copyright 2011 VMWare, Inc. All Rights Reserved.
4 * May partly be based on code that is Copyright © The XFree86 Project Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * Author: Eric Anholt <eric@anholt.net>
27 * Author: Michel Dänzer <michel@tungstengraphics.com>
28 * Author: Thomas Hellstrom <thellstrom@vmware.com>
29 */
30#include "saa.h"
31#include "saa_priv.h"
32
33#ifdef RENDER
34#include <mipict.h>
35
36/**
37 * Same as miCreateAlphaPicture, except it uses
38 * saa_check_poly_fill_rect instead
39 */
40
41static PicturePtr
42saa_create_alpha_picture(ScreenPtr pScreen,
43 PicturePtr pDst,
44 PictFormatPtr pPictFormat, CARD16 width, CARD16 height)
45{
46 PixmapPtr pPixmap;
47 PicturePtr pPicture;
48 GCPtr pGC;
49 int error;
50 xRectangle rect;
51
52 if (width > 32767 || height > 32767)
53 return 0;
54
55 if (!pPictFormat) {
56 if (pDst->polyEdge == PolyEdgeSharp)
57 pPictFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
58 else
59 pPictFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
60 if (!pPictFormat)
61 return 0;
62 }
63
64 pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
65 pPictFormat->depth, 0);
66 if (!pPixmap)
67 return 0;
68 pGC = GetScratchGC(pPixmap->drawable.depth, pScreen);
69 if (!pGC) {
70 (*pScreen->DestroyPixmap) (pPixmap);
71 return 0;
72 }
73 ValidateGC(&pPixmap->drawable, pGC);
74 rect.x = 0;
75 rect.y = 0;
76 rect.width = width;
77 rect.height = height;
78 saa_check_poly_fill_rect(&pPixmap->drawable, pGC, 1, &rect);
79 FreeScratchGC(pGC);
80 pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
81 0, 0, serverClient, &error);
82 (*pScreen->DestroyPixmap) (pPixmap);
83 return pPicture;
84}
85
86/**
87 * saa_trapezoids is essentially a copy of miTrapezoids that uses
88 * saa_create_alpha_picture instead of miCreateAlphaPicture.
89 *
90 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
91 * to initialize the contents after creating the pixmap, which
92 * causes the pixmap to be moved in for acceleration. The subsequent
93 * call to RasterizeTrapezoid won't be accelerated however, which
94 * forces the pixmap to be moved out again.
95 *
96 */
97static void
98saa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
99 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
100 int ntrap, xTrapezoid * traps)
101{
102 ScreenPtr pScreen = pDst->pDrawable->pScreen;
103 PictureScreenPtr ps = GetPictureScreen(pScreen);
104 BoxRec bounds;
105
106 if (maskFormat) {
107 PicturePtr pPicture;
108 INT16 xDst, yDst;
109 INT16 xRel, yRel;
110 saa_access_t access;
111
112 miTrapezoidBounds(ntrap, traps, &bounds);
113
114 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
115 return;
116
117 xDst = traps[0].left.p1.x >> 16;
118 yDst = traps[0].left.p1.y >> 16;
119
120 pPicture = saa_create_alpha_picture(pScreen, pDst, maskFormat,
121 bounds.x2 - bounds.x1,
122 bounds.y2 - bounds.y1);
123 if (!pPicture)
124 return;
125
126 if (saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access)) {
127 for (; ntrap; ntrap--, traps++)
128 (*ps->RasterizeTrapezoid) (pPicture, traps,
129 -bounds.x1, -bounds.y1);
130 saa_fad_write(pPicture->pDrawable, access);
131 }
132
133 xRel = bounds.x1 + xSrc - xDst;
134 yRel = bounds.y1 + ySrc - yDst;
135 CompositePicture(op, pSrc, pPicture, pDst,
136 xRel, yRel, 0, 0, bounds.x1, bounds.y1,
137 bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
138 FreePicture(pPicture, 0);
139 } else {
140 if (pDst->polyEdge == PolyEdgeSharp)
141 maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
142 else
143 maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
144 for (; ntrap; ntrap--, traps++)
145 saa_trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
146 }
147}
148
149/**
150 * saa_triangles is essentially a copy of miTriangles that uses
151 * saa_create_alpha_picture instead of miCreateAlphaPicture.
152 *
153 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
154 * to initialize the contents after creating the pixmap, which
155 * causes the pixmap to be moved in for acceleration. The subsequent
156 * call to AddTriangles won't be accelerated however, which forces the pixmap
157 * to be moved out again.
158 */
159static void
160saa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
161 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
162 int ntri, xTriangle * tris)
163{
164 ScreenPtr pScreen = pDst->pDrawable->pScreen;
165 PictureScreenPtr ps = GetPictureScreen(pScreen);
166 BoxRec bounds;
167
168 if (maskFormat) {
169 PicturePtr pPicture;
170 INT16 xDst, yDst;
171 INT16 xRel, yRel;
172 saa_access_t access;
173
174 miTriangleBounds(ntri, tris, &bounds);
175
176 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
177 return;
178
179 xDst = tris[0].p1.x >> 16;
180 yDst = tris[0].p1.y >> 16;
181
182 pPicture = saa_create_alpha_picture(pScreen, pDst, maskFormat,
183 bounds.x2 - bounds.x1,
184 bounds.y2 - bounds.y1);
185 if (!pPicture)
186 return;
187
188 if (saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access)) {
189 (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris);
190 saa_fad_write(pPicture->pDrawable, access);
191 }
192
193 xRel = bounds.x1 + xSrc - xDst;
194 yRel = bounds.y1 + ySrc - yDst;
195 CompositePicture(op, pSrc, pPicture, pDst,
196 xRel, yRel, 0, 0, bounds.x1, bounds.y1,
197 bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
198 FreePicture(pPicture, 0);
199 } else {
200 if (pDst->polyEdge == PolyEdgeSharp)
201 maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
202 else
203 maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
204
205 for (; ntri; ntri--, tris++)
206 saa_triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris);
207 }
208}
209
210static Bool
211saa_driver_composite(CARD8 op,
212 PicturePtr pSrc,
213 PicturePtr pMask,
214 PicturePtr pDst,
215 INT16 xSrc,
216 INT16 ySrc,
217 INT16 xMask,
218 INT16 yMask,
219 INT16 xDst,
220 INT16 yDst,
221 CARD16 width,
222 CARD16 height,
223 RegionPtr src_reg,
224 RegionPtr mask_reg,
225 RegionPtr dst_reg)
226{
227 struct saa_screen_priv *sscreen = saa_screen(pDst->pDrawable->pScreen);
228 BoxPtr pbox;
229 int nbox;
230 int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
231 PixmapPtr src_pix = NULL, mask_pix = NULL, dst_pix;
232 struct saa_driver *driver = sscreen->driver;
233
234 if (!driver->composite_prepare)
235 return FALSE;
236
237 dst_pix = saa_get_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
238 if (saa_pixmap(dst_pix)->auth_loc != saa_loc_driver)
239 return FALSE;
240
241 if (pMask && pMask->pDrawable) {
242 mask_pix = saa_get_pixmap(pMask->pDrawable, &mask_off_x, &mask_off_y);
243 if (saa_pixmap(mask_pix)->auth_loc != saa_loc_driver)
244 return FALSE;
245 }
246 if (pSrc->pDrawable) {
247 src_pix = saa_get_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
248 if (saa_pixmap(src_pix)->auth_loc != saa_loc_driver)
249 return FALSE;
250 }
251
252 if (!driver->composite_prepare(driver, op, pSrc, pMask, pDst,
253 src_pix, mask_pix, dst_pix,
254 src_reg, mask_reg, dst_reg))
255 return FALSE;
256
257 nbox = REGION_NUM_RECTS(dst_reg);
258 pbox = REGION_RECTS(dst_reg);
259
260 xDst += pDst->pDrawable->x + dst_off_x;
261 yDst += pDst->pDrawable->y + dst_off_y;
262
263 if (src_pix) {
264 xSrc += pSrc->pDrawable->x + src_off_x - xDst;
265 ySrc += pSrc->pDrawable->y + src_off_y - yDst;
266 }
267 if (mask_pix) {
268 xMask += pMask->pDrawable->x + mask_off_x - xDst;
269 yMask += pMask->pDrawable->y + mask_off_y - yDst;
270 }
271
272 while (nbox--) {
273 driver->composite(driver,
274 pbox->x1 + xSrc,
275 pbox->y1 + ySrc,
276 pbox->x1 + xMask,
277 pbox->y1 + yMask,
278 pbox->x1,
279 pbox->y1,
280 pbox->x2 - pbox->x1,
281 pbox->y2 - pbox->y1);
282 pbox++;
283 }
284
285 driver->composite_done(driver);
286 saa_pixmap_dirty(dst_pix, TRUE, dst_reg);
287
288 return TRUE;
289}
290
291/*
292 * Try to turn a composite operation into an accelerated copy.
293 * We can do that in some special cases for PictOpSrc and PictOpOver.
294 */
295
296static Bool
297saa_copy_composite(CARD8 op,
298 PicturePtr pSrc,
299 PicturePtr pMask,
300 PicturePtr pDst,
301 INT16 xSrc,
302 INT16 ySrc,
303 INT16 xMask,
304 INT16 yMask,
305 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height,
306 RegionPtr dst_region)
307{
308 if (!pSrc->pDrawable || pSrc->transform ||
309 pSrc->repeat || xSrc < 0 || ySrc < 0 ||
310 xSrc + width > pSrc->pDrawable->width ||
311 ySrc + height > pSrc->pDrawable->height)
312 return FALSE;
313
314 if (op == PictOpSrc ||
315 (op == PictOpOver && PICT_FORMAT_A(pSrc->format) == 0 &&
316 pMask == NULL)) {
317
318 int xoff, yoff;
319 PixmapPtr dst_pix = saa_get_pixmap(pDst->pDrawable, &xoff, &yoff);
320 struct saa_pixmap *dst_spix = saa_pixmap(dst_pix);
321 struct saa_pixmap *src_spix =
322 saa_pixmap(saa_get_drawable_pixmap(pSrc->pDrawable));
323 int ret;
324
325 if (src_spix->auth_loc != saa_loc_driver ||
326 dst_spix->auth_loc != saa_loc_driver)
327 return FALSE;
328
329 src_spix->src_format = pSrc->format;
330 dst_spix->dst_format = pDst->format;
331
332 xDst += pDst->pDrawable->x;
333 yDst += pDst->pDrawable->y;
334 xSrc += pSrc->pDrawable->x;
335 ySrc += pSrc->pDrawable->y;
336
337 /*
338 * Dst region is in backing pixmap space. We need to
339 * translate it.
340 */
341 REGION_TRANSLATE(pScreen, dst_region, -xoff, -yoff);
342 ret = saa_hw_copy_nton(pSrc->pDrawable, pDst->pDrawable, NULL,
343 REGION_RECTS(dst_region),
344 REGION_NUM_RECTS(dst_region),
345 xSrc - xDst, ySrc - yDst, FALSE, FALSE);
346 REGION_TRANSLATE(pScreen, dst_region, xoff, yoff);
347
348 src_spix->src_format = 0;
349 dst_spix->dst_format = 0;
350
351 if (ret)
352 return TRUE;
353 }
354 return FALSE;
355}
356
357static void
358saa_composite(CARD8 op,
359 PicturePtr pSrc,
360 PicturePtr pMask,
361 PicturePtr pDst,
362 INT16 xSrc,
363 INT16 ySrc,
364 INT16 xMask,
365 INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
366{
367 ScreenPtr pScreen = pDst->pDrawable->pScreen;
368 RegionRec dst_region;
369 RegionPtr src_region;
370 RegionPtr mask_region;
371
372 REGION_NULL(pScreen, &dst_region);
373 if (!saa_compute_composite_regions(pScreen, pSrc, pMask, pDst,
374 xSrc, ySrc, xMask, yMask, xDst,
375 yDst, width, height,
376 &dst_region, &src_region, &mask_region))
377 goto out;
378
379 if (saa_copy_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
380 xDst, yDst, width, height, &dst_region))
381 goto out;
382
383 if (saa_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
384 xDst, yDst, width, height, src_region,
385 mask_region, &dst_region))
386 goto out;
387
388 saa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
389 xDst, yDst, width, height,
390 src_region, mask_region, &dst_region);
391 out:
392 if (src_region)
393 REGION_UNINIT(pScreen, src_region);
394 if (mask_region && mask_region != src_region)
395 REGION_UNINIT(pScreen, mask_region);
396 REGION_UNINIT(pScreen, &dst_region);
397}
398
399void
400saa_render_setup(ScreenPtr pScreen)
401{
402 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
403 struct saa_screen_priv *sscreen = saa_screen(pScreen);
404
405 if (ps) {
406 saa_wrap(sscreen, ps, Trapezoids, saa_trapezoids);
407 saa_wrap(sscreen, ps, Triangles, saa_triangles);
408 saa_wrap(sscreen, ps, Composite, saa_composite);
409 }
410}
411
412void
413saa_render_takedown(ScreenPtr pScreen)
414{
415 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
416 struct saa_screen_priv *sscreen = saa_screen(pScreen);
417
418 if (ps) {
419 saa_unwrap(sscreen, ps, Trapezoids);
420 saa_unwrap(sscreen, ps, Triangles);
421 saa_unwrap(sscreen, ps, Composite);
422 }
423}
424#endif
diff --git a/saa/saa_unaccel.c b/saa/saa_unaccel.c
new file mode 100644
index 0000000..deaf5aa
--- /dev/null
+++ b/saa/saa_unaccel.c
@@ -0,0 +1,935 @@
1/*
2 * Copyright © 1999 Keith Packard
3 * Copyright 2011 VMWare, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Based on "exa_unaccel.c"
26 * Author: Thomas Hellstrom <thellstrom@vmware.com>
27 */
28
29#include "saa_priv.h"
30#include "saa.h"
31#include "mipict.h"
32
33/**
34 * Calls saa_prepare_access with SAA_ACCESS_R for the tile, if that is the
35 * current fill style.
36 *
37 * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are
38 * 1bpp and never in fb, so we don't worry about them.
39 * We should worry about them for completeness sake and going forward.
40 */
41static Bool
42saa_prepare_access_gc(GCPtr pGC)
43{
44 if (pGC->stipple)
45 if (!saa_pad_read(&pGC->stipple->drawable))
46 return FALSE;
47 if (pGC->fillStyle == FillTiled)
48 if (!saa_pad_read(&pGC->tile.pixmap->drawable)) {
49 if (pGC->stipple)
50 saa_fad_read(&pGC->stipple->drawable);
51 return FALSE;
52 }
53 return TRUE;
54}
55
56/**
57 * Finishes access to the tile in the GC, if used.
58 */
59static void
60saa_finish_access_gc(GCPtr pGC)
61{
62 if (pGC->fillStyle == FillTiled)
63 saa_fad_read(&pGC->tile.pixmap->drawable);
64 if (pGC->stipple)
65 saa_fad_read(&pGC->stipple->drawable);
66}
67
68void
69saa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
70 DDXPointPtr ppt, int *pwidth, int fSorted)
71{
72 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
73 struct saa_gc_priv *sgc = saa_gc(pGC);
74 saa_access_t access;
75
76 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_location(pDrawable)));
77
78 sscreen->fallback_count++;
79 if (saa_pad_write(pDrawable, NULL, FALSE, &access)) {
80 if (saa_prepare_access_gc(pGC)) {
81 saa_swap(sgc, pGC, ops);
82 pGC->ops->FillSpans(pDrawable, pGC, nspans, ppt, pwidth, fSorted);
83 saa_swap(sgc, pGC, ops);
84 saa_finish_access_gc(pGC);
85 }
86 saa_fad_write(pDrawable, access);
87 }
88 sscreen->fallback_count--;
89}
90
91static void
92saa_check_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
93 DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
94{
95 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
96 struct saa_gc_priv *sgc = saa_gc(pGC);
97 saa_access_t access
98 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
99
100 sscreen->fallback_count++;
101 if (saa_pad_write(pDrawable, NULL, FALSE, &access)) {
102 saa_swap(sgc, pGC, ops);
103 pGC->ops->SetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
104 saa_swap(sgc, pGC, ops);
105 saa_fad_write(pDrawable, access);
106 }
107 sscreen->fallback_count--;
108}
109
110static void
111saa_check_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
112 int x, int y, int w, int h, int leftPad, int format,
113 char *bits)
114{
115 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
116 struct saa_gc_priv *sgc = saa_gc(pGC);
117 saa_access_t access;
118
119 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
120 sscreen->fallback_count++;
121 if (saa_pad_write(pDrawable, pGC, TRUE, &access)) {
122 saa_swap(sgc, pGC, ops);
123 pGC->ops->PutImage(pDrawable, pGC, depth, x, y, w, h, leftPad,
124 format, bits);
125 saa_swap(sgc, pGC, ops);
126 saa_fad_write(pDrawable, access);
127 }
128 sscreen->fallback_count--;
129}
130
131RegionPtr
132saa_boxes_to_region(ScreenPtr pScreen, int nbox, BoxPtr pbox, int ordering)
133{
134 xRectangle *rects = malloc(nbox * sizeof(*rects));
135 int i;
136 RegionPtr reg;
137
138 if (!rects)
139 return NULL;
140
141 for (i = 0; i < nbox; i++) {
142 rects[i].x = pbox[i].x1;
143 rects[i].y = pbox[i].y1;
144 rects[i].width = pbox[i].x2 - pbox[i].x1;
145 rects[i].height = pbox[i].y2 - pbox[i].y1;
146 }
147
148 reg = RECTS_TO_REGION(pScreen, nbox, rects, ordering);
149 free(rects);
150 return reg;
151}
152
153void
154saa_check_copy_nton(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
155 BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
156 Bool upsidedown, Pixel bitplane, void *closure)
157{
158 ScreenPtr pScreen = pSrc->pScreen;
159 struct saa_screen_priv *sscreen = saa_screen(pScreen);
160 RegionPtr reg, readback;
161 int src_xoff, src_yoff, dst_xoff, dst_yoff;
162 struct saa_gc_priv *sgc = saa_gc(pGC);
163 PixmapPtr src_pixmap;
164 PixmapPtr dst_pixmap;
165 saa_access_t access = SAA_ACCESS_R;
166 int ordering;
167
168 sscreen->fallback_count++;
169 SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
170 saa_drawable_loc(pSrc), saa_drawable_loc(pDst)));
171
172 src_pixmap = saa_get_pixmap(pSrc, &src_xoff, &src_yoff);
173 dst_pixmap = saa_get_pixmap(pDst, &dst_xoff, &dst_yoff);
174
175 ordering = (nbox == 1 || (dx > 0 && dy > 0) ||
176 (pDst != pSrc &&
177 (pDst->type != DRAWABLE_WINDOW ||
178 pSrc->type != DRAWABLE_WINDOW))) ? CT_YXBANDED : CT_UNSORTED;
179
180 reg = saa_boxes_to_region(pScreen, nbox, pbox, ordering);
181 if (!reg)
182 return;
183
184 REGION_TRANSLATE(pScreen, reg, src_xoff + dx, src_yoff + dy);
185 if (!saa_prepare_access_pixmap(src_pixmap, SAA_ACCESS_R, reg))
186 goto out_no_access;
187
188 REGION_TRANSLATE(pScreen, reg, dst_xoff - dx - src_xoff,
189 dst_yoff - dy - src_yoff);
190
191 if (saa_gc_reads_destination(pDst, pGC)) {
192 readback = reg;
193 access = SAA_ACCESS_RW;
194 } else {
195 readback = NULL;
196 access = SAA_ACCESS_W;
197 }
198
199 if (!saa_prepare_access_pixmap(dst_pixmap, access, readback))
200 goto out_no_dst;
201
202 saa_swap(sgc, pGC, ops);
203 while (nbox--) {
204 pGC->ops->CopyArea(pSrc, pDst, pGC, pbox->x1 - pSrc->x + dx,
205 pbox->y1 - pSrc->y + dy,
206 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
207 pbox->x1 - pDst->x, pbox->y1 - pDst->y);
208 pbox++;
209 }
210
211 saa_swap(sgc, pGC, ops);
212 saa_finish_access_pixmap(dst_pixmap, access);
213 saa_pixmap_dirty(dst_pixmap, FALSE, reg);
214 out_no_dst:
215 saa_fad_read(pSrc);
216 out_no_access:
217 sscreen->fallback_count--;
218 REGION_DESTROY(pScreen, reg);
219}
220
221RegionPtr
222saa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
223 int srcx, int srcy, int w, int h, int dstx, int dsty)
224{
225 RegionPtr ret = NULL;
226 struct saa_gc_priv *sgc = saa_gc(pGC);
227 saa_access_t access;
228 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
229
230 SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
231 saa_drawable_loc(pSrc), saa_drawable_loc(pDst)));
232 sscreen->fallback_count++;
233 if (!saa_pad_read_box(pSrc, srcx, srcy, w, h))
234 goto out_no_access;
235 if (!saa_pad_write(pDst, pGC, TRUE, &access))
236 goto out_no_dst;
237
238 saa_swap(sgc, pGC, ops);
239 ret = pGC->ops->CopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
240 saa_swap(sgc, pGC, ops);
241
242 saa_fad_write(pDst, access);
243 out_no_dst:
244 saa_fad_read(pSrc);
245 out_no_access:
246 sscreen->fallback_count--;
247
248 return ret;
249}
250
251static RegionPtr
252saa_check_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
253 int srcx, int srcy, int w, int h, int dstx, int dsty,
254 unsigned long bitplane)
255{
256 RegionPtr ret = NULL;
257 struct saa_gc_priv *sgc = saa_gc(pGC);
258 saa_access_t access;
259 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
260
261 SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
262 saa_drawable_loc(pSrc), saa_drawable_loc(pDst)));
263 sscreen->fallback_count++;
264 if (!saa_pad_read_box(pSrc, srcx, srcy, w, h))
265 goto out_no_src;
266 if (!saa_pad_write(pDst, pGC, TRUE, &access))
267 goto out_no_dst;
268
269 saa_swap(sgc, pGC, ops);
270 ret = pGC->ops->CopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
271 bitplane);
272 saa_swap(sgc, pGC, ops);
273
274 saa_fad_write(pDst, access);
275 out_no_dst:
276 saa_fad_read(pSrc);
277 out_no_src:
278 sscreen->fallback_count--;
279
280 return ret;
281}
282
283static void
284saa_check_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
285 DDXPointPtr pptInit)
286{
287 struct saa_gc_priv *sgc = saa_gc(pGC);
288 saa_access_t access;
289 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
290
291 sscreen->fallback_count++;
292 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
293 if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
294 goto out_no_access;
295 saa_swap(sgc, pGC, ops);
296 pGC->ops->PolyPoint(pDrawable, pGC, mode, npt, pptInit);
297 saa_swap(sgc, pGC, ops);
298 saa_fad_write(pDrawable, access);
299
300 out_no_access:
301 sscreen->fallback_count--;
302}
303
304static void
305saa_check_poly_lines(DrawablePtr pDrawable, GCPtr pGC,
306 int mode, int npt, DDXPointPtr ppt)
307{
308 struct saa_gc_priv *sgc = saa_gc(pGC);
309 saa_access_t access;
310 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
311
312 SAA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
313 pDrawable, saa_drawable_loc(pDrawable),
314 pGC->lineWidth, mode, npt));
315
316 sscreen->fallback_count++;
317 if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
318 goto out_no_access;
319 if (!saa_prepare_access_gc(pGC))
320 goto out_no_gc;
321 saa_swap(sgc, pGC, ops);
322 pGC->ops->Polylines(pDrawable, pGC, mode, npt, ppt);
323 saa_swap(sgc, pGC, ops);
324 saa_finish_access_gc(pGC);
325 out_no_gc:
326 saa_fad_write(pDrawable, access);
327 out_no_access:
328 sscreen->fallback_count--;
329}
330
331static void
332saa_check_poly_segment(DrawablePtr pDrawable, GCPtr pGC,
333 int nsegInit, xSegment * pSegInit)
334{
335 struct saa_gc_priv *sgc = saa_gc(pGC);
336 saa_access_t access;
337 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
338
339 SAA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
340 saa_drawable_loc(pDrawable), pGC->lineWidth, nsegInit));
341
342 sscreen->fallback_count++;
343 if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
344 goto out_no_access;;
345 if (!saa_prepare_access_gc(pGC))
346 goto out_no_gc;
347 saa_swap(sgc, pGC, ops);
348 pGC->ops->PolySegment(pDrawable, pGC, nsegInit, pSegInit);
349 saa_swap(sgc, pGC, ops);
350 saa_finish_access_gc(pGC);
351 out_no_gc:
352 saa_fad_write(pDrawable, access);
353 out_no_access:
354 sscreen->fallback_count--;
355}
356
357static void
358saa_check_poly_arc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs)
359{
360 struct saa_gc_priv *sgc = saa_gc(pGC);
361 saa_access_t access;
362 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
363
364 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
365
366 sscreen->fallback_count++;
367 if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
368 goto out_no_access;;
369 if (!saa_prepare_access_gc(pGC))
370 goto out_no_gc;
371 saa_swap(sgc, pGC, ops);
372 pGC->ops->PolyArc(pDrawable, pGC, narcs, pArcs);
373 saa_swap(sgc, pGC, ops);
374 saa_finish_access_gc(pGC);
375 out_no_gc:
376 saa_fad_write(pDrawable, access);
377 out_no_access:
378 sscreen->fallback_count--;
379}
380
381void
382saa_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC,
383 int nrect, xRectangle * prect)
384{
385 struct saa_gc_priv *sgc = saa_gc(pGC);
386 saa_access_t access;
387 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
388
389 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
390
391 sscreen->fallback_count++;
392
393 /*
394 * TODO: Use @prect for readback / damaging instead of
395 * the damage region. This may fragment the dirty regions more
396 * but should avoid unnecessary readbacks.
397 */
398 if (!saa_pad_write(pDrawable, pGC, FALSE, &access))
399 goto out_no_access;;
400 if (!saa_prepare_access_gc(pGC))
401 goto out_no_gc;
402 saa_swap(sgc, pGC, ops);
403 pGC->ops->PolyFillRect(pDrawable, pGC, nrect, prect);
404 saa_swap(sgc, pGC, ops);
405 saa_finish_access_gc(pGC);
406 out_no_gc:
407 saa_fad_write(pDrawable, access);
408 out_no_access:
409 sscreen->fallback_count--;
410}
411
412static void
413saa_check_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
414 int x, int y, unsigned int nglyph,
415 CharInfoPtr * ppci, pointer pglyphBase)
416{
417 struct saa_gc_priv *sgc = saa_gc(pGC);
418 saa_access_t access;
419 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
420
421 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
422
423 sscreen->fallback_count++;
424 if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
425 goto out_no_access;;
426 if (!saa_prepare_access_gc(pGC))
427 goto out_no_gc;
428 saa_swap(sgc, pGC, ops);
429 pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
430 saa_swap(sgc, pGC, ops);
431 saa_finish_access_gc(pGC);
432 out_no_gc:
433 saa_fad_write(pDrawable, access);
434 out_no_access:
435 sscreen->fallback_count--;
436}
437
438static void
439saa_check_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
440 int x, int y, unsigned int nglyph,
441 CharInfoPtr * ppci, pointer pglyphBase)
442{
443 struct saa_gc_priv *sgc = saa_gc(pGC);
444 saa_access_t access;
445 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
446
447 SAA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
448 saa_drawable_loc(pDrawable), pGC->fillStyle, pGC->alu));
449
450 sscreen->fallback_count++;
451 if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
452 goto out_no_access;;
453 if (!saa_prepare_access_gc(pGC))
454 goto out_no_gc;
455 saa_swap(sgc, pGC, ops);
456 pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
457 saa_swap(sgc, pGC, ops);
458 saa_finish_access_gc(pGC);
459 out_no_gc:
460 saa_fad_write(pDrawable, access);
461 out_no_access:
462 sscreen->fallback_count--;
463}
464
465static void
466saa_check_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
467 DrawablePtr pDrawable, int w, int h, int x, int y)
468{
469 struct saa_gc_priv *sgc = saa_gc(pGC);
470 saa_access_t access;
471 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
472
473 SAA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
474 saa_drawable_loc(&pBitmap->drawable),
475 saa_drawable_loc(pDrawable)));
476
477 sscreen->fallback_count++;
478 if (!saa_pad_write(pDrawable, pGC, TRUE, &access))
479 goto out_no_access;;
480 if (!saa_pad_read_box(&pBitmap->drawable, 0, 0, w, h))
481 goto out_no_src;
482 if (!saa_prepare_access_gc(pGC))
483 goto out_no_gc;
484 saa_swap(sgc, pGC, ops);
485 pGC->ops->PushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
486 saa_swap(sgc, pGC, ops);
487 saa_finish_access_gc(pGC);
488 out_no_gc:
489 saa_fad_read(&pBitmap->drawable);
490 out_no_src:
491 saa_fad_write(pDrawable, access);
492 out_no_access:
493 sscreen->fallback_count--;
494}
495
496static void
497saa_check_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
498{
499 DrawablePtr pDrawable = &pWin->drawable;
500 ScreenPtr pScreen = pDrawable->pScreen;
501 struct saa_screen_priv *sscreen = saa_screen(pScreen);
502 int xoff, yoff;
503 PixmapPtr pPixmap = saa_get_pixmap(&pWin->drawable, &xoff, &yoff);
504 Bool ret;
505
506 SAA_FALLBACK(("from %p\n", pWin));
507
508 /* Only need the source bits, the destination region will be overwritten */
509
510 sscreen->fallback_count++;
511 REGION_TRANSLATE(pScreen, prgnSrc, xoff, yoff);
512 ret = saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_R, prgnSrc);
513 REGION_TRANSLATE(pScreen, prgnSrc, -xoff, -yoff);
514 if (!ret)
515 goto out_no_access;;
516
517 if (saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_W, NULL)) {
518 saa_swap(sscreen, pScreen, CopyWindow);
519 pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc);
520 saa_swap(sscreen, pScreen, CopyWindow);
521 saa_fad_write(pDrawable, SAA_ACCESS_W);
522 }
523 saa_fad_read(pDrawable);
524 out_no_access:
525 sscreen->fallback_count--;
526}
527
528#ifdef RENDER
529
530#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10)
531static void
532saa_src_validate(DrawablePtr pDrawable,
533 int x,
534 int y, int width, int height, unsigned int subWindowMode)
535#else
536static void
537saa_src_validate(DrawablePtr pDrawable, int x, int y, int width, int height)
538#endif
539{
540 ScreenPtr pScreen = pDrawable->pScreen;
541 struct saa_screen_priv *sscreen = saa_screen(pScreen);
542 int xoff, yoff;
543 BoxRec box;
544 RegionRec reg;
545 RegionPtr dst;
546
547 (void) saa_get_pixmap(pDrawable, &xoff, &yoff);
548 box.x1 = x + xoff;
549 box.y1 = y + yoff;
550 box.x2 = box.x1 + width;
551 box.y2 = box.y1 + height;
552
553 dst = (sscreen->srcDraw == pDrawable) ?
554 &sscreen->srcReg : &sscreen->maskReg;
555
556 REGION_INIT(pScreen, &reg, &box, 1);
557 REGION_UNION(pScreen, dst, dst, &reg);
558 REGION_UNINIT(pScreen, &reg);
559
560 if (sscreen->saved_SourceValidate) {
561 saa_swap(sscreen, pScreen, SourceValidate);
562 pScreen->SourceValidate(pDrawable, x, y, width, height
563#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10)
564 , subWindowMode
565#endif
566 );
567 saa_swap(sscreen, pScreen, SourceValidate);
568 }
569}
570
571static void
572saa_check_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
573 unsigned int format, unsigned long planeMask, char *d)
574{
575 ScreenPtr pScreen = pDrawable->pScreen;
576 struct saa_screen_priv *sscreen = saa_screen(pScreen);
577
578 SAA_FALLBACK(("from %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
579
580 sscreen->fallback_count++;
581 if (!saa_pad_read_box(pDrawable, x, y, w, h))
582 goto out_no_access;;
583 saa_swap(sscreen, pScreen, GetImage);
584 pScreen->GetImage(pDrawable, x, y, w, h, format, planeMask, d);
585 saa_swap(sscreen, pScreen, GetImage);
586 saa_fad_read(pDrawable);
587 out_no_access:
588 sscreen->fallback_count--;
589}
590
591static void
592saa_check_get_spans(DrawablePtr pDrawable,
593 int wMax,
594 DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart)
595{
596 ScreenPtr pScreen = pDrawable->pScreen;
597 struct saa_screen_priv *sscreen = saa_screen(pScreen);
598
599 SAA_FALLBACK(("from %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
600
601 sscreen->fallback_count++;
602 if (!saa_pad_read(pDrawable))
603 goto out_no_access;;
604 saa_swap(sscreen, pScreen, GetSpans);
605 pScreen->GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
606 saa_swap(sscreen, pScreen, GetSpans);
607 saa_fad_read(pDrawable);
608 out_no_access:
609 sscreen->fallback_count--;
610}
611
612/*
613 * Compute composite regions taking transforms into account.
614 * The caller must provide a pointer to an initialized dst_reg,
615 * and the function returns pointers to set up source- and mask regions.
616 * The source and mask regions must be uninitialized after use.
617 */
618
619Bool
620saa_compute_composite_regions(ScreenPtr pScreen,
621 PicturePtr pSrc,
622 PicturePtr pMask,
623 PicturePtr pDst,
624 INT16 xSrc, INT16 ySrc, INT16 xMask,
625 INT16 yMask, INT16 xDst,
626 INT16 yDst, INT16 width, INT16 height,
627 RegionPtr dst_reg,
628 RegionPtr *src_reg,
629 RegionPtr *mask_reg)
630{
631 struct saa_screen_priv *sscreen = saa_screen(pScreen);
632 PixmapPtr dst_pixmap;
633 RegionPtr srcReg = NULL;
634 RegionPtr maskReg = NULL;
635 Bool ret;
636 int xoff, yoff;
637
638 *src_reg = NULL;
639 *mask_reg = NULL;
640
641 if (pSrc->pDrawable) {
642 REGION_NULL(pScreen, &sscreen->srcReg);
643 srcReg = &sscreen->srcReg;
644 sscreen->srcDraw = pSrc->pDrawable;
645 if (pSrc != pDst)
646 REGION_TRANSLATE(pScreen, pSrc->pCompositeClip,
647 -pSrc->pDrawable->x, -pSrc->pDrawable->y);
648 }
649
650 if (pMask && pMask->pDrawable) {
651 REGION_NULL(pScreen, &sscreen->maskReg);
652 maskReg = &sscreen->maskReg;
653 if (pMask != pDst && pMask != pSrc)
654 REGION_TRANSLATE(pScreen, pMask->pCompositeClip,
655 -pMask->pDrawable->x, -pMask->pDrawable->y);
656 }
657
658 REGION_TRANSLATE(pScreen, pDst->pCompositeClip,
659 -pDst->pDrawable->x, -pDst->pDrawable->y);
660
661 sscreen->saved_SourceValidate = saa_src_validate;
662 saa_swap(sscreen, pScreen, SourceValidate);
663 ret = miComputeCompositeRegion(dst_reg, pSrc, pMask, pDst,
664 xSrc, ySrc, xMask, yMask,
665 xDst, yDst, width, height);
666 saa_swap(sscreen, pScreen, SourceValidate);
667
668 REGION_TRANSLATE(pScreen, pDst->pCompositeClip,
669 pDst->pDrawable->x, pDst->pDrawable->y);
670 if (pSrc->pDrawable && pSrc != pDst)
671 REGION_TRANSLATE(pScreen, pSrc->pCompositeClip,
672 pSrc->pDrawable->x, pSrc->pDrawable->y);
673 if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc)
674 REGION_TRANSLATE(pScreen, pMask->pCompositeClip,
675 pMask->pDrawable->x, pMask->pDrawable->y);
676
677 if (!ret) {
678 if (srcReg)
679 REGION_UNINIT(pScreen, srcReg);
680 if (maskReg)
681 REGION_UNINIT(pScreen, maskReg);
682
683 return FALSE;
684 }
685
686 *src_reg = srcReg;
687 *mask_reg = maskReg;
688
689 /*
690 * Translate dst region to pixmap space.
691 */
692 dst_pixmap = saa_get_pixmap(pDst->pDrawable, &xoff, &yoff);
693 REGION_TRANSLATE(pScreen, dst_reg, pDst->pDrawable->x + xoff,
694 pDst->pDrawable->y + yoff);
695
696
697 return TRUE;
698}
699
700static Bool
701saa_prepare_composite_reg(ScreenPtr pScreen,
702 CARD8 op,
703 PicturePtr pSrc,
704 PicturePtr pMask,
705 PicturePtr pDst,
706 INT16 xSrc,
707 INT16 ySrc,
708 INT16 xMask,
709 INT16 yMask,
710 INT16 xDst,
711 INT16 yDst,
712 CARD16 width,
713 CARD16 height,
714 RegionPtr src_region,
715 RegionPtr mask_region,
716 RegionPtr dst_region,
717 saa_access_t * access)
718{
719 RegionPtr dstReg = NULL;
720 PixmapPtr pSrcPix = NULL;
721 PixmapPtr pMaskPix = NULL;
722 PixmapPtr pDstPix;
723 struct saa_pixmap *dst_spix;
724
725 *access = SAA_ACCESS_W;
726
727 if (pSrc->pDrawable)
728 pSrcPix = saa_get_drawable_pixmap(pSrc->pDrawable);
729 if (pMask && pMask->pDrawable)
730 pMaskPix = saa_get_drawable_pixmap(pMask->pDrawable);
731
732 /*
733 * Don't limit alphamaps readbacks for now until we've figured out how that
734 * should be done.
735 */
736
737 if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
738 if (!saa_pad_read(pSrc->alphaMap->pDrawable))
739 goto out_no_src_alpha;
740 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
741 if (!saa_pad_read(pMask->alphaMap->pDrawable))
742 goto out_no_mask_alpha;
743 if (pSrcPix)
744 if (!saa_prepare_access_pixmap(pSrcPix, SAA_ACCESS_R, src_region))
745 goto out_no_src;
746 if (pMaskPix)
747 if (!saa_prepare_access_pixmap(pMaskPix, SAA_ACCESS_R, mask_region))
748 goto out_no_mask;
749
750 pDstPix = saa_get_drawable_pixmap(pDst->pDrawable);
751 dst_spix = saa_get_saa_pixmap(pDstPix);
752
753 if (dst_spix->damage && saa_op_reads_destination(op)) {
754 dstReg = dst_region;
755 *access |= SAA_ACCESS_R;
756 }
757
758 if (pDst->alphaMap && pDst->alphaMap->pDrawable)
759 if (!saa_prepare_access_pixmap
760 (saa_get_drawable_pixmap(pDst->alphaMap->pDrawable),
761 *access, dstReg))
762 goto out_no_dst_alpha;
763
764 if (!saa_prepare_access_pixmap(pDstPix, *access, dstReg))
765 goto out_no_dst;
766
767 return TRUE;
768
769 out_no_dst:
770 LogMessage(X_ERROR, "No dst\n");
771 saa_finish_access_pixmap
772 (saa_get_drawable_pixmap(pDst->alphaMap->pDrawable), *access);
773 out_no_dst_alpha:
774 LogMessage(X_ERROR, "No dst alpha\n");
775 if (pMaskPix)
776 saa_finish_access_pixmap(pMaskPix, SAA_ACCESS_R);
777 out_no_mask:
778 LogMessage(X_ERROR, "No mask\n");
779 if (pSrcPix)
780 saa_finish_access_pixmap(pSrcPix, SAA_ACCESS_R);
781 out_no_src:
782 LogMessage(X_ERROR, "No src\n");
783 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
784 saa_fad_read(pMask->alphaMap->pDrawable);
785 out_no_mask_alpha:
786 LogMessage(X_ERROR, "No mask alpha\n");
787 if (pSrc && pSrc->alphaMap && pSrc->alphaMap->pDrawable)
788 saa_fad_read(pSrc->alphaMap->pDrawable);
789 out_no_src_alpha:
790 LogMessage(X_ERROR, "No src alpha\n");
791 return FALSE;
792
793}
794
795void
796saa_check_composite(CARD8 op,
797 PicturePtr pSrc,
798 PicturePtr pMask,
799 PicturePtr pDst,
800 INT16 xSrc,
801 INT16 ySrc,
802 INT16 xMask,
803 INT16 yMask,
804 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height,
805 RegionPtr src_region,
806 RegionPtr mask_region,
807 RegionPtr dst_region)
808{
809 ScreenPtr pScreen = pDst->pDrawable->pScreen;
810 PictureScreenPtr ps = GetPictureScreen(pScreen);
811 struct saa_screen_priv *sscreen = saa_screen(pScreen);
812 saa_access_t access;
813 PixmapPtr pixmap;
814
815 sscreen->fallback_count++;
816 if (!saa_prepare_composite_reg(pScreen, op, pSrc, pMask, pDst, xSrc,
817 ySrc, xMask, yMask, xDst, yDst, width,
818 height,
819 src_region,
820 mask_region,
821 dst_region,
822 &access)) {
823 goto out_no_access;;
824 }
825
826 saa_swap(sscreen, ps, Composite);
827 ps->Composite(op,
828 pSrc,
829 pMask,
830 pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
831 saa_swap(sscreen, ps, Composite);
832 if (pMask && pMask->pDrawable != NULL)
833 saa_fad_read(pMask->pDrawable);
834 if (pSrc->pDrawable != NULL)
835 saa_fad_read(pSrc->pDrawable);
836 pixmap = saa_get_drawable_pixmap(pDst->pDrawable);
837 saa_finish_access_pixmap(pixmap, access);
838 saa_pixmap_dirty(pixmap, FALSE, dst_region);
839 if (pDst->alphaMap && pDst->alphaMap->pDrawable) {
840 pixmap = saa_get_drawable_pixmap(pDst->alphaMap->pDrawable);
841 saa_finish_access_pixmap(pixmap, access);
842 saa_pixmap_dirty(pixmap, FALSE, dst_region);
843 }
844 if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
845 saa_fad_read(pSrc->alphaMap->pDrawable);
846 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
847 saa_fad_read(pMask->alphaMap->pDrawable);
848 out_no_access:
849 sscreen->fallback_count--;
850}
851
852static void
853saa_check_add_traps(PicturePtr pPicture,
854 INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
855{
856 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
857 PictureScreenPtr ps = GetPictureScreen(pScreen);
858 struct saa_screen_priv *sscreen = saa_screen(pScreen);
859 saa_access_t access;
860
861 SAA_FALLBACK(("to pict %p (%c)\n", saa_drawable_loc(pPicture->pDrawable)));
862
863 sscreen->fallback_count++;
864 if (!saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access))
865 goto out_no_access;
866 saa_swap(sscreen, ps, AddTraps);
867 ps->AddTraps(pPicture, x_off, y_off, ntrap, traps);
868 saa_swap(sscreen, ps, AddTraps);
869 saa_fad_write(pPicture->pDrawable, access);
870 out_no_access:
871 sscreen->fallback_count--;
872}
873
874#endif
875
876void
877saa_unaccel_setup(ScreenPtr pScreen)
878{
879#ifdef RENDER
880 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
881#endif
882 struct saa_screen_priv *sscreen = saa_screen(pScreen);
883
884 saa_wrap(sscreen, pScreen, GetImage, saa_check_get_image);
885 saa_wrap(sscreen, pScreen, GetSpans, saa_check_get_spans);
886 saa_wrap(sscreen, pScreen, CopyWindow, saa_check_copy_window);
887
888#ifdef RENDER
889 if (ps) {
890 saa_wrap(sscreen, ps, AddTraps, saa_check_add_traps);
891 }
892#endif
893}
894
895void
896saa_unaccel_takedown(ScreenPtr pScreen)
897{
898#ifdef RENDER
899 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
900#endif
901 struct saa_screen_priv *sscreen = saa_screen(pScreen);
902
903 saa_unwrap(sscreen, pScreen, GetImage);
904 saa_unwrap(sscreen, pScreen, GetSpans);
905 saa_unwrap(sscreen, pScreen, CopyWindow);
906
907#ifdef RENDER
908 if (ps) {
909 saa_unwrap(sscreen, ps, AddTraps);
910 }
911#endif
912}
913
914GCOps saa_gc_ops = {
915 saa_check_fill_spans,
916 saa_check_set_spans,
917 saa_check_put_image,
918 saa_copy_area,
919 saa_check_copy_plane,
920 saa_check_poly_point,
921 saa_check_poly_lines,
922 saa_check_poly_segment,
923 miPolyRectangle,
924 saa_check_poly_arc,
925 miFillPolygon,
926 saa_check_poly_fill_rect,
927 miPolyFillArc,
928 miPolyText8,
929 miPolyText16,
930 miImageText8,
931 miImageText16,
932 saa_check_image_glyph_blt,
933 saa_check_poly_glyph_blt,
934 saa_check_push_pixels,
935};
diff --git a/src/Makefile.am b/src/Makefile.am
index 7c972cf..64a9069 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,12 +24,14 @@
24# _ladir passes a dummy rpath to libtool so the thing will actually link 24# _ladir passes a dummy rpath to libtool so the thing will actually link
25# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. 25# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
26 26
27vmwlegacy_drv_la_LTLIBRARIES = vmwlegacy_drv.la 27vmware_drv_la_LTLIBRARIES = vmware_drv.la
28vmwlegacy_drv_la_LDFLAGS = -module -avoid-version 28vmware_drv_la_LDFLAGS = -module -avoid-version
29vmwlegacy_drv_la_CFLAGS = @XORG_CFLAGS@ 29vmware_drv_la_CFLAGS = @XORG_CFLAGS@
30vmwlegacy_drv_ladir = @moduledir@/drivers 30vmware_drv_ladir = @moduledir@/drivers
31vmware_drv_la_LIBADD = @VMWGFX_LIBADD@
32vmware_drv_la_DEPENDENCIES = @VMWGFX_LIBADD@
31 33
32vmwlegacy_drv_la_SOURCES = \ 34vmware_drv_la_SOURCES = \
33 bits2pixels.c \ 35 bits2pixels.c \
34 bits2pixels.h \ 36 bits2pixels.h \
35 guest_os.h \ 37 guest_os.h \
@@ -50,13 +52,8 @@ vmwlegacy_drv_la_SOURCES = \
50 vmwarectrlproto.h \ 52 vmwarectrlproto.h \
51 vmwarexinerama.c \ 53 vmwarexinerama.c \
52 vmwarevideo.c \ 54 vmwarevideo.c \
53 vmwaremodes.c 55 vmwaremodes.c \
54 56 vmware_bootstrap.h \
55vmware_drv_la_LTLIBRARIES = vmware_drv.la 57 vmware_bootstrap.c \
56vmware_drv_la_LDFLAGS = -module -avoid-version 58 vmware_common.c \
57vmware_drv_la_CFLAGS = @XORG_CFLAGS@ @LIBDRM_CFLAGS@ 59 vmware_common.h
58vmware_drv_la_LIBADD = @LIBDRM_LIBS@
59vmware_drv_ladir = @moduledir@/drivers
60
61vmware_drv_la_SOURCES = \
62 vmwaremodule.c
diff --git a/src/svga_reg.h b/src/svga_reg.h
index 4fa363a..6757aa6 100644
--- a/src/svga_reg.h
+++ b/src/svga_reg.h
@@ -1,52 +1,81 @@
1/* ********************************************************** 1/**********************************************************
2 * Copyright 1998 VMware, Inc. All rights reserved. 2 * Copyright 1998-2009 VMware, Inc. All rights reserved.
3 * **********************************************************/ 3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
4 25
5/* 26/*
6 * svga_reg.h -- 27 * svga_reg.h --
7 * 28 *
8 * SVGA hardware definitions 29 * Virtual hardware definitions for the VMware SVGA II device.
9 */ 30 */
10 31
11#ifndef _SVGA_REG_H_ 32#ifndef _SVGA_REG_H_
12#define _SVGA_REG_H_ 33#define _SVGA_REG_H_
13 34
14#define INCLUDE_ALLOW_USERLEVEL 35/*
15#define INCLUDE_ALLOW_VMMEXT 36 * PCI device IDs.
16#define INCLUDE_ALLOW_VMCORE 37 */
17#include "includeCheck.h" 38#define PCI_VENDOR_ID_VMWARE 0x15AD
39#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405
18 40
19/* 41/*
20 * Memory and port addresses and fundamental constants 42 * SVGA_REG_ENABLE bit definitions.
21 */ 43 */
44#define SVGA_REG_ENABLE_DISABLE 0
45#define SVGA_REG_ENABLE_ENABLE 1
46#define SVGA_REG_ENABLE_HIDE 2
47#define SVGA_REG_ENABLE_ENABLE_HIDE (SVGA_REG_ENABLE_ENABLE |\
48 SVGA_REG_ENABLE_HIDE)
22 49
23/* 50/*
24 * Note-- MAX_WIDTH and MAX_HEIGHT are largely ignored by the code. This 51 * Legal values for the SVGA_REG_CURSOR_ON register in old-fashioned
25 * isn't such a bad thing for forward compatibility. --Jeremy. 52 * cursor bypass mode. This is still supported, but no new guest
53 * drivers should use it.
26 */ 54 */
27#define SVGA_MAX_WIDTH 2360 55#define SVGA_CURSOR_ON_HIDE 0x0 /* Must be 0 to maintain backward compatibility */
28#define SVGA_MAX_HEIGHT 1770 56#define SVGA_CURSOR_ON_SHOW 0x1 /* Must be 1 to maintain backward compatibility */
29#define SVGA_MAX_BITS_PER_PIXEL 32 57#define SVGA_CURSOR_ON_REMOVE_FROM_FB 0x2 /* Remove the cursor from the framebuffer because we need to see what's under it */
30#define SVGA_MAX_DEPTH 24 58#define SVGA_CURSOR_ON_RESTORE_TO_FB 0x3 /* Put the cursor back in the framebuffer so the user can see it */
31#define SVGA_MAX_DISPLAYS 10
32 59
33/* 60/*
34 * The maximum size of the onscreen framebuffer. The size of the 61 * The maximum framebuffer size that can traced for e.g. guests in VESA mode.
35 * changeMap in the monitor is proportional to this number since it's 62 * The changeMap in the monitor is proportional to this number. Therefore, we'd
36 * the amount of memory we need to trace in VESA mode. Therefore, we'd
37 * like to keep it as small as possible to reduce monitor overhead (using 63 * like to keep it as small as possible to reduce monitor overhead (using
38 * SVGA_VRAM_MAX_SIZE for this increases the size of the shared area 64 * SVGA_VRAM_MAX_SIZE for this increases the size of the shared area by over
39 * by over 4k!). 65 * 4k!).
66 *
67 * NB: For compatibility reasons, this value must be greater than 0xff0000.
68 * See bug 335072.
40 */ 69 */
41 70#define SVGA_FB_MAX_TRACEABLE_SIZE 0x1000000
42#define SVGA_FB_MAX_SIZE \
43 ((((SVGA_MAX_WIDTH * SVGA_MAX_HEIGHT * \
44 SVGA_MAX_BITS_PER_PIXEL / 8) >> PAGE_SHIFT) + 1) << PAGE_SHIFT)
45 71
46#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8 72#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8
47#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH) 73#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH)
48#define SVGA_NUM_PALETTE_REGS (3 * SVGA_MAX_PSEUDOCOLORS) 74#define SVGA_NUM_PALETTE_REGS (3 * SVGA_MAX_PSEUDOCOLORS)
49 75
76/* Base and Offset gets us headed the right way for PCI Base Addr Registers */
77#define SVGA_LEGACY_BASE_PORT 0x4560
78
50#define SVGA_MAGIC 0x900000UL 79#define SVGA_MAGIC 0x900000UL
51#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver)) 80#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver))
52 81
@@ -63,19 +92,14 @@
63#define SVGA_VERSION_0 0 92#define SVGA_VERSION_0 0
64#define SVGA_ID_0 SVGA_MAKE_ID(SVGA_VERSION_0) 93#define SVGA_ID_0 SVGA_MAKE_ID(SVGA_VERSION_0)
65 94
66/* Invalid SVGA_ID_ */ 95/* "Invalid" value for all SVGA IDs. (Version ID, screen object ID, surface ID...) */
67#define SVGA_ID_INVALID 0xFFFFFFFF 96#define SVGA_ID_INVALID 0xFFFFFFFF
68 97
69/* More backwards compatibility, old location of color map: */ 98/* Port offsets, relative to BAR0 */
70#define SVGA_OLD_PALETTE_BASE 17 99#define SVGA_INDEX_PORT 0x0
71 100#define SVGA_VALUE_PORT 0x1
72/* Base and Offset gets us headed the right way for PCI Base Addr Registers */ 101#define SVGA_BIOS_PORT 0x2
73#define SVGA_LEGACY_BASE_PORT 0x4560 102#define SVGA_IRQSTATUS_PORT 0x8
74#define SVGA_INDEX_PORT 0x0
75#define SVGA_VALUE_PORT 0x1
76#define SVGA_BIOS_PORT 0x2
77#define SVGA_NUM_PORTS 0x3
78#define SVGA_IRQSTATUS_PORT 0x8
79 103
80/* 104/*
81 * Interrupt source flags for IRQSTATUS_PORT and IRQMASK. 105 * Interrupt source flags for IRQSTATUS_PORT and IRQMASK.
@@ -87,15 +111,6 @@
87#define SVGA_IRQFLAG_FIFO_PROGRESS 0x2 /* Made forward progress in the FIFO */ 111#define SVGA_IRQFLAG_FIFO_PROGRESS 0x2 /* Made forward progress in the FIFO */
88#define SVGA_IRQFLAG_FENCE_GOAL 0x4 /* SVGA_FIFO_FENCE_GOAL reached */ 112#define SVGA_IRQFLAG_FENCE_GOAL 0x4 /* SVGA_FIFO_FENCE_GOAL reached */
89 113
90/* This port is deprecated, but retained because of old drivers. */
91#define SVGA_LEGACY_ACCEL_PORT 0x3
92
93/* Legal values for the SVGA_REG_CURSOR_ON register in cursor bypass mode */
94#define SVGA_CURSOR_ON_HIDE 0x0 /* Must be 0 to maintain backward compatibility */
95#define SVGA_CURSOR_ON_SHOW 0x1 /* Must be 1 to maintain backward compatibility */
96#define SVGA_CURSOR_ON_REMOVE_FROM_FB 0x2 /* Remove the cursor from the framebuffer because we need to see what's under it */
97#define SVGA_CURSOR_ON_RESTORE_TO_FB 0x3 /* Put the cursor back in the framebuffer so the user can see it */
98
99/* 114/*
100 * Registers 115 * Registers
101 */ 116 */
@@ -108,13 +123,13 @@ enum {
108 SVGA_REG_MAX_WIDTH = 4, 123 SVGA_REG_MAX_WIDTH = 4,
109 SVGA_REG_MAX_HEIGHT = 5, 124 SVGA_REG_MAX_HEIGHT = 5,
110 SVGA_REG_DEPTH = 6, 125 SVGA_REG_DEPTH = 6,
111 SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */ 126 SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */
112 SVGA_REG_PSEUDOCOLOR = 8, 127 SVGA_REG_PSEUDOCOLOR = 8,
113 SVGA_REG_RED_MASK = 9, 128 SVGA_REG_RED_MASK = 9,
114 SVGA_REG_GREEN_MASK = 10, 129 SVGA_REG_GREEN_MASK = 10,
115 SVGA_REG_BLUE_MASK = 11, 130 SVGA_REG_BLUE_MASK = 11,
116 SVGA_REG_BYTES_PER_LINE = 12, 131 SVGA_REG_BYTES_PER_LINE = 12,
117 SVGA_REG_FB_START = 13, 132 SVGA_REG_FB_START = 13, /* (Deprecated) */
118 SVGA_REG_FB_OFFSET = 14, 133 SVGA_REG_FB_OFFSET = 14,
119 SVGA_REG_VRAM_SIZE = 15, 134 SVGA_REG_VRAM_SIZE = 15,
120 SVGA_REG_FB_SIZE = 16, 135 SVGA_REG_FB_SIZE = 16,
@@ -122,33 +137,46 @@ enum {
122 /* ID 0 implementation only had the above registers, then the palette */ 137 /* ID 0 implementation only had the above registers, then the palette */
123 138
124 SVGA_REG_CAPABILITIES = 17, 139 SVGA_REG_CAPABILITIES = 17,
125 SVGA_REG_MEM_START = 18, /* Memory for command FIFO and bitmaps */ 140 SVGA_REG_MEM_START = 18, /* (Deprecated) */
126 SVGA_REG_MEM_SIZE = 19, 141 SVGA_REG_MEM_SIZE = 19,
127 SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */ 142 SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */
128 SVGA_REG_SYNC = 21, /* See "FIFO Synchronization Registers" */ 143 SVGA_REG_SYNC = 21, /* See "FIFO Synchronization Registers" */
129 SVGA_REG_BUSY = 22, /* See "FIFO Synchronization Registers" */ 144 SVGA_REG_BUSY = 22, /* See "FIFO Synchronization Registers" */
130 SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */ 145 SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */
131 SVGA_REG_CURSOR_ID = 24, /* ID of cursor */ 146 SVGA_REG_CURSOR_ID = 24, /* (Deprecated) */
132 SVGA_REG_CURSOR_X = 25, /* Set cursor X position */ 147 SVGA_REG_CURSOR_X = 25, /* (Deprecated) */
133 SVGA_REG_CURSOR_Y = 26, /* Set cursor Y position */ 148 SVGA_REG_CURSOR_Y = 26, /* (Deprecated) */
134 SVGA_REG_CURSOR_ON = 27, /* Turn cursor on/off */ 149 SVGA_REG_CURSOR_ON = 27, /* (Deprecated) */
135 SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* Current bpp in the host */ 150 SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* (Deprecated) */
136 SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */ 151 SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */
137 SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */ 152 SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */
138 SVGA_REG_NUM_DISPLAYS = 31, /* Number of guest displays */ 153 SVGA_REG_NUM_DISPLAYS = 31, /* (Deprecated) */
139 SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */ 154 SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */
140 SVGA_REG_IRQMASK = 33, /* Interrupt mask */ 155 SVGA_REG_IRQMASK = 33, /* Interrupt mask */
156
157 /* Legacy multi-monitor support */
141 SVGA_REG_NUM_GUEST_DISPLAYS = 34,/* Number of guest displays in X/Y direction */ 158 SVGA_REG_NUM_GUEST_DISPLAYS = 34,/* Number of guest displays in X/Y direction */
142 SVGA_REG_DISPLAY_ID = 35, /* The display ID for the following display attributes */ 159 SVGA_REG_DISPLAY_ID = 35, /* Display ID for the following display attributes */
143 SVGA_REG_DISPLAY_IS_PRIMARY = 36,/* Whether this is a primary display */ 160 SVGA_REG_DISPLAY_IS_PRIMARY = 36,/* Whether this is a primary display */
144 SVGA_REG_DISPLAY_POSITION_X = 37,/* The display position x */ 161 SVGA_REG_DISPLAY_POSITION_X = 37,/* The display position x */
145 SVGA_REG_DISPLAY_POSITION_Y = 38,/* The display position y */ 162 SVGA_REG_DISPLAY_POSITION_Y = 38,/* The display position y */
146 SVGA_REG_DISPLAY_WIDTH = 39, /* The display's width */ 163 SVGA_REG_DISPLAY_WIDTH = 39, /* The display's width */
147 SVGA_REG_DISPLAY_HEIGHT = 40, /* The display's height */ 164 SVGA_REG_DISPLAY_HEIGHT = 40, /* The display's height */
148 SVGA_REG_TOP = 41, /* Must be 1 more than the last register */
149 165
150 SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ 166 /* See "Guest memory regions" below. */
167 SVGA_REG_GMR_ID = 41,
168 SVGA_REG_GMR_DESCRIPTOR = 42,
169 SVGA_REG_GMR_MAX_IDS = 43,
170 SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44,
171
172 SVGA_REG_TRACES = 45, /* Enable trace-based updates even when FIFO is on */
173 SVGA_REG_GMRS_MAX_PAGES = 46, /* Maximum number of 4KB pages for all GMRs */
174 SVGA_REG_MEMORY_SIZE = 47, /* Total dedicated device memory excluding FIFO */
175 SVGA_REG_TOP = 48, /* Must be 1 more than the last register */
176
177 SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */
151 /* Next 768 (== 256*3) registers exist for colormap */ 178 /* Next 768 (== 256*3) registers exist for colormap */
179
152 SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + SVGA_NUM_PALETTE_REGS 180 SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + SVGA_NUM_PALETTE_REGS
153 /* Base of scratch registers */ 181 /* Base of scratch registers */
154 /* Next reg[SVGA_REG_SCRATCH_SIZE] registers exist for scratch usage: 182 /* Next reg[SVGA_REG_SCRATCH_SIZE] registers exist for scratch usage:
@@ -156,126 +184,264 @@ enum {
156 the use of the current SVGA driver. */ 184 the use of the current SVGA driver. */
157}; 185};
158 186
187/*
188 * Macros to compute variable length items (sizes in 32-bit words, except
189 * for SVGA_GLYPH_SCANLINE_SIZE, which is in bytes).
190 */
191#define SVGA_BITMAP_SIZE(w,h) ((((w)+31) >> 5) * (h))
192#define SVGA_PIXMAP_SIZE(w,h,bpp) ((( ((w)*(bpp))+31 ) >> 5) * (h))
193#define SVGA_BITMAP_INCREMENT(w) ((( (w)+31 ) >> 5) * sizeof (uint32))
194#define SVGA_PIXMAP_INCREMENT(w,bpp) ((( ((w)*(bpp))+31 ) >> 5) * sizeof (uint32))
159 195
160/* 196/*
161 * Capabilities 197 * Guest memory regions (GMRs):
198 *
199 * This is a new memory mapping feature available in SVGA devices
200 * which have the SVGA_CAP_GMR bit set. Previously, there were two
201 * fixed memory regions available with which to share data between the
202 * device and the driver: the FIFO ('MEM') and the framebuffer. GMRs
203 * are our name for an extensible way of providing arbitrary DMA
204 * buffers for use between the driver and the SVGA device. They are a
205 * new alternative to framebuffer memory, usable for both 2D and 3D
206 * graphics operations.
207 *
208 * Since GMR mapping must be done synchronously with guest CPU
209 * execution, we use a new pair of SVGA registers:
210 *
211 * SVGA_REG_GMR_ID --
212 *
213 * Read/write.
214 * This register holds the 32-bit ID (a small positive integer)
215 * of a GMR to create, delete, or redefine. Writing this register
216 * has no side-effects.
217 *
218 * SVGA_REG_GMR_DESCRIPTOR --
219 *
220 * Write-only.
221 * Writing this register will create, delete, or redefine the GMR
222 * specified by the above ID register. If this register is zero,
223 * the GMR is deleted. Any pointers into this GMR (including those
224 * currently being processed by FIFO commands) will be
225 * synchronously invalidated.
226 *
227 * If this register is nonzero, it must be the physical page
228 * number (PPN) of a data structure which describes the physical
229 * layout of the memory region this GMR should describe. The
230 * descriptor structure will be read synchronously by the SVGA
231 * device when this register is written. The descriptor need not
232 * remain allocated for the lifetime of the GMR.
233 *
234 * The guest driver should write SVGA_REG_GMR_ID first, then
235 * SVGA_REG_GMR_DESCRIPTOR.
236 *
237 * SVGA_REG_GMR_MAX_IDS --
238 *
239 * Read-only.
240 * The SVGA device may choose to support a maximum number of
241 * user-defined GMR IDs. This register holds the number of supported
242 * IDs. (The maximum supported ID plus 1)
243 *
244 * SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH --
245 *
246 * Read-only.
247 * The SVGA device may choose to put a limit on the total number
248 * of SVGAGuestMemDescriptor structures it will read when defining
249 * a single GMR.
250 *
251 * The descriptor structure is an array of SVGAGuestMemDescriptor
252 * structures. Each structure may do one of three things:
253 *
254 * - Terminate the GMR descriptor list.
255 * (ppn==0, numPages==0)
256 *
257 * - Add a PPN or range of PPNs to the GMR's virtual address space.
258 * (ppn != 0, numPages != 0)
259 *
260 * - Provide the PPN of the next SVGAGuestMemDescriptor, in order to
261 * support multi-page GMR descriptor tables without forcing the
262 * driver to allocate physically contiguous memory.
263 * (ppn != 0, numPages == 0)
264 *
265 * Note that each physical page of SVGAGuestMemDescriptor structures
266 * can describe at least 2MB of guest memory. If the driver needs to
267 * use more than one page of descriptor structures, it must use one of
268 * its SVGAGuestMemDescriptors to point to an additional page. The
269 * device will never automatically cross a page boundary.
270 *
271 * Once the driver has described a GMR, it is immediately available
272 * for use via any FIFO command that uses an SVGAGuestPtr structure.
273 * These pointers include a GMR identifier plus an offset into that
274 * GMR.
275 *
276 * The driver must check the SVGA_CAP_GMR bit before using the GMR
277 * registers.
162 */ 278 */
163 279
164#define SVGA_CAP_NONE 0x00000000 280/*
165#define SVGA_CAP_RECT_FILL 0x00000001 281 * Special GMR IDs, allowing SVGAGuestPtrs to point to framebuffer
166#define SVGA_CAP_RECT_COPY 0x00000002 282 * memory as well. In the future, these IDs could even be used to
167#define SVGA_CAP_RECT_PAT_FILL 0x00000004 283 * allow legacy memory regions to be redefined by the guest as GMRs.
168#define SVGA_CAP_LEGACY_OFFSCREEN 0x00000008 284 *
169#define SVGA_CAP_RASTER_OP 0x00000010 285 * Using the guest framebuffer (GFB) at BAR1 for general purpose DMA
170#define SVGA_CAP_CURSOR 0x00000020 286 * is being phased out. Please try to use user-defined GMRs whenever
171#define SVGA_CAP_CURSOR_BYPASS 0x00000040 287 * possible.
172#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 288 */
173#define SVGA_CAP_8BIT_EMULATION 0x00000100 289#define SVGA_GMR_NULL ((uint32) -1)
174#define SVGA_CAP_ALPHA_CURSOR 0x00000200 290#define SVGA_GMR_FRAMEBUFFER ((uint32) -2) /* Guest Framebuffer (GFB) */
175#define SVGA_CAP_GLYPH 0x00000400 291
176#define SVGA_CAP_GLYPH_CLIPPING 0x00000800 292typedef
177#define SVGA_CAP_OFFSCREEN_1 0x00001000 293struct SVGAGuestMemDescriptor {
178#define SVGA_CAP_ALPHA_BLEND 0x00002000 294 uint32 ppn;
179#define SVGA_CAP_3D 0x00004000 295 uint32 numPages;
180#define SVGA_CAP_EXTENDED_FIFO 0x00008000 296} SVGAGuestMemDescriptor;
181#define SVGA_CAP_MULTIMON 0x00010000 297
182#define SVGA_CAP_PITCHLOCK 0x00020000 298typedef
183#define SVGA_CAP_IRQMASK 0x00040000 299struct SVGAGuestPtr {
184#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 300 uint32 gmrId;
301 uint32 offset;
302} SVGAGuestPtr;
185 303
186 304
187/* 305/*
188 * Raster op codes (same encoding as X) used by FIFO drivers. 306 * SVGAGMRImageFormat --
307 *
308 * This is a packed representation of the source 2D image format
309 * for a GMR-to-screen blit. Currently it is defined as an encoding
310 * of the screen's color depth and bits-per-pixel, however, 16 bits
311 * are reserved for future use to identify other encodings (such as
312 * RGBA or higher-precision images).
313 *
314 * Currently supported formats:
315 *
316 * bpp depth Format Name
317 * --- ----- -----------
318 * 32 24 32-bit BGRX
319 * 24 24 24-bit BGR
320 * 16 16 RGB 5-6-5
321 * 16 15 RGB 5-5-5
322 *
189 */ 323 */
190 324
191#define SVGA_ROP_CLEAR 0x00 /* 0 */ 325typedef
192#define SVGA_ROP_AND 0x01 /* src AND dst */ 326struct SVGAGMRImageFormat {
193#define SVGA_ROP_AND_REVERSE 0x02 /* src AND NOT dst */ 327 union {
194#define SVGA_ROP_COPY 0x03 /* src */ 328 struct {
195#define SVGA_ROP_AND_INVERTED 0x04 /* NOT src AND dst */ 329 uint32 bitsPerPixel : 8;
196#define SVGA_ROP_NOOP 0x05 /* dst */ 330 uint32 colorDepth : 8;
197#define SVGA_ROP_XOR 0x06 /* src XOR dst */ 331 uint32 reserved : 16; /* Must be zero */
198#define SVGA_ROP_OR 0x07 /* src OR dst */ 332 };
199#define SVGA_ROP_NOR 0x08 /* NOT src AND NOT dst */
200#define SVGA_ROP_EQUIV 0x09 /* NOT src XOR dst */
201#define SVGA_ROP_INVERT 0x0a /* NOT dst */
202#define SVGA_ROP_OR_REVERSE 0x0b /* src OR NOT dst */
203#define SVGA_ROP_COPY_INVERTED 0x0c /* NOT src */
204#define SVGA_ROP_OR_INVERTED 0x0d /* NOT src OR dst */
205#define SVGA_ROP_NAND 0x0e /* NOT src OR NOT dst */
206#define SVGA_ROP_SET 0x0f /* 1 */
207#define SVGA_ROP_UNSUPPORTED 0x10
208 333
209#define SVGA_NUM_SUPPORTED_ROPS 16 334 uint32 value;
210#define SVGA_ROP_ALL (MASK(SVGA_NUM_SUPPORTED_ROPS)) 335 };
211#define SVGA_IS_VALID_ROP(rop) (rop < SVGA_NUM_SUPPORTED_ROPS) 336} SVGAGMRImageFormat;
212 337
213#define SVGA_INVALID_DISPLAY_ID ((uint32)-1) 338typedef
339struct SVGAGuestImage {
340 SVGAGuestPtr ptr;
341
342 /*
343 * A note on interpretation of pitch: This value of pitch is the
344 * number of bytes between vertically adjacent image
345 * blocks. Normally this is the number of bytes between the first
346 * pixel of two adjacent scanlines. With compressed textures,
347 * however, this may represent the number of bytes between
348 * compression blocks rather than between rows of pixels.
349 *
350 * XXX: Compressed textures currently must be tightly packed in guest memory.
351 *
352 * If the image is 1-dimensional, pitch is ignored.
353 *
354 * If 'pitch' is zero, the SVGA3D device calculates a pitch value
355 * assuming each row of blocks is tightly packed.
356 */
357 uint32 pitch;
358} SVGAGuestImage;
214 359
215/* 360/*
216 * Ops 361 * SVGAColorBGRX --
217 * For each pixel, the four channels of the image are computed with: 362 *
218 * 363 * A 24-bit color format (BGRX), which does not depend on the
219 * C = Ca * Fa + Cb * Fb 364 * format of the legacy guest framebuffer (GFB) or the current
220 * 365 * GMRFB state.
221 * where C, Ca, Cb are the values of the respective channels and Fa 366 */
222 * and Fb come from the following table: 367
223 * 368typedef
224 * BlendOp Fa Fb 369struct SVGAColorBGRX {
225 * ------------------------------------------ 370 union {
226 * Clear 0 0 371 struct {
227 * Src 1 0 372 uint32 b : 8;
228 * Dst 0 1 373 uint32 g : 8;
229 * Over 1 1-Aa 374 uint32 r : 8;
230 * OverReverse 1-Ab 1 375 uint32 x : 8; /* Unused */
231 * In Ab 0 376 };
232 * InReverse 0 Aa 377
233 * Out 1-Ab 0 378 uint32 value;
234 * OutReverse 0 1-Aa 379 };
235 * Atop Ab 1-Aa 380} SVGAColorBGRX;
236 * AtopReverse 1-Ab Aa 381
237 * Xor 1-Ab 1-Aa 382
238 * Add 1 1 383/*
239 * Saturate min(1,(1-Ab)/Aa) 1 384 * SVGASignedRect --
240 * 385 * SVGASignedPoint --
241 * Flags 386 *
242 * You can use the following flags to achieve additional affects: 387 * Signed rectangle and point primitives. These are used by the new
243 * 388 * 2D primitives for drawing to Screen Objects, which can occupy a
244 * Flag Effect 389 * signed virtual coordinate space.
245 * ------------------------------------------ 390 *
246 * ConstantSourceAlpha Ca = Ca * Param0 391 * SVGASignedRect specifies a half-open interval: the (left, top)
247 * ConstantDestAlpha Cb = Cb * Param1 392 * pixel is part of the rectangle, but the (right, bottom) pixel is
248 * 393 * not.
249 * Flag effects resolve before the op. For example 394 */
250 * BlendOp == Add && Flags == ConstantSourceAlpha | 395
251 * ConstantDestAlpha results in: 396typedef
252 * 397struct SVGASignedRect {
253 * C = (Ca * Param0) + (Cb * Param1) 398 int32 left;
254 */ 399 int32 top;
255 400 int32 right;
256#define SVGA_BLENDOP_CLEAR 0 401 int32 bottom;
257#define SVGA_BLENDOP_SRC 1 402} SVGASignedRect;
258#define SVGA_BLENDOP_DST 2 403
259#define SVGA_BLENDOP_OVER 3 404typedef
260#define SVGA_BLENDOP_OVER_REVERSE 4 405struct SVGASignedPoint {
261#define SVGA_BLENDOP_IN 5 406 int32 x;
262#define SVGA_BLENDOP_IN_REVERSE 6 407 int32 y;
263#define SVGA_BLENDOP_OUT 7 408} SVGASignedPoint;
264#define SVGA_BLENDOP_OUT_REVERSE 8 409
265#define SVGA_BLENDOP_ATOP 9 410
266#define SVGA_BLENDOP_ATOP_REVERSE 10 411/*
267#define SVGA_BLENDOP_XOR 11 412 * Capabilities
268#define SVGA_BLENDOP_ADD 12 413 *
269#define SVGA_BLENDOP_SATURATE 13 414 * Note the holes in the bitfield. Missing bits have been deprecated,
270 415 * and must not be reused. Those capabilities will never be reported
271#define SVGA_NUM_BLENDOPS 14 416 * by new versions of the SVGA device.
272#define SVGA_IS_VALID_BLENDOP(op) (op >= 0 && op < SVGA_NUM_BLENDOPS) 417 *
273 418 * SVGA_CAP_GMR2 --
274#define SVGA_BLENDFLAG_CONSTANT_SOURCE_ALPHA 0x01 419 * Provides asynchronous commands to define and remap guest memory
275#define SVGA_BLENDFLAG_CONSTANT_DEST_ALPHA 0x02 420 * regions. Adds device registers SVGA_REG_GMRS_MAX_PAGES and
276#define SVGA_NUM_BLENDFLAGS 2 421 * SVGA_REG_MEMORY_SIZE.
277#define SVGA_BLENDFLAG_ALL (MASK(SVGA_NUM_BLENDFLAGS)) 422 *
278#define SVGA_IS_VALID_BLENDFLAG(flag) ((flag & ~SVGA_BLENDFLAG_ALL) == 0) 423 * SVGA_CAP_SCREEN_OBJECT_2 --
424 * Allow screen object support, and require backing stores from the
425 * guest for each screen object.
426 */
427
428#define SVGA_CAP_NONE 0x00000000
429#define SVGA_CAP_RECT_COPY 0x00000002
430#define SVGA_CAP_CURSOR 0x00000020
431#define SVGA_CAP_CURSOR_BYPASS 0x00000040 /* Legacy (Use Cursor Bypass 3 instead) */
432#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 /* Legacy (Use Cursor Bypass 3 instead) */
433#define SVGA_CAP_8BIT_EMULATION 0x00000100
434#define SVGA_CAP_ALPHA_CURSOR 0x00000200
435#define SVGA_CAP_3D 0x00004000
436#define SVGA_CAP_EXTENDED_FIFO 0x00008000
437#define SVGA_CAP_MULTIMON 0x00010000 /* Legacy multi-monitor support */
438#define SVGA_CAP_PITCHLOCK 0x00020000
439#define SVGA_CAP_IRQMASK 0x00040000
440#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 /* Legacy multi-monitor support */
441#define SVGA_CAP_GMR 0x00100000
442#define SVGA_CAP_TRACES 0x00200000
443#define SVGA_CAP_GMR2 0x00400000
444#define SVGA_CAP_SCREEN_OBJECT_2 0x00800000
279 445
280 446
281/* 447/*
@@ -332,19 +498,47 @@ enum {
332 * These in block 3a, the VMX currently considers mandatory for the 498 * These in block 3a, the VMX currently considers mandatory for the
333 * extended FIFO. 499 * extended FIFO.
334 */ 500 */
335 501
336 /* Valid if exists (i.e. if extended FIFO enabled): */ 502 /* Valid if exists (i.e. if extended FIFO enabled): */
337 SVGA_FIFO_3D_HWVERSION, /* See SVGA3dHardwareVersion in svga3d_reg.h */ 503 SVGA_FIFO_3D_HWVERSION, /* See SVGA3dHardwareVersion in svga3d_reg.h */
338 /* Valid with SVGA_FIFO_CAP_PITCHLOCK: */ 504 /* Valid with SVGA_FIFO_CAP_PITCHLOCK: */
339 SVGA_FIFO_PITCHLOCK, 505 SVGA_FIFO_PITCHLOCK,
506
340 /* Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: */ 507 /* Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: */
341 SVGA_FIFO_CURSOR_ON, /* Cursor bypass 3 show/hide register */ 508 SVGA_FIFO_CURSOR_ON, /* Cursor bypass 3 show/hide register */
342 SVGA_FIFO_CURSOR_X, /* Cursor bypass 3 x register */ 509 SVGA_FIFO_CURSOR_X, /* Cursor bypass 3 x register */
343 SVGA_FIFO_CURSOR_Y, /* Cursor bypass 3 y register */ 510 SVGA_FIFO_CURSOR_Y, /* Cursor bypass 3 y register */
344 SVGA_FIFO_CURSOR_COUNT, /* Incremented when any of the other 3 change */ 511 SVGA_FIFO_CURSOR_COUNT, /* Incremented when any of the other 3 change */
345 SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */ 512 SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */
513
346 /* Valid with SVGA_FIFO_CAP_RESERVE: */ 514 /* Valid with SVGA_FIFO_CAP_RESERVE: */
347 SVGA_FIFO_RESERVED, /* Bytes past NEXT_CMD with real contents */ 515 SVGA_FIFO_RESERVED, /* Bytes past NEXT_CMD with real contents */
516
517 /*
518 * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2:
519 *
520 * By default this is SVGA_ID_INVALID, to indicate that the cursor
521 * coordinates are specified relative to the virtual root. If this
522 * is set to a specific screen ID, cursor position is reinterpreted
523 * as a signed offset relative to that screen's origin.
524 */
525 SVGA_FIFO_CURSOR_SCREEN_ID,
526
527 /*
528 * Valid with SVGA_FIFO_CAP_DEAD
529 *
530 * An arbitrary value written by the host, drivers should not use it.
531 */
532 SVGA_FIFO_DEAD,
533
534 /*
535 * Valid with SVGA_FIFO_CAP_3D_HWVERSION_REVISED:
536 *
537 * Contains 3D HWVERSION (see SVGA3dHardwareVersion in svga3d_reg.h)
538 * on platforms that can enforce graphics resource limits.
539 */
540 SVGA_FIFO_3D_HWVERSION_REVISED,
541
348 /* 542 /*
349 * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new 543 * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new
350 * registers, but this must be done carefully and with judicious use of 544 * registers, but this must be done carefully and with judicious use of
@@ -361,6 +555,7 @@ enum {
361 * before 3D_CAPS, needs to reason about something other than 555 * before 3D_CAPS, needs to reason about something other than
362 * SVGA_FIFO_MIN. 556 * SVGA_FIFO_MIN.
363 */ 557 */
558
364 /* 559 /*
365 * 3D caps block space; valid with 3D hardware version >= 560 * 3D caps block space; valid with 3D hardware version >=
366 * SVGA3D_HWVERSION_WS6_B1. 561 * SVGA3D_HWVERSION_WS6_B1.
@@ -533,6 +728,87 @@ enum {
533 * Pitch Lock -- Pitch lock register is supported 728 * Pitch Lock -- Pitch lock register is supported
534 * Video -- SVGA Video overlay units are supported 729 * Video -- SVGA Video overlay units are supported
535 * Escape -- Escape command is supported 730 * Escape -- Escape command is supported
731 *
732 * XXX: Add longer descriptions for each capability, including a list
733 * of the new features that each capability provides.
734 *
735 * SVGA_FIFO_CAP_SCREEN_OBJECT --
736 *
737 * Provides dynamic multi-screen rendering, for improved Unity and
738 * multi-monitor modes. With Screen Object, the guest can
739 * dynamically create and destroy 'screens', which can represent
740 * Unity windows or virtual monitors. Screen Object also provides
741 * strong guarantees that DMA operations happen only when
742 * guest-initiated. Screen Object deprecates the BAR1 guest
743 * framebuffer (GFB) and all commands that work only with the GFB.
744 *
745 * New registers:
746 * FIFO_CURSOR_SCREEN_ID, VIDEO_DATA_GMRID, VIDEO_DST_SCREEN_ID
747 *
748 * New 2D commands:
749 * DEFINE_SCREEN, DESTROY_SCREEN, DEFINE_GMRFB, BLIT_GMRFB_TO_SCREEN,
750 * BLIT_SCREEN_TO_GMRFB, ANNOTATION_FILL, ANNOTATION_COPY
751 *
752 * New 3D commands:
753 * BLIT_SURFACE_TO_SCREEN
754 *
755 * New guarantees:
756 *
757 * - The host will not read or write guest memory, including the GFB,
758 * except when explicitly initiated by a DMA command.
759 *
760 * - All DMA, including legacy DMA like UPDATE and PRESENT_READBACK,
761 * is guaranteed to complete before any subsequent FENCEs.
762 *
763 * - All legacy commands which affect a Screen (UPDATE, PRESENT,
764 * PRESENT_READBACK) as well as new Screen blit commands will
765 * all behave consistently as blits, and memory will be read
766 * or written in FIFO order.
767 *
768 * For example, if you PRESENT from one SVGA3D surface to multiple
769 * places on the screen, the data copied will always be from the
770 * SVGA3D surface at the time the PRESENT was issued in the FIFO.
771 * This was not necessarily true on devices without Screen Object.
772 *
773 * This means that on devices that support Screen Object, the
774 * PRESENT_READBACK command should not be necessary unless you
775 * actually want to read back the results of 3D rendering into
776 * system memory. (And for that, the BLIT_SCREEN_TO_GMRFB
777 * command provides a strict superset of functionality.)
778 *
779 * - When a screen is resized, either using Screen Object commands or
780 * legacy multimon registers, its contents are preserved.
781 *
782 * SVGA_FIFO_CAP_GMR2 --
783 *
784 * Provides new commands to define and remap guest memory regions (GMR).
785 *
786 * New 2D commands:
787 * DEFINE_GMR2, REMAP_GMR2.
788 *
789 * SVGA_FIFO_CAP_3D_HWVERSION_REVISED --
790 *
791 * Indicates new register SVGA_FIFO_3D_HWVERSION_REVISED exists.
792 * This register may replace SVGA_FIFO_3D_HWVERSION on platforms
793 * that enforce graphics resource limits. This allows the platform
794 * to clear SVGA_FIFO_3D_HWVERSION and disable 3D in legacy guest
795 * drivers that do not limit their resources.
796 *
797 * Note this is an alias to SVGA_FIFO_CAP_GMR2 because these indicators
798 * are codependent (and thus we use a single capability bit).
799 *
800 * SVGA_FIFO_CAP_SCREEN_OBJECT_2 --
801 *
802 * Modifies the DEFINE_SCREEN command to include a guest provided
803 * backing store in GMR memory and the bytesPerLine for the backing
804 * store. This capability requires the use of a backing store when
805 * creating screen objects. However if SVGA_FIFO_CAP_SCREEN_OBJECT
806 * is present then backing stores are optional.
807 *
808 * SVGA_FIFO_CAP_DEAD --
809 *
810 * Drivers should not use this cap bit. This cap bit can not be
811 * reused since some hosts already expose it.
536 */ 812 */
537 813
538#define SVGA_FIFO_CAP_NONE 0 814#define SVGA_FIFO_CAP_NONE 0
@@ -543,6 +819,11 @@ enum {
543#define SVGA_FIFO_CAP_CURSOR_BYPASS_3 (1<<4) 819#define SVGA_FIFO_CAP_CURSOR_BYPASS_3 (1<<4)
544#define SVGA_FIFO_CAP_ESCAPE (1<<5) 820#define SVGA_FIFO_CAP_ESCAPE (1<<5)
545#define SVGA_FIFO_CAP_RESERVE (1<<6) 821#define SVGA_FIFO_CAP_RESERVE (1<<6)
822#define SVGA_FIFO_CAP_SCREEN_OBJECT (1<<7)
823#define SVGA_FIFO_CAP_GMR2 (1<<8)
824#define SVGA_FIFO_CAP_3D_HWVERSION_REVISED SVGA_FIFO_CAP_GMR2
825#define SVGA_FIFO_CAP_SCREEN_OBJECT_2 (1<<9)
826#define SVGA_FIFO_CAP_DEAD (1<<10)
546 827
547 828
548/* 829/*
@@ -586,20 +867,22 @@ enum {
586 SVGA_VIDEO_DATA_OFFSET, 867 SVGA_VIDEO_DATA_OFFSET,
587 SVGA_VIDEO_FORMAT, 868 SVGA_VIDEO_FORMAT,
588 SVGA_VIDEO_COLORKEY, 869 SVGA_VIDEO_COLORKEY,
589 SVGA_VIDEO_SIZE, 870 SVGA_VIDEO_SIZE, /* Deprecated */
590 SVGA_VIDEO_WIDTH, 871 SVGA_VIDEO_WIDTH,
591 SVGA_VIDEO_HEIGHT, 872 SVGA_VIDEO_HEIGHT,
592 SVGA_VIDEO_SRC_X, 873 SVGA_VIDEO_SRC_X,
593 SVGA_VIDEO_SRC_Y, 874 SVGA_VIDEO_SRC_Y,
594 SVGA_VIDEO_SRC_WIDTH, 875 SVGA_VIDEO_SRC_WIDTH,
595 SVGA_VIDEO_SRC_HEIGHT, 876 SVGA_VIDEO_SRC_HEIGHT,
596 SVGA_VIDEO_DST_X, 877 SVGA_VIDEO_DST_X, /* Signed int32 */
597 SVGA_VIDEO_DST_Y, 878 SVGA_VIDEO_DST_Y, /* Signed int32 */
598 SVGA_VIDEO_DST_WIDTH, 879 SVGA_VIDEO_DST_WIDTH,
599 SVGA_VIDEO_DST_HEIGHT, 880 SVGA_VIDEO_DST_HEIGHT,
600 SVGA_VIDEO_PITCH_1, 881 SVGA_VIDEO_PITCH_1,
601 SVGA_VIDEO_PITCH_2, 882 SVGA_VIDEO_PITCH_2,
602 SVGA_VIDEO_PITCH_3, 883 SVGA_VIDEO_PITCH_3,
884 SVGA_VIDEO_DATA_GMRID, /* Optional, defaults to SVGA_GMR_FRAMEBUFFER */
885 SVGA_VIDEO_DST_SCREEN_ID, /* Optional, defaults to virtual coords (SVGA_ID_INVALID) */
603 SVGA_VIDEO_NUM_REGS 886 SVGA_VIDEO_NUM_REGS
604}; 887};
605 888
@@ -625,242 +908,658 @@ typedef struct SVGAOverlayUnit {
625 uint32 srcY; 908 uint32 srcY;
626 uint32 srcWidth; 909 uint32 srcWidth;
627 uint32 srcHeight; 910 uint32 srcHeight;
628 uint32 dstX; 911 int32 dstX;
629 uint32 dstY; 912 int32 dstY;
630 uint32 dstWidth; 913 uint32 dstWidth;
631 uint32 dstHeight; 914 uint32 dstHeight;
632 uint32 pitches[3]; 915 uint32 pitches[3];
916 uint32 dataGMRId;
917 uint32 dstScreenId;
633} SVGAOverlayUnit; 918} SVGAOverlayUnit;
634 919
635 920
636/* 921/*
637 * Drawing object ID's, in the range 0 to SVGA_MAX_ID 922 * SVGAScreenObject --
923 *
924 * This is a new way to represent a guest's multi-monitor screen or
925 * Unity window. Screen objects are only supported if the
926 * SVGA_FIFO_CAP_SCREEN_OBJECT capability bit is set.
927 *
928 * If Screen Objects are supported, they can be used to fully
929 * replace the functionality provided by the framebuffer registers
930 * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY.
931 *
932 * The screen object is a struct with guaranteed binary
933 * compatibility. New flags can be added, and the struct may grow,
934 * but existing fields must retain their meaning.
935 *
936 * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2 are required fields of
937 * a SVGAGuestPtr that is used to back the screen contents. This
938 * memory must come from the GFB. The guest is not allowed to
939 * access the memory and doing so will have undefined results. The
940 * backing store is required to be page aligned and the size is
941 * padded to the next page boundry. The number of pages is:
942 * (bytesPerLine * size.width * 4 + PAGE_SIZE - 1) / PAGE_SIZE
943 *
944 * The pitch in the backingStore is required to be at least large
945 * enough to hold a 32bbp scanline. It is recommended that the
946 * driver pad bytesPerLine for a potential performance win.
947 *
948 * The cloneCount field is treated as a hint from the guest that
949 * the user wants this display to be cloned, countCount times. A
950 * value of zero means no cloning should happen.
638 */ 951 */
639 952
640#define SVGA_MAX_ID 499 953#define SVGA_SCREEN_MUST_BE_SET (1 << 0) /* Must be set or results undefined */
954#define SVGA_SCREEN_HAS_ROOT SVGA_SCREEN_MUST_BE_SET /* Deprecated */
955#define SVGA_SCREEN_IS_PRIMARY (1 << 1) /* Guest considers this screen to be 'primary' */
956#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) /* Guest is running a fullscreen app here */
641 957
642/* 958/*
643 * Macros to compute variable length items (sizes in 32-bit words, except 959 * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When the screen is
644 * for SVGA_GLYPH_SCANLINE_SIZE, which is in bytes). 960 * deactivated the base layer is defined to lose all contents and
961 * become black. When a screen is deactivated the backing store is
962 * optional. When set backingPtr and bytesPerLine will be ignored.
645 */ 963 */
964#define SVGA_SCREEN_DEACTIVATE (1 << 3)
965
966/*
967 * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When this flag is set
968 * the screen contents will be outputted as all black to the user
969 * though the base layer contents is preserved. The screen base layer
970 * can still be read and written to like normal though the no visible
971 * effect will be seen by the user. When the flag is changed the
972 * screen will be blanked or redrawn to the current contents as needed
973 * without any extra commands from the driver. This flag only has an
974 * effect when the screen is not deactivated.
975 */
976#define SVGA_SCREEN_BLANKING (1 << 4)
977
978typedef
979struct SVGAScreenObject {
980 uint32 structSize; /* sizeof(SVGAScreenObject) */
981 uint32 id;
982 uint32 flags;
983 struct {
984 uint32 width;
985 uint32 height;
986 } size;
987 struct {
988 int32 x;
989 int32 y;
990 } root;
991
992 /*
993 * Added and required by SVGA_FIFO_CAP_SCREEN_OBJECT_2, optional
994 * with SVGA_FIFO_CAP_SCREEN_OBJECT.
995 */
996 SVGAGuestImage backingStore;
997 uint32 cloneCount;
998} SVGAScreenObject;
646 999
647#define SVGA_BITMAP_SIZE(w,h) ((((w)+31) >> 5) * (h))
648#define SVGA_BITMAP_SCANLINE_SIZE(w) (( (w)+31 ) >> 5)
649#define SVGA_PIXMAP_SIZE(w,h,bpp) ((( ((w)*(bpp))+31 ) >> 5) * (h))
650#define SVGA_PIXMAP_SCANLINE_SIZE(w,bpp) (( ((w)*(bpp))+31 ) >> 5)
651#define SVGA_GLYPH_SIZE(w,h) ((((((w) + 7) >> 3) * (h)) + 3) >> 2)
652#define SVGA_GLYPH_SCANLINE_SIZE(w) (((w) + 7) >> 3)
653#define SVGA_ESCAPE_SIZE(s) (((s) + 3) >> 2)
654 1000
655/* 1001/*
656 * Increment from one scanline to the next of a bitmap or pixmap 1002 * Commands in the command FIFO:
1003 *
1004 * Command IDs defined below are used for the traditional 2D FIFO
1005 * communication (not all commands are available for all versions of the
1006 * SVGA FIFO protocol).
1007 *
1008 * Note the holes in the command ID numbers: These commands have been
1009 * deprecated, and the old IDs must not be reused.
1010 *
1011 * Command IDs from 1000 to 1999 are reserved for use by the SVGA3D
1012 * protocol.
1013 *
1014 * Each command's parameters are described by the comments and
1015 * structs below.
657 */ 1016 */
658#define SVGA_BITMAP_INCREMENT(w) ((( (w)+31 ) >> 5) * sizeof (uint32)) 1017
659#define SVGA_PIXMAP_INCREMENT(w,bpp) ((( ((w)*(bpp))+31 ) >> 5) * sizeof (uint32)) 1018typedef enum {
1019 SVGA_CMD_INVALID_CMD = 0,
1020 SVGA_CMD_UPDATE = 1,
1021 SVGA_CMD_RECT_COPY = 3,
1022 SVGA_CMD_DEFINE_CURSOR = 19,
1023 SVGA_CMD_DEFINE_ALPHA_CURSOR = 22,
1024 SVGA_CMD_UPDATE_VERBOSE = 25,
1025 SVGA_CMD_FRONT_ROP_FILL = 29,
1026 SVGA_CMD_FENCE = 30,
1027 SVGA_CMD_ESCAPE = 33,
1028 SVGA_CMD_DEFINE_SCREEN = 34,
1029 SVGA_CMD_DESTROY_SCREEN = 35,
1030 SVGA_CMD_DEFINE_GMRFB = 36,
1031 SVGA_CMD_BLIT_GMRFB_TO_SCREEN = 37,
1032 SVGA_CMD_BLIT_SCREEN_TO_GMRFB = 38,
1033 SVGA_CMD_ANNOTATION_FILL = 39,
1034 SVGA_CMD_ANNOTATION_COPY = 40,
1035 SVGA_CMD_DEFINE_GMR2 = 41,
1036 SVGA_CMD_REMAP_GMR2 = 42,
1037 SVGA_CMD_MAX
1038} SVGAFifoCmdId;
1039
1040#define SVGA_CMD_MAX_ARGS 64
1041
660 1042
661/* 1043/*
662 * Transparent color for DRAW_GLYPH_CLIPPED 1044 * SVGA_CMD_UPDATE --
1045 *
1046 * This is a DMA transfer which copies from the Guest Framebuffer
1047 * (GFB) at BAR1 + SVGA_REG_FB_OFFSET to any screens which
1048 * intersect with the provided virtual rectangle.
1049 *
1050 * This command does not support using arbitrary guest memory as a
1051 * data source- it only works with the pre-defined GFB memory.
1052 * This command also does not support signed virtual coordinates.
1053 * If you have defined screens (using SVGA_CMD_DEFINE_SCREEN) with
1054 * negative root x/y coordinates, the negative portion of those
1055 * screens will not be reachable by this command.
1056 *
1057 * This command is not necessary when using framebuffer
1058 * traces. Traces are automatically enabled if the SVGA FIFO is
1059 * disabled, and you may explicitly enable/disable traces using
1060 * SVGA_REG_TRACES. With traces enabled, any write to the GFB will
1061 * automatically act as if a subsequent SVGA_CMD_UPDATE was issued.
1062 *
1063 * Traces and SVGA_CMD_UPDATE are the only supported ways to render
1064 * pseudocolor screen updates. The newer Screen Object commands
1065 * only support true color formats.
1066 *
1067 * Availability:
1068 * Always available.
663 */ 1069 */
664#define SVGA_COLOR_TRANSPARENT (~0) 1070
1071typedef
1072struct SVGAFifoCmdUpdate {
1073 uint32 x;
1074 uint32 y;
1075 uint32 width;
1076 uint32 height;
1077} SVGAFifoCmdUpdate;
1078
665 1079
666/* 1080/*
667 * Commands in the command FIFO 1081 * SVGA_CMD_RECT_COPY --
1082 *
1083 * Perform a rectangular DMA transfer from one area of the GFB to
1084 * another, and copy the result to any screens which intersect it.
1085 *
1086 * Availability:
1087 * SVGA_CAP_RECT_COPY
668 */ 1088 */
669 1089
670#define SVGA_CMD_INVALID_CMD 0 1090typedef
671 /* FIFO layout: 1091struct SVGAFifoCmdRectCopy {
672 <nothing> (well, undefined) */ 1092 uint32 srcX;
1093 uint32 srcY;
1094 uint32 destX;
1095 uint32 destY;
1096 uint32 width;
1097 uint32 height;
1098} SVGAFifoCmdRectCopy;
673 1099
674#define SVGA_CMD_UPDATE 1
675 /* FIFO layout:
676 X, Y, Width, Height */
677 1100
678#define SVGA_CMD_RECT_FILL 2 1101/*
679 /* FIFO layout: 1102 * SVGA_CMD_DEFINE_CURSOR --
680 Color, X, Y, Width, Height */ 1103 *
1104 * Provide a new cursor image, as an AND/XOR mask.
1105 *
1106 * The recommended way to position the cursor overlay is by using
1107 * the SVGA_FIFO_CURSOR_* registers, supported by the
1108 * SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability.
1109 *
1110 * Availability:
1111 * SVGA_CAP_CURSOR
1112 */
681 1113
682#define SVGA_CMD_RECT_COPY 3 1114typedef
683 /* FIFO layout: 1115struct SVGAFifoCmdDefineCursor {
684 Source X, Source Y, Dest X, Dest Y, Width, Height */ 1116 uint32 id; /* Reserved, must be zero. */
1117 uint32 hotspotX;
1118 uint32 hotspotY;
1119 uint32 width;
1120 uint32 height;
1121 uint32 andMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */
1122 uint32 xorMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */
1123 /*
1124 * Followed by scanline data for AND mask, then XOR mask.
1125 * Each scanline is padded to a 32-bit boundary.
1126 */
1127} SVGAFifoCmdDefineCursor;
685 1128
686#define SVGA_CMD_DEFINE_BITMAP 4
687 /* FIFO layout:
688 Pixmap ID, Width, Height, <scanlines> */
689 1129
690#define SVGA_CMD_DEFINE_BITMAP_SCANLINE 5 1130/*
691 /* FIFO layout: 1131 * SVGA_CMD_DEFINE_ALPHA_CURSOR --
692 Pixmap ID, Width, Height, Line #, scanline */ 1132 *
1133 * Provide a new cursor image, in 32-bit BGRA format.
1134 *
1135 * The recommended way to position the cursor overlay is by using
1136 * the SVGA_FIFO_CURSOR_* registers, supported by the
1137 * SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability.
1138 *
1139 * Availability:
1140 * SVGA_CAP_ALPHA_CURSOR
1141 */
693 1142
694#define SVGA_CMD_DEFINE_PIXMAP 6 1143typedef
695 /* FIFO layout: 1144struct SVGAFifoCmdDefineAlphaCursor {
696 Pixmap ID, Width, Height, Depth, <scanlines> */ 1145 uint32 id; /* Reserved, must be zero. */
1146 uint32 hotspotX;
1147 uint32 hotspotY;
1148 uint32 width;
1149 uint32 height;
1150 /* Followed by scanline data */
1151} SVGAFifoCmdDefineAlphaCursor;
697 1152
698#define SVGA_CMD_DEFINE_PIXMAP_SCANLINE 7
699 /* FIFO layout:
700 Pixmap ID, Width, Height, Depth, Line #, scanline */
701 1153
702#define SVGA_CMD_RECT_BITMAP_FILL 8 1154/*
703 /* FIFO layout: 1155 * SVGA_CMD_UPDATE_VERBOSE --
704 Bitmap ID, X, Y, Width, Height, Foreground, Background */ 1156 *
1157 * Just like SVGA_CMD_UPDATE, but also provide a per-rectangle
1158 * 'reason' value, an opaque cookie which is used by internal
1159 * debugging tools. Third party drivers should not use this
1160 * command.
1161 *
1162 * Availability:
1163 * SVGA_CAP_EXTENDED_FIFO
1164 */
705 1165
706#define SVGA_CMD_RECT_PIXMAP_FILL 9 1166typedef
707 /* FIFO layout: 1167struct SVGAFifoCmdUpdateVerbose {
708 Pixmap ID, X, Y, Width, Height */ 1168 uint32 x;
1169 uint32 y;
1170 uint32 width;
1171 uint32 height;
1172 uint32 reason;
1173} SVGAFifoCmdUpdateVerbose;
709 1174
710#define SVGA_CMD_RECT_BITMAP_COPY 10
711 /* FIFO layout:
712 Bitmap ID, Source X, Source Y, Dest X, Dest Y,
713 Width, Height, Foreground, Background */
714 1175
715#define SVGA_CMD_RECT_PIXMAP_COPY 11 1176/*
716 /* FIFO layout: 1177 * SVGA_CMD_FRONT_ROP_FILL --
717 Pixmap ID, Source X, Source Y, Dest X, Dest Y, Width, Height */ 1178 *
1179 * This is a hint which tells the SVGA device that the driver has
1180 * just filled a rectangular region of the GFB with a solid
1181 * color. Instead of reading these pixels from the GFB, the device
1182 * can assume that they all equal 'color'. This is primarily used
1183 * for remote desktop protocols.
1184 *
1185 * Availability:
1186 * SVGA_FIFO_CAP_ACCELFRONT
1187 */
1188
1189#define SVGA_ROP_COPY 0x03
718 1190
719#define SVGA_CMD_FREE_OBJECT 12 1191#define SVGA_INVALID_DISPLAY_ID ((uint32)-1)
720 /* FIFO layout:
721 Object (pixmap, bitmap, ...) ID */
722 1192
723#define SVGA_CMD_RECT_ROP_FILL 13 1193typedef
724 /* FIFO layout: 1194struct SVGAFifoCmdFrontRopFill {
725 Color, X, Y, Width, Height, ROP */ 1195 uint32 color; /* In the same format as the GFB */
1196 uint32 x;
1197 uint32 y;
1198 uint32 width;
1199 uint32 height;
1200 uint32 rop; /* Must be SVGA_ROP_COPY */
1201} SVGAFifoCmdFrontRopFill;
726 1202
727#define SVGA_CMD_RECT_ROP_COPY 14
728 /* FIFO layout:
729 Source X, Source Y, Dest X, Dest Y, Width, Height, ROP */
730 1203
731#define SVGA_CMD_RECT_ROP_BITMAP_FILL 15 1204/*
732 /* FIFO layout: 1205 * SVGA_CMD_FENCE --
733 ID, X, Y, Width, Height, Foreground, Background, ROP */ 1206 *
1207 * Insert a synchronization fence. When the SVGA device reaches
1208 * this command, it will copy the 'fence' value into the
1209 * SVGA_FIFO_FENCE register. It will also compare the fence against
1210 * SVGA_FIFO_FENCE_GOAL. If the fence matches the goal and the
1211 * SVGA_IRQFLAG_FENCE_GOAL interrupt is enabled, the device will
1212 * raise this interrupt.
1213 *
1214 * Availability:
1215 * SVGA_FIFO_FENCE for this command,
1216 * SVGA_CAP_IRQMASK for SVGA_FIFO_FENCE_GOAL.
1217 */
734 1218
735#define SVGA_CMD_RECT_ROP_PIXMAP_FILL 16 1219typedef
736 /* FIFO layout: 1220struct {
737 ID, X, Y, Width, Height, ROP */ 1221 uint32 fence;
1222} SVGAFifoCmdFence;
738 1223
739#define SVGA_CMD_RECT_ROP_BITMAP_COPY 17
740 /* FIFO layout:
741 ID, Source X, Source Y,
742 Dest X, Dest Y, Width, Height, Foreground, Background, ROP */
743 1224
744#define SVGA_CMD_RECT_ROP_PIXMAP_COPY 18 1225/*
745 /* FIFO layout: 1226 * SVGA_CMD_ESCAPE --
746 ID, Source X, Source Y, Dest X, Dest Y, Width, Height, ROP */ 1227 *
1228 * Send an extended or vendor-specific variable length command.
1229 * This is used for video overlay, third party plugins, and
1230 * internal debugging tools. See svga_escape.h
1231 *
1232 * Availability:
1233 * SVGA_FIFO_CAP_ESCAPE
1234 */
747 1235
748#define SVGA_CMD_DEFINE_CURSOR 19 1236typedef
749 /* FIFO layout: 1237struct SVGAFifoCmdEscape {
750 ID, Hotspot X, Hotspot Y, Width, Height, 1238 uint32 nsid;
751 Depth for AND mask, Depth for XOR mask, 1239 uint32 size;
752 <scanlines for AND mask>, <scanlines for XOR mask> */ 1240 /* followed by 'size' bytes of data */
1241} SVGAFifoCmdEscape;
753 1242
754#define SVGA_CMD_DISPLAY_CURSOR 20
755 /* FIFO layout:
756 ID, On/Off (1 or 0) */
757 1243
758#define SVGA_CMD_MOVE_CURSOR 21 1244/*
759 /* FIFO layout: 1245 * SVGA_CMD_DEFINE_SCREEN --
760 X, Y */ 1246 *
1247 * Define or redefine an SVGAScreenObject. See the description of
1248 * SVGAScreenObject above. The video driver is responsible for
1249 * generating new screen IDs. They should be small positive
1250 * integers. The virtual device will have an implementation
1251 * specific upper limit on the number of screen IDs
1252 * supported. Drivers are responsible for recycling IDs. The first
1253 * valid ID is zero.
1254 *
1255 * - Interaction with other registers:
1256 *
1257 * For backwards compatibility, when the GFB mode registers (WIDTH,
1258 * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device
1259 * deletes all screens other than screen #0, and redefines screen
1260 * #0 according to the specified mode. Drivers that use
1261 * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0.
1262 *
1263 * If you use screen objects, do not use the legacy multi-mon
1264 * registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*).
1265 *
1266 * Availability:
1267 * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
1268 */
761 1269
762#define SVGA_CMD_DEFINE_ALPHA_CURSOR 22 1270typedef
763 /* FIFO layout: 1271struct {
764 ID, Hotspot X, Hotspot Y, Width, Height, 1272 SVGAScreenObject screen; /* Variable-length according to version */
765 <scanlines> */ 1273} SVGAFifoCmdDefineScreen;
766 1274
767#define SVGA_CMD_DRAW_GLYPH 23
768 /* FIFO layout:
769 X, Y, W, H, FGCOLOR, <stencil buffer> */
770
771#define SVGA_CMD_DRAW_GLYPH_CLIPPED 24
772 /* FIFO layout:
773 X, Y, W, H, FGCOLOR, BGCOLOR, <cliprect>, <stencil buffer>
774 Transparent color expands are done by setting BGCOLOR to ~0 */
775
776#define SVGA_CMD_UPDATE_VERBOSE 25
777 /* FIFO layout:
778 X, Y, Width, Height, Reason */
779
780#define SVGA_CMD_SURFACE_FILL 26
781 /* FIFO layout:
782 color, dstSurfaceOffset, x, y, w, h, rop */
783
784#define SVGA_CMD_SURFACE_COPY 27
785 /* FIFO layout:
786 srcSurfaceOffset, dstSurfaceOffset, srcX, srcY,
787 destX, destY, w, h, rop */
788
789#define SVGA_CMD_SURFACE_ALPHA_BLEND 28
790 /* FIFO layout:
791 srcSurfaceOffset, dstSurfaceOffset, srcX, srcY,
792 destX, destY, w, h, op (SVGA_BLENDOP*), flags (SVGA_BLENDFLAGS*),
793 param1, param2 */
794
795#define SVGA_CMD_FRONT_ROP_FILL 29
796 /* FIFO layout:
797 Color, X, Y, Width, Height, ROP */
798
799#define SVGA_CMD_FENCE 30
800 /* FIFO layout:
801 Fence value */
802
803#define SVGA_CMD_VIDEO_PLAY_OBSOLETE 31
804 /* Obsolete; do not use. */
805
806#define SVGA_CMD_VIDEO_END_OBSOLETE 32
807 /* Obsolete; do not use. */
808
809#define SVGA_CMD_ESCAPE 33
810 /* FIFO layout:
811 Namespace ID, size(bytes), data */
812
813#define SVGA_CMD_MAX 34
814
815#define SVGA_CMD_MAX_ARGS 64
816
817/*
818 * Location and size of SVGA frame buffer and the FIFO.
819 */
820#define SVGA_VRAM_MIN_SIZE (4 * 640 * 480) /* bytes */
821#define SVGA_VRAM_MAX_SIZE (128 * 1024 * 1024)
822
823#define SVGA_VRAM_SIZE_WS (16 * 1024 * 1024) /* 16 MB */
824#define SVGA_MEM_SIZE_WS (2 * 1024 * 1024) /* 2 MB */
825#define SVGA_VRAM_SIZE_SERVER (4 * 1024 * 1024) /* 4 MB */
826#define SVGA_MEM_SIZE_SERVER (256 * 1024) /* 256 KB */
827
828#if /* defined(VMX86_WGS) || */ defined(VMX86_SERVER)
829#define SVGA_VRAM_SIZE SVGA_VRAM_SIZE_SERVER
830#define SVGA_MEM_SIZE SVGA_MEM_SIZE_SERVER
831#else
832#define SVGA_VRAM_SIZE SVGA_VRAM_SIZE_WS
833#define SVGA_MEM_SIZE SVGA_MEM_SIZE_WS
834#endif
835 1275
836/* 1276/*
837 * SVGA_FB_START is the default starting address of the SVGA frame 1277 * SVGA_CMD_DESTROY_SCREEN --
838 * buffer in the guest's physical address space. 1278 *
839 * SVGA_FB_START_BIGMEM is the starting address of the SVGA frame 1279 * Destroy an SVGAScreenObject. Its ID is immediately available for
840 * buffer for VMs that have a large amount of physical memory. 1280 * re-use.
841 * 1281 *
842 * The address of SVGA_FB_START is set to 2GB - (SVGA_FB_MAX_SIZE + SVGA_MEM_SIZE), 1282 * Availability:
843 * thus the SVGA frame buffer sits at [SVGA_FB_START .. 2GB-1] in the 1283 * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
844 * physical address space. Our older SVGA drivers for NT treat the 1284 */
845 * address of the frame buffer as a signed integer. For backwards 1285
846 * compatibility, we keep the default location of the frame buffer 1286typedef
847 * at under 2GB in the address space. This restricts VMs to have "only" 1287struct {
848 * up to ~2031MB (i.e., up to SVGA_FB_START) of physical memory. 1288 uint32 screenId;
849 * 1289} SVGAFifoCmdDestroyScreen;
850 * For VMs that want more memory than the ~2031MB, we place the SVGA 1290
851 * frame buffer at SVGA_FB_START_BIGMEM. This allows VMs to have up 1291
852 * to 3584MB, at least as far as the SVGA frame buffer is concerned 1292/*
853 * (note that there may be other issues that limit the VM memory 1293 * SVGA_CMD_DEFINE_GMRFB --
854 * size). PCI devices use high memory addresses, so we have to put 1294 *
855 * SVGA_FB_START_BIGMEM low enough so that it doesn't overlap with any 1295 * This command sets a piece of SVGA device state called the
856 * of these devices. Placing SVGA_FB_START_BIGMEM at 0xE0000000 1296 * Guest Memory Region Framebuffer, or GMRFB. The GMRFB is a
857 * should leave plenty of room for the PCI devices. 1297 * piece of light-weight state which identifies the location and
858 * 1298 * format of an image in guest memory or in BAR1. The GMRFB has
859 * NOTE: All of that is only true for the 0710 chipset. As of the 0405 1299 * an arbitrary size, and it doesn't need to match the geometry
860 * chipset, the framebuffer start is determined solely based on the value 1300 * of the GFB or any screen object.
861 * the guest BIOS or OS programs into the PCI base address registers. 1301 *
862 */ 1302 * The GMRFB can be redefined as often as you like. You could
863#define SVGA_FB_LEGACY_START 0x7EFC0000 1303 * always use the same GMRFB, you could redefine it before
864#define SVGA_FB_LEGACY_START_BIGMEM 0xE0000000 1304 * rendering from a different guest screen, or you could even
1305 * redefine it before every blit.
1306 *
1307 * There are multiple ways to use this command. The simplest way is
1308 * to use it to move the framebuffer either to elsewhere in the GFB
1309 * (BAR1) memory region, or to a user-defined GMR. This lets a
1310 * driver use a framebuffer allocated entirely out of normal system
1311 * memory, which we encourage.
1312 *
1313 * Another way to use this command is to set up a ring buffer of
1314 * updates in GFB memory. If a driver wants to ensure that no
1315 * frames are skipped by the SVGA device, it is important that the
1316 * driver not modify the source data for a blit until the device is
1317 * done processing the command. One efficient way to accomplish
1318 * this is to use a ring of small DMA buffers. Each buffer is used
1319 * for one blit, then we move on to the next buffer in the
1320 * ring. The FENCE mechanism is used to protect each buffer from
1321 * re-use until the device is finished with that buffer's
1322 * corresponding blit.
1323 *
1324 * This command does not affect the meaning of SVGA_CMD_UPDATE.
1325 * UPDATEs always occur from the legacy GFB memory area. This
1326 * command has no support for pseudocolor GMRFBs. Currently only
1327 * true-color 15, 16, and 24-bit depths are supported. Future
1328 * devices may expose capabilities for additional framebuffer
1329 * formats.
1330 *
1331 * The default GMRFB value is undefined. Drivers must always send
1332 * this command at least once before performing any blit from the
1333 * GMRFB.
1334 *
1335 * Availability:
1336 * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
1337 */
1338
1339typedef
1340struct {
1341 SVGAGuestPtr ptr;
1342 uint32 bytesPerLine;
1343 SVGAGMRImageFormat format;
1344} SVGAFifoCmdDefineGMRFB;
1345
1346
1347/*
1348 * SVGA_CMD_BLIT_GMRFB_TO_SCREEN --
1349 *
1350 * This is a guest-to-host blit. It performs a DMA operation to
1351 * copy a rectangular region of pixels from the current GMRFB to
1352 * one or more Screen Objects.
1353 *
1354 * The destination coordinate may be specified relative to a
1355 * screen's origin (if a screen ID is specified) or relative to the
1356 * virtual coordinate system's origin (if the screen ID is
1357 * SVGA_ID_INVALID). The actual destination may span zero or more
1358 * screens, in the case of a virtual destination rect or a rect
1359 * which extends off the edge of the specified screen.
1360 *
1361 * This command writes to the screen's "base layer": the underlying
1362 * framebuffer which exists below any cursor or video overlays. No
1363 * action is necessary to explicitly hide or update any overlays
1364 * which exist on top of the updated region.
1365 *
1366 * The SVGA device is guaranteed to finish reading from the GMRFB
1367 * by the time any subsequent FENCE commands are reached.
1368 *
1369 * This command consumes an annotation. See the
1370 * SVGA_CMD_ANNOTATION_* commands for details.
1371 *
1372 * Availability:
1373 * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
1374 */
1375
1376typedef
1377struct {
1378 SVGASignedPoint srcOrigin;
1379 SVGASignedRect destRect;
1380 uint32 destScreenId;
1381} SVGAFifoCmdBlitGMRFBToScreen;
1382
1383
1384/*
1385 * SVGA_CMD_BLIT_SCREEN_TO_GMRFB --
1386 *
1387 * This is a host-to-guest blit. It performs a DMA operation to
1388 * copy a rectangular region of pixels from a single Screen Object
1389 * back to the current GMRFB.
1390 *
1391 * Usage note: This command should be used rarely. It will
1392 * typically be inefficient, but it is necessary for some types of
1393 * synchronization between 3D (GPU) and 2D (CPU) rendering into
1394 * overlapping areas of a screen.
1395 *
1396 * The source coordinate is specified relative to a screen's
1397 * origin. The provided screen ID must be valid. If any parameters
1398 * are invalid, the resulting pixel values are undefined.
1399 *
1400 * This command reads the screen's "base layer". Overlays like
1401 * video and cursor are not included, but any data which was sent
1402 * using a blit-to-screen primitive will be available, no matter
1403 * whether the data's original source was the GMRFB or the 3D
1404 * acceleration hardware.
1405 *
1406 * Note that our guest-to-host blits and host-to-guest blits aren't
1407 * symmetric in their current implementation. While the parameters
1408 * are identical, host-to-guest blits are a lot less featureful.
1409 * They do not support clipping: If the source parameters don't
1410 * fully fit within a screen, the blit fails. They must originate
1411 * from exactly one screen. Virtual coordinates are not directly
1412 * supported.
1413 *
1414 * Host-to-guest blits do support the same set of GMRFB formats
1415 * offered by guest-to-host blits.
1416 *
1417 * The SVGA device is guaranteed to finish writing to the GMRFB by
1418 * the time any subsequent FENCE commands are reached.
1419 *
1420 * Availability:
1421 * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
1422 */
1423
1424typedef
1425struct {
1426 SVGASignedPoint destOrigin;
1427 SVGASignedRect srcRect;
1428 uint32 srcScreenId;
1429} SVGAFifoCmdBlitScreenToGMRFB;
1430
1431
1432/*
1433 * SVGA_CMD_ANNOTATION_FILL --
1434 *
1435 * This is a blit annotation. This command stores a small piece of
1436 * device state which is consumed by the next blit-to-screen
1437 * command. The state is only cleared by commands which are
1438 * specifically documented as consuming an annotation. Other
1439 * commands (such as ESCAPEs for debugging) may intervene between
1440 * the annotation and its associated blit.
1441 *
1442 * This annotation is a promise about the contents of the next
1443 * blit: The video driver is guaranteeing that all pixels in that
1444 * blit will have the same value, specified here as a color in
1445 * SVGAColorBGRX format.
1446 *
1447 * The SVGA device can still render the blit correctly even if it
1448 * ignores this annotation, but the annotation may allow it to
1449 * perform the blit more efficiently, for example by ignoring the
1450 * source data and performing a fill in hardware.
1451 *
1452 * This annotation is most important for performance when the
1453 * user's display is being remoted over a network connection.
1454 *
1455 * Availability:
1456 * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
1457 */
1458
1459typedef
1460struct {
1461 SVGAColorBGRX color;
1462} SVGAFifoCmdAnnotationFill;
1463
1464
1465/*
1466 * SVGA_CMD_ANNOTATION_COPY --
1467 *
1468 * This is a blit annotation. See SVGA_CMD_ANNOTATION_FILL for more
1469 * information about annotations.
1470 *
1471 * This annotation is a promise about the contents of the next
1472 * blit: The video driver is guaranteeing that all pixels in that
1473 * blit will have the same value as those which already exist at an
1474 * identically-sized region on the same or a different screen.
1475 *
1476 * Note that the source pixels for the COPY in this annotation are
1477 * sampled before applying the anqnotation's associated blit. They
1478 * are allowed to overlap with the blit's destination pixels.
1479 *
1480 * The copy source rectangle is specified the same way as the blit
1481 * destination: it can be a rectangle which spans zero or more
1482 * screens, specified relative to either a screen or to the virtual
1483 * coordinate system's origin. If the source rectangle includes
1484 * pixels which are not from exactly one screen, the results are
1485 * undefined.
1486 *
1487 * Availability:
1488 * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2
1489 */
1490
1491typedef
1492struct {
1493 SVGASignedPoint srcOrigin;
1494 uint32 srcScreenId;
1495} SVGAFifoCmdAnnotationCopy;
1496
1497
1498/*
1499 * SVGA_CMD_DEFINE_GMR2 --
1500 *
1501 * Define guest memory region v2. See the description of GMRs above.
1502 *
1503 * Availability:
1504 * SVGA_CAP_GMR2
1505 */
1506
1507typedef
1508struct {
1509 uint32 gmrId;
1510 uint32 numPages;
1511} SVGAFifoCmdDefineGMR2;
1512
1513
1514/*
1515 * SVGA_CMD_REMAP_GMR2 --
1516 *
1517 * Remap guest memory region v2. See the description of GMRs above.
1518 *
1519 * This command allows guest to modify a portion of an existing GMR by
1520 * invalidating it or reassigning it to different guest physical pages.
1521 * The pages are identified by physical page number (PPN). The pages
1522 * are assumed to be pinned and valid for DMA operations.
1523 *
1524 * Description of command flags:
1525 *
1526 * SVGA_REMAP_GMR2_VIA_GMR: If enabled, references a PPN list in a GMR.
1527 * The PPN list must not overlap with the remap region (this can be
1528 * handled trivially by referencing a separate GMR). If flag is
1529 * disabled, PPN list is appended to SVGARemapGMR command.
1530 *
1531 * SVGA_REMAP_GMR2_PPN64: If set, PPN list is in PPN64 format, otherwise
1532 * it is in PPN32 format.
1533 *
1534 * SVGA_REMAP_GMR2_SINGLE_PPN: If set, PPN list contains a single entry.
1535 * A single PPN can be used to invalidate a portion of a GMR or
1536 * map it to to a single guest scratch page.
1537 *
1538 * Availability:
1539 * SVGA_CAP_GMR2
1540 */
1541
1542typedef enum {
1543 SVGA_REMAP_GMR2_PPN32 = 0,
1544 SVGA_REMAP_GMR2_VIA_GMR = (1 << 0),
1545 SVGA_REMAP_GMR2_PPN64 = (1 << 1),
1546 SVGA_REMAP_GMR2_SINGLE_PPN = (1 << 2),
1547} SVGARemapGMR2Flags;
1548
1549typedef
1550struct {
1551 uint32 gmrId;
1552 SVGARemapGMR2Flags flags;
1553 uint32 offsetPages; /* offset in pages to begin remap */
1554 uint32 numPages; /* number of pages to remap */
1555 /*
1556 * Followed by additional data depending on SVGARemapGMR2Flags.
1557 *
1558 * If flag SVGA_REMAP_GMR2_VIA_GMR is set, single SVGAGuestPtr follows.
1559 * Otherwise an array of page descriptors in PPN32 or PPN64 format
1560 * (according to flag SVGA_REMAP_GMR2_PPN64) follows. If flag
1561 * SVGA_REMAP_GMR2_SINGLE_PPN is set, array contains a single entry.
1562 */
1563} SVGAFifoCmdRemapGMR2;
865 1564
866#endif 1565#endif
diff --git a/src/vmware.c b/src/vmware.c
index fa01dca..9160cf2 100644
--- a/src/vmware.c
+++ b/src/vmware.c
@@ -39,195 +39,17 @@ char rcsId_vmware[] =
39#include "guest_os.h" 39#include "guest_os.h"
40#include "vm_device_version.h" 40#include "vm_device_version.h"
41#include "svga_modes.h" 41#include "svga_modes.h"
42#include "vmware_bootstrap.h"
43#include "vmware_common.h"
42 44
43#ifndef HAVE_XORG_SERVER_1_5_0 45#ifndef HAVE_XORG_SERVER_1_5_0
44#include <xf86_ansic.h> 46#include <xf86_ansic.h>
45#include <xf86_libc.h> 47#include <xf86_libc.h>
46#endif 48#endif
47 49
48#ifdef HaveDriverFuncs 50#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5)
49#define VMWARE_DRIVER_FUNC HaveDriverFuncs
50#else
51#define VMWARE_DRIVER_FUNC 0
52#endif
53
54/*
55 * So that the file compiles unmodified when dropped in to a < 6.9 source tree.
56 */
57#ifndef _X_EXPORT
58#define _X_EXPORT
59#endif
60/*
61 * So that the file compiles unmodified when dropped into an xfree source tree.
62 */
63#ifndef XORG_VERSION_CURRENT
64#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT
65#endif
66
67/*
68 * Sanity check that xf86PciInfo.h has the correct values (which come from
69 * the VMware source tree in vm_device_version.h.
70 */
71#if PCI_CHIP_VMWARE0405 != PCI_DEVICE_ID_VMWARE_SVGA2
72#error "PCI_CHIP_VMWARE0405 is wrong, update it from vm_device_version.h"
73#endif
74#if PCI_CHIP_VMWARE0710 != PCI_DEVICE_ID_VMWARE_SVGA
75#error "PCI_CHIP_VMWARE0710 is wrong, update it from vm_device_version.h"
76#endif
77#if PCI_VENDOR_VMWARE != PCI_VENDOR_ID_VMWARE
78#error "PCI_VENDOR_VMWARE is wrong, update it from vm_device_version.h"
79#endif
80
81#define VMWARE_INCHTOMM 25.4
82
83/*
84 * This is the only way I know to turn a #define of an integer constant into
85 * a constant string.
86 */
87#define VMW_INNERSTRINGIFY(s) #s
88#define VMW_STRING(str) VMW_INNERSTRINGIFY(str)
89
90#define VMWARE_NAME "vmwlegacy"
91#define VMWARE_DRIVER_NAME "vmwlegacy"
92#define VMWARE_DRIVER_VERSION \
93 (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL)
94#define VMWARE_DRIVER_VERSION_STRING \
95 VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \
96 "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL)
97
98static const char VMWAREBuildStr[] = "VMware Guest X Server "
99 VMWARE_DRIVER_VERSION_STRING " - build=$Name$\n";
100
101/*
102 * Standard four digit version string expected by VMware Tools installer.
103 * As the driver's version is only {major, minor, patchlevel},
104 * The fourth digit may describe the commit number relative to the
105 * last version tag as output from `git describe`
106 */
107
108#ifdef __GNUC__
109#ifdef VMW_SUBPATCH
110const char vmwlegacy_drv_modinfo[]
111__attribute__((section(".modinfo"),unused)) =
112 "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH);
113#else
114const char vmwlegacy_drv_modinfo[]
115__attribute__((section(".modinfo"),unused)) =
116 "version=" VMWARE_DRIVER_VERSION_STRING ".0";
117#endif /*VMW_SUBPATCH*/
118#endif
119
120static SymTabRec VMWAREChipsets[] = {
121 { PCI_CHIP_VMWARE0405, "vmware0405" },
122 { PCI_CHIP_VMWARE0710, "vmware0710" },
123 { -1, NULL }
124};
125
126#ifndef XSERVER_LIBPCIACCESS
127static resRange vmwareLegacyRes[] = {
128 { ResExcIoBlock, SVGA_LEGACY_BASE_PORT,
129 SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)},
130 _VGA_EXCLUSIVE, _END
131};
132#else
133#define vmwareLegacyRes NULL
134#endif
135
136#if XSERVER_LIBPCIACCESS
137
138#define VMWARE_DEVICE_MATCH(d, i) \
139 {PCI_VENDOR_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
140
141static const struct pci_id_match VMwareDeviceMatch[] = {
142 VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0405, 0 ),
143 VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0710, 0 ),
144 { 0, 0, 0 },
145};
146#endif
147
148/*
149 * Currently, even the PCI obedient 0405 chip still only obeys IOSE and
150 * MEMSE for the SVGA resources. Thus, RES_EXCLUSIVE_VGA is required.
151 *
152 * The 0710 chip also uses hardcoded IO ports that aren't disablable.
153 */
154
155static PciChipsets VMWAREPciChipsets[] = {
156 { PCI_CHIP_VMWARE0405, PCI_CHIP_VMWARE0405, RES_EXCLUSIVE_VGA },
157 { PCI_CHIP_VMWARE0710, PCI_CHIP_VMWARE0710, vmwareLegacyRes },
158 { -1, -1, RES_UNDEFINED }
159};
160
161#if HAVE_XORG_SERVER_1_7_0
162
163#define xf86LoaderReqSymLists(...) do {} while (0) 51#define xf86LoaderReqSymLists(...) do {} while (0)
164#define LoaderRefSymLists(...) do {} while (0) 52#endif
165
166#else
167
168static const char *vgahwSymbols[] = {
169 "vgaHWGetHWRec",
170 "vgaHWGetIOBase",
171 "vgaHWGetIndex",
172 "vgaHWInit",
173 "vgaHWProtect",
174 "vgaHWRestore",
175 "vgaHWSave",
176 "vgaHWSaveScreen",
177 "vgaHWUnlock",
178 NULL
179};
180
181static const char *fbSymbols[] = {
182 "fbCreateDefColormap",
183 "fbPictureInit",
184 "fbScreenInit",
185 NULL
186};
187
188static const char *ramdacSymbols[] = {
189 "xf86CreateCursorInfoRec",
190 "xf86DestroyCursorInfoRec",
191 "xf86InitCursor",
192 NULL
193};
194
195static const char *shadowfbSymbols[] = {
196 "ShadowFBInit2",
197 NULL
198};
199
200#endif /* HAVE_XORG_SERVER_1_7_0 */
201
202#ifdef XFree86LOADER
203static XF86ModuleVersionInfo vmwlegacyVersRec = {
204 VMWARE_DRIVER_NAME,
205 MODULEVENDORSTRING,
206 MODINFOSTRING1,
207 MODINFOSTRING2,
208 XORG_VERSION_CURRENT,
209 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
210 ABI_CLASS_VIDEODRV,
211 ABI_VIDEODRV_VERSION,
212 MOD_CLASS_VIDEODRV,
213 { 0, 0, 0, 0}
214};
215#endif /* XFree86LOADER */
216
217typedef enum {
218 OPTION_HW_CURSOR,
219 OPTION_XINERAMA,
220 OPTION_STATIC_XINERAMA,
221 OPTION_DEFAULT_MODE,
222} VMWAREOpts;
223
224static const OptionInfoRec VMWAREOptions[] = {
225 { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
226 { OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE },
227 { OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE },
228 { OPTION_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE },
229 { -1, NULL, OPTV_NONE, {0}, FALSE }
230};
231 53
232/* Table of default modes to always add to the mode list. */ 54/* Table of default modes to always add to the mode list. */
233 55
@@ -466,141 +288,6 @@ RewriteTagString(const char *istr, char *ostr, int osize)
466} 288}
467#endif 289#endif
468 290
469static void
470VMWAREIdentify(int flags)
471{
472 xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets);
473}
474
475static const OptionInfoRec *
476VMWAREAvailableOptions(int chipid, int busid)
477{
478 return VMWAREOptions;
479}
480
481static int
482VMWAREParseTopologyElement(ScrnInfoPtr pScrn,
483 unsigned int output,
484 const char *elementName,
485 const char *element,
486 const char *expectedTerminators,
487 Bool needTerminator,
488 unsigned int *outValue)
489{
490 char buf[10] = {0, };
491 size_t i = 0;
492 int retVal = -1;
493 const char *str = element;
494
495 for (i = 0; str[i] >= '0' && str[i] <= '9'; i++);
496 if (i == 0) {
497 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: unable to parse %s.\n",
498 output, elementName);
499 goto exit;
500 }
501
502 strncpy(buf, str, i);
503 *outValue = atoi(buf);
504
505 if (*outValue > (unsigned short)-1) {
506 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %s must be less than %hu.\n",
507 output, elementName, (unsigned short)-1);
508 goto exit;
509 }
510
511 str += i;
512
513 if (needTerminator || str[0] != '\0') {
514 Bool unexpected = TRUE;
515
516 for (i = 0; i < strlen(expectedTerminators); i++) {
517 if (str[0] == expectedTerminators[i]) {
518 unexpected = FALSE;
519 }
520 }
521
522 if (unexpected) {
523 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
524 "Output %u: unexpected character '%c' after %s.\n",
525 output, str[0], elementName);
526 goto exit;
527 } else {
528 str++;
529 }
530 }
531
532 retVal = str - element;
533
534 exit:
535 return retVal;
536}
537
538static xXineramaScreenInfo *
539VMWAREParseTopologyString(ScrnInfoPtr pScrn,
540 const char *topology,
541 unsigned int *retNumOutputs)
542{
543 xXineramaScreenInfo *extents = NULL;
544 unsigned int numOutputs = 0;
545 const char *str = topology;
546
547 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Starting...\n");
548
549 do {
550 unsigned int x, y, width, height;
551 int i;
552
553 i = VMWAREParseTopologyElement(pScrn, numOutputs, "width", str, "xX", TRUE, &width);
554 if (i == -1) {
555 goto error;
556 }
557 str += i;
558
559 i = VMWAREParseTopologyElement(pScrn, numOutputs, "height", str, "+", TRUE, &height);
560 if (i == -1) {
561 goto error;
562 }
563 str += i;
564
565 i= VMWAREParseTopologyElement(pScrn, numOutputs, "X offset", str, "+", TRUE, &x);
566 if (i == -1) {
567 goto error;
568 }
569 str += i;
570
571 i = VMWAREParseTopologyElement(pScrn, numOutputs, "Y offset", str, ";", FALSE, &y);
572 if (i == -1) {
573 goto error;
574 }
575 str += i;
576
577 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %ux%u+%u+%u\n",
578 numOutputs, width, height, x, y);
579
580 numOutputs++;
581 extents = realloc(extents, numOutputs * sizeof (xXineramaScreenInfo));
582 extents[numOutputs - 1].x_org = x;
583 extents[numOutputs - 1].y_org = y;
584 extents[numOutputs - 1].width = width;
585 extents[numOutputs - 1].height = height;
586 } while (*str != 0);
587
588 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Succeeded.\n");
589 goto exit;
590
591 error:
592 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Failed.\n");
593
594 free(extents);
595 extents = NULL;
596 numOutputs = 0;
597
598 exit:
599 *retNumOutputs = numOutputs;
600 return extents;
601}
602
603
604static Bool 291static Bool
605VMWAREPreInit(ScrnInfoPtr pScrn, int flags) 292VMWAREPreInit(ScrnInfoPtr pScrn, int flags)
606{ 293{
@@ -899,18 +586,14 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int flags)
899#endif 586#endif
900 587
901 xf86CollectOptions(pScrn, NULL); 588 xf86CollectOptions(pScrn, NULL);
902 if (!(options = malloc(sizeof(VMWAREOptions)))) 589 if (!(options = VMWARECopyOptions()))
903 return FALSE; 590 return FALSE;
904 memcpy(options, VMWAREOptions, sizeof(VMWAREOptions));
905 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 591 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
906 592
907 if (pScrn->depth <= 8) { 593 if (pScrn->depth <= 8) {
908 pScrn->rgbBits = 8; 594 pScrn->rgbBits = 8;
909 } 595 }
910 596
911 from = X_PROBED;
912 pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets, DEVICE_ID(pVMWARE->PciInfo));
913
914 if (!pScrn->chipset) { 597 if (!pScrn->chipset) {
915 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04x is not recognised\n", DEVICE_ID(pVMWARE->PciInfo)); 598 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04x is not recognised\n", DEVICE_ID(pVMWARE->PciInfo));
916 return FALSE; 599 return FALSE;
@@ -1608,46 +1291,6 @@ vmwareIsRegionEqual(const RegionPtr reg1,
1608 return TRUE; 1291 return TRUE;
1609} 1292}
1610 1293
1611#if VMWARE_DRIVER_FUNC
1612static Bool
1613VMWareDriverFunc(ScrnInfoPtr pScrn,
1614 xorgDriverFuncOp op,
1615 pointer data)
1616{
1617 CARD32 *flag;
1618 xorgRRModeMM *modemm;
1619
1620 switch (op) {
1621 case GET_REQUIRED_HW_INTERFACES:
1622 flag = (CARD32 *)data;
1623
1624 if (flag) {
1625 *flag = HW_IO | HW_MMIO;
1626 }
1627 return TRUE;
1628 case RR_GET_MODE_MM:
1629 modemm = (xorgRRModeMM *)data;
1630
1631 /*
1632 * Because changing the resolution of the guest is usually changing the size
1633 * of a window on the host desktop, the real physical DPI will not change. To
1634 * keep the guest in sync, we scale the 'physical' screen dimensions to
1635 * keep the DPI constant.
1636 */
1637 if (modemm && modemm->mode) {
1638 modemm->mmWidth = (modemm->mode->HDisplay * VMWARE_INCHTOMM +
1639 pScrn->xDpi / 2) / pScrn->xDpi;
1640 modemm->mmHeight = (modemm->mode->VDisplay * VMWARE_INCHTOMM +
1641 pScrn->yDpi / 2) / pScrn->yDpi;
1642 }
1643 return TRUE;
1644 default:
1645 return FALSE;
1646 }
1647}
1648#endif
1649
1650
1651static Bool 1294static Bool
1652VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 1295VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1653{ 1296{
@@ -1663,9 +1306,8 @@ VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1663 1306
1664 1307
1665 xf86CollectOptions(pScrn, NULL); 1308 xf86CollectOptions(pScrn, NULL);
1666 if (!(options = malloc(sizeof(VMWAREOptions)))) 1309 if (!(options = VMWARECopyOptions()))
1667 return FALSE; 1310 return FALSE;
1668 memcpy(options, VMWAREOptions, sizeof(VMWAREOptions));
1669 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); 1311 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
1670 1312
1671 /* 1313 /*
@@ -1680,11 +1322,25 @@ VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1680 } 1322 }
1681 1323
1682 1324
1683 if (useXinerama && xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) { 1325 if (useXinerama && xf86IsOptionSet(options, OPTION_GUI_LAYOUT)) {
1326 char *topology = xf86GetOptValString(options, OPTION_GUI_LAYOUT);
1327 if (topology) {
1328 pVMWARE->xineramaState =
1329 VMWAREParseTopologyString(pScrn, topology,
1330 &pVMWARE->xineramaNumOutputs, "gui");
1331
1332 pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL;
1333
1334 free(topology);
1335 }
1336 } else if (useXinerama &&
1337 xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) {
1684 char *topology = xf86GetOptValString(options, OPTION_STATIC_XINERAMA); 1338 char *topology = xf86GetOptValString(options, OPTION_STATIC_XINERAMA);
1685 if (topology) { 1339 if (topology) {
1686 pVMWARE->xineramaState = 1340 pVMWARE->xineramaState =
1687 VMWAREParseTopologyString(pScrn, topology, &pVMWARE->xineramaNumOutputs); 1341 VMWAREParseTopologyString(pScrn, topology,
1342 &pVMWARE->xineramaNumOutputs,
1343 "static Xinerama");
1688 1344
1689 pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL; 1345 pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL;
1690 1346
@@ -1986,155 +1642,14 @@ VMWAREValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
1986 return MODE_OK; 1642 return MODE_OK;
1987} 1643}
1988 1644
1989#if XSERVER_LIBPCIACCESS 1645void
1990static Bool 1646vmwlegacy_hookup(ScrnInfoPtr pScrn)
1991VMwarePciProbe (DriverPtr drv,
1992 int entity_num,
1993 struct pci_device *device,
1994 intptr_t match_data)
1995{
1996 ScrnInfoPtr scrn = NULL;
1997 EntityInfoPtr entity;
1998
1999 scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets,
2000 NULL, NULL, NULL, NULL, NULL);
2001 if (scrn != NULL) {
2002 scrn->driverVersion = VMWARE_DRIVER_VERSION;
2003 scrn->driverName = VMWARE_DRIVER_NAME;
2004 scrn->name = VMWARE_NAME;
2005 scrn->Probe = NULL;
2006 }
2007
2008 entity = xf86GetEntityInfo(entity_num);
2009 switch (DEVICE_ID(device)) {
2010 case PCI_CHIP_VMWARE0405:
2011 case PCI_CHIP_VMWARE0710:
2012 xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n");
2013 scrn->PreInit = VMWAREPreInit;
2014 scrn->ScreenInit = VMWAREScreenInit;
2015 scrn->SwitchMode = VMWARESwitchMode;
2016 scrn->EnterVT = VMWAREEnterVT;
2017 scrn->LeaveVT = VMWARELeaveVT;
2018 scrn->FreeScreen = VMWAREFreeScreen;
2019 scrn->ValidMode = VMWAREValidMode;
2020 break;
2021 default:
2022 xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n");
2023 }
2024 return scrn != NULL;
2025}
2026#else
2027
2028static Bool
2029VMWAREProbe(DriverPtr drv, int flags)
2030{
2031 int numDevSections, numUsed;
2032 GDevPtr *devSections;
2033 int *usedChips;
2034 int i;
2035 Bool foundScreen = FALSE;
2036 char buildString[sizeof(VMWAREBuildStr)];
2037
2038 RewriteTagString(VMWAREBuildStr, buildString, sizeof(VMWAREBuildStr));
2039 xf86MsgVerb(X_PROBED, 4, "%s", buildString);
2040
2041 numDevSections = xf86MatchDevice(VMWARE_DRIVER_NAME, &devSections);
2042 if (numDevSections <= 0) {
2043#ifdef DEBUG
2044 xf86MsgVerb(X_ERROR, 0, "No vmware driver section\n");
2045#endif
2046 return FALSE;
2047 }
2048 if (xf86GetPciVideoInfo()) {
2049 VmwareLog(("Some PCI Video Info Exists\n"));
2050 numUsed = xf86MatchPciInstances(VMWARE_NAME, PCI_VENDOR_VMWARE,
2051 VMWAREChipsets, VMWAREPciChipsets, devSections,
2052 numDevSections, drv, &usedChips);
2053 free(devSections);
2054 if (numUsed <= 0)
2055 return FALSE;
2056 if (flags & PROBE_DETECT)
2057 foundScreen = TRUE;
2058 else
2059 for (i = 0; i < numUsed; i++) {
2060 ScrnInfoPtr pScrn = NULL;
2061
2062 VmwareLog(("Even some VMware SVGA PCI instances exists\n"));
2063 pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i],
2064 VMWAREPciChipsets, NULL, NULL, NULL,
2065 NULL, NULL);
2066 if (pScrn) {
2067 VmwareLog(("And even configuration suceeded\n"));
2068 pScrn->driverVersion = VMWARE_DRIVER_VERSION;
2069 pScrn->driverName = VMWARE_DRIVER_NAME;
2070 pScrn->name = VMWARE_NAME;
2071 pScrn->Probe = VMWAREProbe;
2072 pScrn->PreInit = VMWAREPreInit;
2073 pScrn->ScreenInit = VMWAREScreenInit;
2074 pScrn->SwitchMode = VMWARESwitchMode;
2075 pScrn->AdjustFrame = VMWAREAdjustFrame;
2076 pScrn->EnterVT = VMWAREEnterVT;
2077 pScrn->LeaveVT = VMWARELeaveVT;
2078 pScrn->FreeScreen = VMWAREFreeScreen;
2079 pScrn->ValidMode = VMWAREValidMode;
2080 foundScreen = TRUE;
2081 }
2082 }
2083 free(usedChips);
2084 }
2085 return foundScreen;
2086}
2087#endif
2088
2089
2090_X_EXPORT DriverRec vmwlegacy = {
2091 VMWARE_DRIVER_VERSION,
2092 VMWARE_DRIVER_NAME,
2093 VMWAREIdentify,
2094#if XSERVER_LIBPCIACCESS
2095 NULL,
2096#else
2097 VMWAREProbe,
2098#endif
2099 VMWAREAvailableOptions,
2100 NULL,
2101 0,
2102#if VMWARE_DRIVER_FUNC
2103 VMWareDriverFunc,
2104#endif
2105#if XSERVER_LIBPCIACCESS
2106 VMwareDeviceMatch,
2107 VMwarePciProbe,
2108#endif
2109};
2110
2111#ifdef XFree86LOADER
2112static MODULESETUPPROTO(vmwlegacySetup);
2113
2114_X_EXPORT XF86ModuleData vmwlegacyModuleData = {
2115 &vmwlegacyVersRec,
2116 vmwlegacySetup,
2117 NULL
2118};
2119
2120static pointer
2121vmwlegacySetup(pointer module, pointer opts, int *errmaj, int *errmin)
2122{ 1647{
2123 static Bool setupDone = FALSE; 1648 pScrn->PreInit = VMWAREPreInit;
2124 1649 pScrn->ScreenInit = VMWAREScreenInit;
2125 if (!setupDone) { 1650 pScrn->SwitchMode = VMWARESwitchMode;
2126 setupDone = TRUE; 1651 pScrn->EnterVT = VMWAREEnterVT;
2127 1652 pScrn->LeaveVT = VMWARELeaveVT;
2128 xf86AddDriver(&vmwlegacy, module, VMWARE_DRIVER_FUNC); 1653 pScrn->FreeScreen = VMWAREFreeScreen;
2129 1654 pScrn->ValidMode = VMWAREValidMode;
2130 LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols,
2131 shadowfbSymbols, NULL);
2132
2133 return (pointer)1;
2134 }
2135 if (errmaj) {
2136 *errmaj = LDR_ONCEONLY;
2137 }
2138 return NULL;
2139} 1655}
2140#endif /* XFree86LOADER */
diff --git a/src/vmware_bootstrap.c b/src/vmware_bootstrap.c
new file mode 100644
index 0000000..522fec0
--- /dev/null
+++ b/src/vmware_bootstrap.c
@@ -0,0 +1,503 @@
1/*
2 * Copyright 2011 VMWare, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Unknown at vmware
26 * Author: Thomas Hellstrom <thellstrom@vmware.com>
27 */
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "xf86.h"
33#include "compiler.h"
34#include "xf86PciInfo.h" /* pci vendor id */
35#include "xf86Pci.h" /* pci */
36#include "vm_device_version.h"
37#include "vmware_bootstrap.h"
38
39#ifndef HAVE_XORG_SERVER_1_5_0
40#include <xf86_ansic.h>
41#include <xf86_libc.h>
42#endif
43
44#ifdef HaveDriverFuncs
45#define VMWARE_DRIVER_FUNC HaveDriverFuncs
46#else
47#define VMWARE_DRIVER_FUNC 0
48#endif
49
50/*
51 * So that the file compiles unmodified when dropped in to a < 6.9 source tree.
52 */
53#ifndef _X_EXPORT
54#define _X_EXPORT
55#endif
56/*
57 * So that the file compiles unmodified when dropped into an xfree source tree.
58 */
59#ifndef XORG_VERSION_CURRENT
60#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT
61#endif
62
63/*
64 * Sanity check that xf86PciInfo.h has the correct values (which come from
65 * the VMware source tree in vm_device_version.h.
66 */
67#if PCI_CHIP_VMWARE0405 != PCI_DEVICE_ID_VMWARE_SVGA2
68#error "PCI_CHIP_VMWARE0405 is wrong, update it from vm_device_version.h"
69#endif
70#if PCI_CHIP_VMWARE0710 != PCI_DEVICE_ID_VMWARE_SVGA
71#error "PCI_CHIP_VMWARE0710 is wrong, update it from vm_device_version.h"
72#endif
73#if PCI_VENDOR_VMWARE != PCI_VENDOR_ID_VMWARE
74#error "PCI_VENDOR_VMWARE is wrong, update it from vm_device_version.h"
75#endif
76
77/*
78 * This is the only way I know to turn a #define of an integer constant into
79 * a constant string.
80 */
81#define VMW_INNERSTRINGIFY(s) #s
82#define VMW_STRING(str) VMW_INNERSTRINGIFY(str)
83
84#define VMWARE_NAME "vmware"
85#define VMWARE_DRIVER_NAME "vmware"
86#define VMWARE_DRIVER_VERSION \
87 (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL)
88#define VMWARE_DRIVER_VERSION_STRING \
89 VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \
90 "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL)
91
92static const char VMWAREBuildStr[] = "VMware Guest X Server "
93 VMWARE_DRIVER_VERSION_STRING " - build=$Name$\n";
94
95/*
96 * Standard four digit version string expected by VMware Tools installer.
97 * As the driver's version is only {major, minor, patchlevel},
98 * The fourth digit may describe the commit number relative to the
99 * last version tag as output from `git describe`
100 */
101
102#ifdef __GNUC__
103#ifdef VMW_SUBPATCH
104const char vmware_drv_modinfo[]
105__attribute__((section(".modinfo"),unused)) =
106 "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH);
107#else
108const char vmware_drv_modinfo[]
109__attribute__((section(".modinfo"),unused)) =
110 "version=" VMWARE_DRIVER_VERSION_STRING ".0";
111#endif /*VMW_SUBPATCH*/
112#endif
113
114#ifndef XSERVER_LIBPCIACCESS
115static resRange vmwareLegacyRes[] = {
116 { ResExcIoBlock, SVGA_LEGACY_BASE_PORT,
117 SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)},
118 _VGA_EXCLUSIVE, _END
119};
120#else
121#define vmwareLegacyRes NULL
122#endif
123
124#if XSERVER_LIBPCIACCESS
125#define VENDOR_ID(p) (p)->vendor_id
126#define DEVICE_ID(p) (p)->device_id
127#define SUBVENDOR_ID(p) (p)->subvendor_id
128#define SUBSYS_ID(p) (p)->subdevice_id
129#define CHIP_REVISION(p) (p)->revision
130#else
131#define VENDOR_ID(p) (p)->vendor
132#define DEVICE_ID(p) (p)->chipType
133#define SUBVENDOR_ID(p) (p)->subsysVendor
134#define SUBSYS_ID(p) (p)->subsysCard
135#define CHIP_REVISION(p) (p)->chipRev
136#endif
137
138#if XSERVER_LIBPCIACCESS
139
140#define VMWARE_DEVICE_MATCH(d, i) \
141 {PCI_VENDOR_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
142
143static const struct pci_id_match VMwareDeviceMatch[] = {
144 VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0405, 0 ),
145 VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0710, 0 ),
146 { 0, 0, 0 },
147};
148#endif
149
150/*
151 * Currently, even the PCI obedient 0405 chip still only obeys IOSE and
152 * MEMSE for the SVGA resources. Thus, RES_EXCLUSIVE_VGA is required.
153 *
154 * The 0710 chip also uses hardcoded IO ports that aren't disablable.
155 */
156
157static PciChipsets VMWAREPciChipsets[] = {
158 { PCI_CHIP_VMWARE0405, PCI_CHIP_VMWARE0405, RES_EXCLUSIVE_VGA },
159 { PCI_CHIP_VMWARE0710, PCI_CHIP_VMWARE0710, vmwareLegacyRes },
160 { -1, -1, RES_UNDEFINED }
161};
162
163static SymTabRec VMWAREChipsets[] = {
164 { PCI_CHIP_VMWARE0405, "vmware0405" },
165 { PCI_CHIP_VMWARE0710, "vmware0710" },
166 { -1, NULL }
167};
168
169#ifdef XFree86LOADER
170static XF86ModuleVersionInfo vmwareVersRec = {
171 VMWARE_DRIVER_NAME,
172 MODULEVENDORSTRING,
173 MODINFOSTRING1,
174 MODINFOSTRING2,
175 XORG_VERSION_CURRENT,
176 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
177 ABI_CLASS_VIDEODRV,
178 ABI_VIDEODRV_VERSION,
179 MOD_CLASS_VIDEODRV,
180 { 0, 0, 0, 0}
181};
182#endif /* XFree86LOADER */
183
184static const OptionInfoRec VMWAREOptions[] = {
185 { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
186 { OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE },
187 { OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE },
188 { OPTION_GUI_LAYOUT, "GuiLayout", OPTV_STRING, {0}, FALSE },
189 { OPTION_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE },
190 { OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE},
191 { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE},
192 { OPTION_DIRECT_PRESENTS, "DirectPresents", OPTV_BOOLEAN, {0}, FALSE},
193 { OPTION_HW_PRESENTS, "HWPresents", OPTV_BOOLEAN, {0}, FALSE},
194 { OPTION_RENDERCHECK, "RenderCheck", OPTV_BOOLEAN, {0}, FALSE},
195 { -1, NULL, OPTV_NONE, {0}, FALSE }
196};
197
198OptionInfoPtr VMWARECopyOptions(void)
199{
200 OptionInfoPtr options;
201 if (!(options = malloc(sizeof(VMWAREOptions))))
202 return NULL;
203
204 memcpy(options, VMWAREOptions, sizeof(VMWAREOptions));
205 return options;
206}
207
208static Bool
209VMwarePreinitStub(ScrnInfoPtr pScrn, int flags)
210{
211#if XSERVER_LIBPCIACCESS
212 struct pci_device *pciInfo;
213#else
214 pciVideoPtr pciInfo;
215#endif /* XSERVER_LIBPCIACCESS */
216 EntityInfoPtr pEnt;
217
218 pScrn->PreInit = pScrn->driverPrivate;
219
220#ifdef BUILD_VMWGFX
221 pScrn->driverPrivate = NULL;
222
223 /*
224 * Try vmwgfx path.
225 */
226 if ((*pScrn->PreInit)(pScrn, flags))
227 return TRUE;
228
229#else
230 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
231 "Driver was compiled without KMS- and 3D support.\n");
232#endif /* defined(BUILD_VMWGFX) */
233 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
234 "Disabling 3D support.\n");
235 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
236 "Disabling Render Acceleration.\n");
237 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
238 "Disabling RandR12+ support.\n");
239
240 pScrn->driverPrivate = NULL;
241 vmwlegacy_hookup(pScrn);
242
243 pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
244 if (pEnt->location.type != BUS_PCI)
245 return FALSE;
246
247 pciInfo = xf86GetPciInfoForEntity(pEnt->index);
248 if (pciInfo == NULL)
249 return FALSE;
250
251 pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets,
252 DEVICE_ID(pciInfo));
253
254 return (*pScrn->PreInit)(pScrn, flags);
255};
256
257#if XSERVER_LIBPCIACCESS
258static Bool
259VMwarePciProbe (DriverPtr drv,
260 int entity_num,
261 struct pci_device *device,
262 intptr_t match_data)
263{
264 ScrnInfoPtr scrn = NULL;
265 EntityInfoPtr entity;
266
267 scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets,
268 NULL, NULL, NULL, NULL, NULL);
269 if (scrn != NULL) {
270 scrn->driverVersion = VMWARE_DRIVER_VERSION;
271 scrn->driverName = VMWARE_DRIVER_NAME;
272 scrn->name = VMWARE_NAME;
273 scrn->Probe = NULL;
274 }
275
276 entity = xf86GetEntityInfo(entity_num);
277 switch (DEVICE_ID(device)) {
278 case PCI_CHIP_VMWARE0405:
279 case PCI_CHIP_VMWARE0710:
280 xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n");
281
282#ifdef BUILD_VMWGFX
283 vmwgfx_hookup(scrn);
284#else
285 vmwlegacy_hookup(scrn);
286#endif /* defined(BUILD_VMWGFX) */
287
288 scrn->driverPrivate = scrn->PreInit;
289 scrn->PreInit = VMwarePreinitStub;
290 break;
291 default:
292 xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n");
293 }
294 return scrn != NULL;
295}
296#else
297
298static Bool
299VMWAREProbe(DriverPtr drv, int flags)
300{
301 int numDevSections, numUsed;
302 GDevPtr *devSections;
303 int *usedChips;
304 int i;
305 Bool foundScreen = FALSE;
306 char buildString[sizeof(VMWAREBuildStr)];
307
308 RewriteTagString(VMWAREBuildStr, buildString, sizeof(VMWAREBuildStr));
309 xf86MsgVerb(X_PROBED, 4, "%s", buildString);
310
311 numDevSections = xf86MatchDevice(VMWARE_DRIVER_NAME, &devSections);
312 if (numDevSections <= 0) {
313#ifdef DEBUG
314 xf86MsgVerb(X_ERROR, 0, "No vmware driver section\n");
315#endif
316 return FALSE;
317 }
318 if (xf86GetPciVideoInfo()) {
319 VmwareLog(("Some PCI Video Info Exists\n"));
320 numUsed = xf86MatchPciInstances(VMWARE_NAME, PCI_VENDOR_VMWARE,
321 VMWAREChipsets, VMWAREPciChipsets, devSections,
322 numDevSections, drv, &usedChips);
323 free(devSections);
324 if (numUsed <= 0)
325 return FALSE;
326 if (flags & PROBE_DETECT)
327 foundScreen = TRUE;
328 else
329 for (i = 0; i < numUsed; i++) {
330 ScrnInfoPtr pScrn = NULL;
331
332 VmwareLog(("Even some VMware SVGA PCI instances exists\n"));
333 pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i],
334 VMWAREPciChipsets, NULL, NULL, NULL,
335 NULL, NULL);
336 if (pScrn) {
337 VmwareLog(("And even configuration suceeded\n"));
338 pScrn->driverVersion = VMWARE_DRIVER_VERSION;
339 pScrn->driverName = VMWARE_DRIVER_NAME;
340 pScrn->name = VMWARE_NAME;
341 pScrn->Probe = VMWAREProbe;
342 pScrn->PreInit = VMWAREPreInit;
343
344#ifdef BUILD_VMWGFX
345 vmwgfx_hookup(scrn);
346#else
347 vmwlegacy_hookup(scrn);
348#endif /* defined(BUILD_VMWGFX) */
349
350 scrn->driverPrivate = scrn->PreInit;
351 scrn->PreInit = VMwarePreinitStub;
352 foundScreen = TRUE;
353 }
354 }
355 free(usedChips);
356 }
357 return foundScreen;
358}
359#endif
360
361static void
362VMWAREIdentify(int flags)
363{
364 xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets);
365}
366
367static const OptionInfoRec *
368VMWAREAvailableOptions(int chipid, int busid)
369{
370 return VMWAREOptions;
371}
372
373#if VMWARE_DRIVER_FUNC
374static Bool
375VMWareDriverFunc(ScrnInfoPtr pScrn,
376 xorgDriverFuncOp op,
377 pointer data)
378{
379 CARD32 *flag;
380 xorgRRModeMM *modemm;
381
382 switch (op) {
383 case GET_REQUIRED_HW_INTERFACES:
384 flag = (CARD32 *)data;
385
386 if (flag) {
387 *flag = HW_IO | HW_MMIO;
388 }
389 return TRUE;
390 case RR_GET_MODE_MM:
391 modemm = (xorgRRModeMM *)data;
392
393 /*
394 * Because changing the resolution of the guest is usually changing the size
395 * of a window on the host desktop, the real physical DPI will not change. To
396 * keep the guest in sync, we scale the 'physical' screen dimensions to
397 * keep the DPI constant.
398 */
399 if (modemm && modemm->mode) {
400 modemm->mmWidth = (modemm->mode->HDisplay * VMWARE_INCHTOMM +
401 pScrn->xDpi / 2) / pScrn->xDpi;
402 modemm->mmHeight = (modemm->mode->VDisplay * VMWARE_INCHTOMM +
403 pScrn->yDpi / 2) / pScrn->yDpi;
404 }
405 return TRUE;
406 default:
407 return FALSE;
408 }
409}
410#endif
411
412
413_X_EXPORT DriverRec vmware = {
414 VMWARE_DRIVER_VERSION,
415 VMWARE_DRIVER_NAME,
416 VMWAREIdentify,
417#if XSERVER_LIBPCIACCESS
418 NULL,
419#else
420 VMWAREProbe,
421#endif
422 VMWAREAvailableOptions,
423 NULL,
424 0,
425#if VMWARE_DRIVER_FUNC
426 VMWareDriverFunc,
427#endif
428#if XSERVER_LIBPCIACCESS
429 VMwareDeviceMatch,
430 VMwarePciProbe,
431#endif
432};
433
434#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5)
435
436#define xf86LoaderReqSymLists(...) do {} while (0)
437#define LoaderRefSymLists(...) do {} while (0)
438
439#else
440
441const char *vgahwSymbols[] = {
442 "vgaHWGetHWRec",
443 "vgaHWGetIOBase",
444 "vgaHWGetIndex",
445 "vgaHWInit",
446 "vgaHWProtect",
447 "vgaHWRestore",
448 "vgaHWSave",
449 "vgaHWSaveScreen",
450 "vgaHWUnlock",
451 NULL
452};
453
454static const char *fbSymbols[] = {
455 "fbCreateDefColormap",
456 "fbPictureInit",
457 "fbScreenInit",
458 NULL
459};
460
461static const char *ramdacSymbols[] = {
462 "xf86CreateCursorInfoRec",
463 "xf86DestroyCursorInfoRec",
464 "xf86InitCursor",
465 NULL
466};
467
468static const char *shadowfbSymbols[] = {
469 "ShadowFBInit2",
470 NULL
471};
472#endif
473
474#ifdef XFree86LOADER
475static MODULESETUPPROTO(vmwareSetup);
476
477_X_EXPORT XF86ModuleData vmwareModuleData = {
478 &vmwareVersRec,
479 vmwareSetup,
480 NULL
481};
482
483static pointer
484vmwareSetup(pointer module, pointer opts, int *errmaj, int *errmin)
485{
486 static Bool setupDone = FALSE;
487
488 if (!setupDone) {
489 setupDone = TRUE;
490
491 xf86AddDriver(&vmware, module, VMWARE_DRIVER_FUNC);
492
493 LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols,
494 shadowfbSymbols, NULL);
495
496 return (pointer)1;
497 }
498 if (errmaj) {
499 *errmaj = LDR_ONCEONLY;
500 }
501 return NULL;
502}
503#endif /* XFree86LOADER */
diff --git a/src/vmware_bootstrap.h b/src/vmware_bootstrap.h
new file mode 100644
index 0000000..172deb8
--- /dev/null
+++ b/src/vmware_bootstrap.h
@@ -0,0 +1,59 @@
1/*
2 * Copyright 2011 VMWare, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Thomas Hellstrom <thellstrom@vmware.com>
26 */
27#ifndef _VMWARE_BOOTSTRAP_H_
28#define _VMWARE_BOOTSTRAP_H_
29
30#include <xf86.h>
31
32#define VMWARE_INCHTOMM 25.4
33
34typedef enum {
35 OPTION_HW_CURSOR,
36 OPTION_XINERAMA,
37 OPTION_STATIC_XINERAMA,
38 OPTION_GUI_LAYOUT,
39 OPTION_DEFAULT_MODE,
40 OPTION_RENDER_ACCEL,
41 OPTION_DRI,
42 OPTION_DIRECT_PRESENTS,
43 OPTION_HW_PRESENTS,
44 OPTION_RENDERCHECK
45} VMWAREOpts;
46
47OptionInfoPtr VMWARECopyOptions(void);
48const char **vgahwSymbols;
49
50void
51vmwlegacy_hookup(ScrnInfoPtr pScrn);
52
53#ifdef BUILD_VMWGFX
54void
55vmwgfx_hookup(ScrnInfoPtr pScrn);
56#endif /* defined(BUILD_VMWGFX) */
57
58
59#endif
diff --git a/src/vmware_common.c b/src/vmware_common.c
new file mode 100644
index 0000000..6ef7ca6
--- /dev/null
+++ b/src/vmware_common.c
@@ -0,0 +1,163 @@
1/*
2 * Copyright 2011 VMWare, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Unknown at vmware
26 */
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include <xf86.h>
32#include "vmware_common.h"
33
34#ifndef HAVE_XORG_SERVER_1_5_0
35#include <xf86_ansic.h>
36#include <xf86_libc.h>
37#endif
38
39static int
40VMWAREParseTopologyElement(ScrnInfoPtr pScrn,
41 unsigned int output,
42 const char *elementName,
43 const char *element,
44 const char *expectedTerminators,
45 Bool needTerminator,
46 unsigned int *outValue)
47{
48 char buf[10] = {0, };
49 size_t i = 0;
50 int retVal = -1;
51 const char *str = element;
52
53 for (i = 0; str[i] >= '0' && str[i] <= '9'; i++);
54 if (i == 0) {
55 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: unable to parse %s.\n",
56 output, elementName);
57 goto exit;
58 }
59
60 strncpy(buf, str, i);
61 *outValue = atoi(buf);
62
63 if (*outValue > (unsigned short)-1) {
64 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %s must be less than %hu.\n",
65 output, elementName, (unsigned short)-1);
66 goto exit;
67 }
68
69 str += i;
70
71 if (needTerminator || str[0] != '\0') {
72 Bool unexpected = TRUE;
73
74 for (i = 0; i < strlen(expectedTerminators); i++) {
75 if (str[0] == expectedTerminators[i]) {
76 unexpected = FALSE;
77 }
78 }
79
80 if (unexpected) {
81 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
82 "Output %u: unexpected character '%c' after %s.\n",
83 output, str[0], elementName);
84 goto exit;
85 } else {
86 str++;
87 }
88 }
89
90 retVal = str - element;
91
92 exit:
93 return retVal;
94}
95
96xXineramaScreenInfo *
97VMWAREParseTopologyString(ScrnInfoPtr pScrn,
98 const char *topology,
99 unsigned int *retNumOutputs,
100 const char info[])
101{
102 xXineramaScreenInfo *extents = NULL;
103 unsigned int numOutputs = 0;
104 const char *str = topology;
105
106 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Starting...\n",
107 info);
108
109 do {
110 unsigned int x, y, width, height;
111 int i;
112
113 i = VMWAREParseTopologyElement(pScrn, numOutputs, "width", str, "xX", TRUE, &width);
114 if (i == -1) {
115 goto error;
116 }
117 str += i;
118
119 i = VMWAREParseTopologyElement(pScrn, numOutputs, "height", str, "+", TRUE, &height);
120 if (i == -1) {
121 goto error;
122 }
123 str += i;
124
125 i= VMWAREParseTopologyElement(pScrn, numOutputs, "X offset", str, "+", TRUE, &x);
126 if (i == -1) {
127 goto error;
128 }
129 str += i;
130
131 i = VMWAREParseTopologyElement(pScrn, numOutputs, "Y offset", str, ";", FALSE, &y);
132 if (i == -1) {
133 goto error;
134 }
135 str += i;
136
137 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %ux%u+%u+%u\n",
138 numOutputs, width, height, x, y);
139
140 numOutputs++;
141 extents = realloc(extents, numOutputs * sizeof (xXineramaScreenInfo));
142 extents[numOutputs - 1].x_org = x;
143 extents[numOutputs - 1].y_org = y;
144 extents[numOutputs - 1].width = width;
145 extents[numOutputs - 1].height = height;
146 } while (*str != 0);
147
148 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Succeeded.\n",
149 info);
150 goto exit;
151
152 error:
153 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Failed.\n",
154 info);
155
156 free(extents);
157 extents = NULL;
158 numOutputs = 0;
159
160 exit:
161 *retNumOutputs = numOutputs;
162 return extents;
163}
diff --git a/src/vmware_common.h b/src/vmware_common.h
new file mode 100644
index 0000000..9cd7194
--- /dev/null
+++ b/src/vmware_common.h
@@ -0,0 +1,41 @@
1/*
2 * Copyright 2011 VMWare, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Unknown at vmware
26 * Author: Thomas Hellstrom <thellstrom@vmware.com>
27 */
28
29#ifndef _VMWARE_COMMON_H_
30#define _VMWARE_COMMON_H_
31
32#include <X11/extensions/panoramiXproto.h>
33#include <xf86.h>
34
35xXineramaScreenInfo *
36VMWAREParseTopologyString(ScrnInfoPtr pScrn,
37 const char *topology,
38 unsigned int *retNumOutputs,
39 const char info[]);
40
41#endif
diff --git a/src/vmwaremodule.c b/src/vmwaremodule.c
deleted file mode 100644
index 0da2440..0000000
--- a/src/vmwaremodule.c
+++ /dev/null
@@ -1,256 +0,0 @@
1/**********************************************************
2 * Copyright 2010 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#ifdef HAVE_LIBDRM
31#include <xf86drm.h>
32#endif
33
34#include <xorg-server.h>
35#include <xf86.h>
36
37#ifndef HAVE_XORG_SERVER_1_5_0
38#include <xf86_ansic.h>
39#include <xf86_libc.h>
40#endif
41
42/*
43 * Defines and exported module info.
44 */
45
46#define VMWARE_DRIVER_NAME "vmware"
47#define VMWGFX_DRIVER_NAME "vmwgfx"
48#define VMWGFX_MODULE_NAME "vmwgfx"
49#define VMWGFX_COMPAT_MAJOR 11
50#define VMWGFX_REQUIRED_MAJOR 11
51#define VMWGFX_REQUIRED_MINOR 0
52#define VMWLEGACY_DRIVER_NAME "vmwlegacy"
53
54#define VMW_STRING_INNER(s) #s
55#define VMW_STRING(str) VMW_STRING_INNER(str)
56
57#define VMWARE_DRIVER_VERSION \
58 (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL)
59#define VMWARE_DRIVER_VERSION_STRING \
60 VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \
61 "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL)
62
63/*
64 * Standard four digit version string expected by VMware Tools installer.
65 * As the driver's version is only {major, minor, patchlevel},
66 * the fourth digit may describe the commit number relative to the
67 * last version tag as output from `git describe`
68 */
69
70#ifdef __GNUC__
71#ifdef VMW_SUBPATCH
72const char vmware_drv_modinfo[] __attribute__((section(".modinfo"),unused)) =
73 "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH);
74#else
75const char vmware_drv_modinfo[] __attribute__((section(".modinfo"),unused)) =
76 "version=" VMWARE_DRIVER_VERSION_STRING ".0";
77#endif /*VMW_SUBPATCH*/
78#endif
79
80static XF86ModuleVersionInfo vmware_version;
81static MODULESETUPPROTO(vmware_setup);
82
83_X_EXPORT XF86ModuleData vmwareModuleData = {
84 &vmware_version,
85 vmware_setup,
86 NULL
87};
88
89extern XF86ModuleData *VMWGFX_MODULE_DATA;
90
91/*
92 * Chain loading functions
93 */
94
95static Bool
96vmware_check_kernel_module()
97{
98#ifdef HAVE_LIBDRM
99 /* Super simple way of knowing if the kernel driver is loaded */
100 int ret = drmOpen(VMWGFX_MODULE_NAME, NULL);
101 if (ret < 0) {
102 /* This shouldn't go in the log as the original message does not */
103 fprintf(stderr, "%s: Please ignore above \"FATAL: Module %s not found."
104 "\"\n", VMWARE_DRIVER_NAME, VMWGFX_MODULE_NAME);
105 /* This is what goes into the log on the other hand */
106 xf86DrvMsg(-1, X_PROBED, "%s: Please ignore above \"[drm] failed to "
107 "load kernel module \"%s\"\"\n", VMWARE_DRIVER_NAME,
108 VMWGFX_MODULE_NAME);
109 return FALSE;
110 }
111
112 drmClose(ret);
113
114 return TRUE;
115#else
116 return FALSE;
117#endif /* HAVE_LIBDRM */
118}
119
120static Bool
121vmware_check_vmwgfx_driver(int matched, pointer opts)
122{
123#ifdef HAVE_LIBDRM
124 int major; int minor;
125 pointer module;
126 CARD32 version;
127
128 if (matched) {
129 xf86DrvMsg(-1, X_PROBED, "%s: X configured to use %s X driver assume "
130 "who ever did that knows what they are doing\n",
131 VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME);
132 /* Also how did they end up here, if the configured X to use vmwgfx and
133 * X should load that driver for that hardware. And since there is only
134 * one SVGA device this driver shouldn't be loaded. Weird...
135 */
136 return TRUE;
137 }
138
139 module = xf86LoadOneModule(VMWGFX_DRIVER_NAME, opts);
140 if (!module) {
141 xf86DrvMsg(-1, X_ERROR, "%s: Please ignore the above warnings about "
142 "not being able to to load module/driver %s\n",
143 VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME);
144 return FALSE;
145 }
146
147 version = xf86GetModuleVersion(module);
148 major = GET_MODULE_MAJOR_VERSION(version);
149 minor = GET_MODULE_MINOR_VERSION(version);
150
151 if (major > VMWGFX_COMPAT_MAJOR ||
152 major < VMWGFX_REQUIRED_MAJOR ||
153 (major == VMWGFX_REQUIRED_MAJOR && minor < VMWGFX_REQUIRED_MINOR)) {
154 xf86DrvMsg(-1, X_PROBED, "%s: The %s X driver failed version "
155 "checking.\n", VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME);
156 goto err;
157 }
158
159 return TRUE;
160
161err:
162 /* XXX We should drop the reference on the module here */
163#endif /* HAVE_LIBDRM */
164 return FALSE;
165}
166
167static Bool
168vmware_chain_module(pointer opts)
169{
170 int vmwlegacy_devices;
171 int vmwgfx_devices;
172 int vmware_devices;
173 int matched;
174 char *driver_name;
175 GDevPtr *gdevs;
176 GDevPtr gdev;
177 int i;
178
179 vmware_devices = xf86MatchDevice(VMWARE_DRIVER_NAME, &gdevs);
180 vmwgfx_devices = xf86MatchDevice(VMWGFX_DRIVER_NAME, NULL);
181 vmwlegacy_devices = xf86MatchDevice(VMWLEGACY_DRIVER_NAME, NULL);
182
183 if (vmware_check_vmwgfx_driver(vmwgfx_devices, opts) &&
184 vmware_check_kernel_module()) {
185 xf86DrvMsg(-1, X_INFO, "%s: Using %s X driver.\n",
186 VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME);
187 driver_name = VMWGFX_DRIVER_NAME;
188 matched = 1;
189 } else {
190 xf86DrvMsg(-1, X_INFO, "%s: Using %s driver everything is fine.\n",
191 VMWARE_DRIVER_NAME, VMWLEGACY_DRIVER_NAME);
192 driver_name = VMWLEGACY_DRIVER_NAME;
193 matched = vmwlegacy_devices;
194 }
195
196 /* Xorg -configure returns 1 from xf86MatchDevice with NULL gdevs */
197 for (i = 0; gdevs && i < vmware_devices; i++) {
198 gdev = gdevs[i];
199 gdev->driver = driver_name;
200 }
201
202 free(gdevs);
203
204 if (!matched) {
205 if (xf86LoadOneModule(driver_name, opts) == NULL) {
206 xf86DrvMsg(-1, X_ERROR, "%s: Unexpected failure while "
207 "loading the \"%s\" driver. Giving up.\n",
208 VMWARE_DRIVER_NAME, driver_name);
209 return FALSE;
210 }
211 }
212
213 return TRUE;
214}
215
216
217/*
218 * Module info
219 */
220
221static XF86ModuleVersionInfo vmware_version = {
222 VMWARE_DRIVER_NAME,
223 MODULEVENDORSTRING,
224 MODINFOSTRING1,
225 MODINFOSTRING2,
226 XORG_VERSION_CURRENT,
227 PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
228 ABI_CLASS_VIDEODRV,
229 ABI_VIDEODRV_VERSION,
230 MOD_CLASS_VIDEODRV,
231 {0, 0, 0, 0}
232};
233
234static pointer
235vmware_setup(pointer module, pointer opts, int *errmaj, int *errmin)
236{
237 static Bool setupDone = 0;
238
239 /* This module should be loaded only once, but check to be sure. */
240 if (!setupDone) {
241 setupDone = 1;
242
243 /* Chain load the real driver */
244 if (vmware_chain_module(opts))
245 return (pointer) 1;
246 else {
247 if (errmaj)
248 *errmaj = LDR_NOSUBENT;
249 return NULL;
250 }
251 } else {
252 if (errmaj)
253 *errmaj = LDR_ONCEONLY;
254 return NULL;
255 }
256}
diff --git a/vmwgfx/Makefile.am b/vmwgfx/Makefile.am
new file mode 100644
index 0000000..1ee6582
--- /dev/null
+++ b/vmwgfx/Makefile.am
@@ -0,0 +1,26 @@
1noinst_LTLIBRARIES = libvmwgfx.la
2libvmwgfx_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) @LIBDRM_CFLAGS@ @XATRACKER_CFLAGS@ -I$(top_srcdir)/src -I$(top_srcdir)/saa
3libvmwgfx_la_LIBADD = @LIBDRM_LIBS@ $(top_srcdir)/saa/libsaa.la\
4 @XATRACKER_LIBS@
5libvmwgfx_la_DEPENDENCIES = $(top_srcdir)/saa/libsaa.la
6
7libvmwgfx_la_SOURCES = \
8 vmwgfx_driver.c \
9 vmwgfx_driver.h \
10 vmwgfx_crtc.c \
11 vmwgfx_output.c \
12 vmwgfx_dri2.c \
13 vmwgfx_tex_video.c \
14 vmwgfx_saa.c \
15 vmwgfx_saa.h \
16 vmwgfx_drmi.c \
17 vmwgfx_drmi.h \
18 vmwgfx_overlay.c \
19 vmwgfx_ctrl.c \
20 vmwgfx_ctrl.h \
21 vmwgfx_xa_composite.c \
22 vmwgfx_xa_surface.c \
23 wsbm_util.h
24
25
26
diff --git a/vmwgfx/svga3d_reg.h b/vmwgfx/svga3d_reg.h
new file mode 100644
index 0000000..a527d7d
--- /dev/null
+++ b/vmwgfx/svga3d_reg.h
@@ -0,0 +1,1801 @@
1/**********************************************************
2 * Copyright 1998-2009 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26/*
27 * svga3d_reg.h --
28 *
29 * SVGA 3D hardware definitions
30 */
31
32#ifndef _SVGA3D_REG_H_
33#define _SVGA3D_REG_H_
34
35#include "svga_reg.h"
36
37
38/*
39 * 3D Hardware Version
40 *
41 * The hardware version is stored in the SVGA_FIFO_3D_HWVERSION fifo
42 * register. Is set by the host and read by the guest. This lets
43 * us make new guest drivers which are backwards-compatible with old
44 * SVGA hardware revisions. It does not let us support old guest
45 * drivers. Good enough for now.
46 *
47 */
48
49#define SVGA3D_MAKE_HWVERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
50#define SVGA3D_MAJOR_HWVERSION(version) ((version) >> 16)
51#define SVGA3D_MINOR_HWVERSION(version) ((version) & 0xFF)
52
53typedef enum {
54 SVGA3D_HWVERSION_WS5_RC1 = SVGA3D_MAKE_HWVERSION(0, 1),
55 SVGA3D_HWVERSION_WS5_RC2 = SVGA3D_MAKE_HWVERSION(0, 2),
56 SVGA3D_HWVERSION_WS51_RC1 = SVGA3D_MAKE_HWVERSION(0, 3),
57 SVGA3D_HWVERSION_WS6_B1 = SVGA3D_MAKE_HWVERSION(1, 1),
58 SVGA3D_HWVERSION_FUSION_11 = SVGA3D_MAKE_HWVERSION(1, 4),
59 SVGA3D_HWVERSION_WS65_B1 = SVGA3D_MAKE_HWVERSION(2, 0),
60 SVGA3D_HWVERSION_CURRENT = SVGA3D_HWVERSION_WS65_B1,
61} SVGA3dHardwareVersion;
62
63/*
64 * Generic Types
65 */
66
67typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
68#define SVGA3D_NUM_CLIPPLANES 6
69#define SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS 8
70
71
72/*
73 * Surface formats.
74 *
75 * If you modify this list, be sure to keep GLUtil.c in sync. It
76 * includes the internal format definition of each surface in
77 * GLUtil_ConvertSurfaceFormat, and it contains a table of
78 * human-readable names in GLUtil_GetFormatName.
79 */
80
81typedef enum SVGA3dSurfaceFormat {
82 SVGA3D_FORMAT_INVALID = 0,
83
84 SVGA3D_X8R8G8B8 = 1,
85 SVGA3D_A8R8G8B8 = 2,
86
87 SVGA3D_R5G6B5 = 3,
88 SVGA3D_X1R5G5B5 = 4,
89 SVGA3D_A1R5G5B5 = 5,
90 SVGA3D_A4R4G4B4 = 6,
91
92 SVGA3D_Z_D32 = 7,
93 SVGA3D_Z_D16 = 8,
94 SVGA3D_Z_D24S8 = 9,
95 SVGA3D_Z_D15S1 = 10,
96
97 SVGA3D_LUMINANCE8 = 11,
98 SVGA3D_LUMINANCE4_ALPHA4 = 12,
99 SVGA3D_LUMINANCE16 = 13,
100 SVGA3D_LUMINANCE8_ALPHA8 = 14,
101
102 SVGA3D_DXT1 = 15,
103 SVGA3D_DXT2 = 16,
104 SVGA3D_DXT3 = 17,
105 SVGA3D_DXT4 = 18,
106 SVGA3D_DXT5 = 19,
107
108 SVGA3D_BUMPU8V8 = 20,
109 SVGA3D_BUMPL6V5U5 = 21,
110 SVGA3D_BUMPX8L8V8U8 = 22,
111 SVGA3D_BUMPL8V8U8 = 23,
112
113 SVGA3D_ARGB_S10E5 = 24, /* 16-bit floating-point ARGB */
114 SVGA3D_ARGB_S23E8 = 25, /* 32-bit floating-point ARGB */
115
116 SVGA3D_A2R10G10B10 = 26,
117
118 /* signed formats */
119 SVGA3D_V8U8 = 27,
120 SVGA3D_Q8W8V8U8 = 28,
121 SVGA3D_CxV8U8 = 29,
122
123 /* mixed formats */
124 SVGA3D_X8L8V8U8 = 30,
125 SVGA3D_A2W10V10U10 = 31,
126
127 SVGA3D_ALPHA8 = 32,
128
129 /* Single- and dual-component floating point formats */
130 SVGA3D_R_S10E5 = 33,
131 SVGA3D_R_S23E8 = 34,
132 SVGA3D_RG_S10E5 = 35,
133 SVGA3D_RG_S23E8 = 36,
134
135 /*
136 * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
137 * the most efficient format to use when creating new surfaces
138 * expressly for index or vertex data.
139 */
140 SVGA3D_BUFFER = 37,
141
142 SVGA3D_Z_D24X8 = 38,
143
144 SVGA3D_V16U16 = 39,
145
146 SVGA3D_G16R16 = 40,
147 SVGA3D_A16B16G16R16 = 41,
148
149 /* Packed Video formats */
150 SVGA3D_UYVY = 42,
151 SVGA3D_YUY2 = 43,
152
153 SVGA3D_FORMAT_MAX
154} SVGA3dSurfaceFormat;
155
156typedef uint32 SVGA3dColor; /* a, r, g, b */
157
158/*
159 * These match the D3DFORMAT_OP definitions used by Direct3D. We need
160 * them so that we can query the host for what the supported surface
161 * operations are (when we're using the D3D backend, in particular),
162 * and so we can send those operations to the guest.
163 */
164typedef enum {
165 SVGA3DFORMAT_OP_TEXTURE = 0x00000001,
166 SVGA3DFORMAT_OP_VOLUMETEXTURE = 0x00000002,
167 SVGA3DFORMAT_OP_CUBETEXTURE = 0x00000004,
168 SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET = 0x00000008,
169 SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET = 0x00000010,
170 SVGA3DFORMAT_OP_ZSTENCIL = 0x00000040,
171 SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH = 0x00000080,
172
173/*
174 * This format can be used as a render target if the current display mode
175 * is the same depth if the alpha channel is ignored. e.g. if the device
176 * can render to A8R8G8B8 when the display mode is X8R8G8B8, then the
177 * format op list entry for A8R8G8B8 should have this cap.
178 */
179 SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET = 0x00000100,
180
181/*
182 * This format contains DirectDraw support (including Flip). This flag
183 * should not to be set on alpha formats.
184 */
185 SVGA3DFORMAT_OP_DISPLAYMODE = 0x00000400,
186
187/*
188 * The rasterizer can support some level of Direct3D support in this format
189 * and implies that the driver can create a Context in this mode (for some
190 * render target format). When this flag is set, the SVGA3DFORMAT_OP_DISPLAYMODE
191 * flag must also be set.
192 */
193 SVGA3DFORMAT_OP_3DACCELERATION = 0x00000800,
194
195/*
196 * This is set for a private format when the driver has put the bpp in
197 * the structure.
198 */
199 SVGA3DFORMAT_OP_PIXELSIZE = 0x00001000,
200
201/*
202 * Indicates that this format can be converted to any RGB format for which
203 * SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB is specified
204 */
205 SVGA3DFORMAT_OP_CONVERT_TO_ARGB = 0x00002000,
206
207/*
208 * Indicates that this format can be used to create offscreen plain surfaces.
209 */
210 SVGA3DFORMAT_OP_OFFSCREENPLAIN = 0x00004000,
211
212/*
213 * Indicated that this format can be read as an SRGB texture (meaning that the
214 * sampler will linearize the looked up data)
215 */
216 SVGA3DFORMAT_OP_SRGBREAD = 0x00008000,
217
218/*
219 * Indicates that this format can be used in the bumpmap instructions
220 */
221 SVGA3DFORMAT_OP_BUMPMAP = 0x00010000,
222
223/*
224 * Indicates that this format can be sampled by the displacement map sampler
225 */
226 SVGA3DFORMAT_OP_DMAP = 0x00020000,
227
228/*
229 * Indicates that this format cannot be used with texture filtering
230 */
231 SVGA3DFORMAT_OP_NOFILTER = 0x00040000,
232
233/*
234 * Indicates that format conversions are supported to this RGB format if
235 * SVGA3DFORMAT_OP_CONVERT_TO_ARGB is specified in the source format.
236 */
237 SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB = 0x00080000,
238
239/*
240 * Indicated that this format can be written as an SRGB target (meaning that the
241 * pixel pipe will DE-linearize data on output to format)
242 */
243 SVGA3DFORMAT_OP_SRGBWRITE = 0x00100000,
244
245/*
246 * Indicates that this format cannot be used with alpha blending
247 */
248 SVGA3DFORMAT_OP_NOALPHABLEND = 0x00200000,
249
250/*
251 * Indicates that the device can auto-generated sublevels for resources
252 * of this format
253 */
254 SVGA3DFORMAT_OP_AUTOGENMIPMAP = 0x00400000,
255
256/*
257 * Indicates that this format can be used by vertex texture sampler
258 */
259 SVGA3DFORMAT_OP_VERTEXTEXTURE = 0x00800000,
260
261/*
262 * Indicates that this format supports neither texture coordinate wrap
263 * modes, nor mipmapping
264 */
265 SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP = 0x01000000
266} SVGA3dFormatOp;
267
268/*
269 * This structure is a conversion of SVGA3DFORMAT_OP_*.
270 * Entries must be located at the same position.
271 */
272typedef union {
273 uint32 value;
274 struct {
275 uint32 texture : 1;
276 uint32 volumeTexture : 1;
277 uint32 cubeTexture : 1;
278 uint32 offscreenRenderTarget : 1;
279 uint32 sameFormatRenderTarget : 1;
280 uint32 unknown1 : 1;
281 uint32 zStencil : 1;
282 uint32 zStencilArbitraryDepth : 1;
283 uint32 sameFormatUpToAlpha : 1;
284 uint32 unknown2 : 1;
285 uint32 displayMode : 1;
286 uint32 acceleration3d : 1;
287 uint32 pixelSize : 1;
288 uint32 convertToARGB : 1;
289 uint32 offscreenPlain : 1;
290 uint32 sRGBRead : 1;
291 uint32 bumpMap : 1;
292 uint32 dmap : 1;
293 uint32 noFilter : 1;
294 uint32 memberOfGroupARGB : 1;
295 uint32 sRGBWrite : 1;
296 uint32 noAlphaBlend : 1;
297 uint32 autoGenMipMap : 1;
298 uint32 vertexTexture : 1;
299 uint32 noTexCoordWrapNorMip : 1;
300 };
301} SVGA3dSurfaceFormatCaps;
302
303/*
304 * SVGA_3D_CMD_SETRENDERSTATE Types. All value types
305 * must fit in a uint32.
306 */
307
308typedef enum {
309 SVGA3D_RS_INVALID = 0,
310 SVGA3D_RS_ZENABLE = 1, /* SVGA3dBool */
311 SVGA3D_RS_ZWRITEENABLE = 2, /* SVGA3dBool */
312 SVGA3D_RS_ALPHATESTENABLE = 3, /* SVGA3dBool */
313 SVGA3D_RS_DITHERENABLE = 4, /* SVGA3dBool */
314 SVGA3D_RS_BLENDENABLE = 5, /* SVGA3dBool */
315 SVGA3D_RS_FOGENABLE = 6, /* SVGA3dBool */
316 SVGA3D_RS_SPECULARENABLE = 7, /* SVGA3dBool */
317 SVGA3D_RS_STENCILENABLE = 8, /* SVGA3dBool */
318 SVGA3D_RS_LIGHTINGENABLE = 9, /* SVGA3dBool */
319 SVGA3D_RS_NORMALIZENORMALS = 10, /* SVGA3dBool */
320 SVGA3D_RS_POINTSPRITEENABLE = 11, /* SVGA3dBool */
321 SVGA3D_RS_POINTSCALEENABLE = 12, /* SVGA3dBool */
322 SVGA3D_RS_STENCILREF = 13, /* uint32 */
323 SVGA3D_RS_STENCILMASK = 14, /* uint32 */
324 SVGA3D_RS_STENCILWRITEMASK = 15, /* uint32 */
325 SVGA3D_RS_FOGSTART = 16, /* float */
326 SVGA3D_RS_FOGEND = 17, /* float */
327 SVGA3D_RS_FOGDENSITY = 18, /* float */
328 SVGA3D_RS_POINTSIZE = 19, /* float */
329 SVGA3D_RS_POINTSIZEMIN = 20, /* float */
330 SVGA3D_RS_POINTSIZEMAX = 21, /* float */
331 SVGA3D_RS_POINTSCALE_A = 22, /* float */
332 SVGA3D_RS_POINTSCALE_B = 23, /* float */
333 SVGA3D_RS_POINTSCALE_C = 24, /* float */
334 SVGA3D_RS_FOGCOLOR = 25, /* SVGA3dColor */
335 SVGA3D_RS_AMBIENT = 26, /* SVGA3dColor */
336 SVGA3D_RS_CLIPPLANEENABLE = 27, /* SVGA3dClipPlanes */
337 SVGA3D_RS_FOGMODE = 28, /* SVGA3dFogMode */
338 SVGA3D_RS_FILLMODE = 29, /* SVGA3dFillMode */
339 SVGA3D_RS_SHADEMODE = 30, /* SVGA3dShadeMode */
340 SVGA3D_RS_LINEPATTERN = 31, /* SVGA3dLinePattern */
341 SVGA3D_RS_SRCBLEND = 32, /* SVGA3dBlendOp */
342 SVGA3D_RS_DSTBLEND = 33, /* SVGA3dBlendOp */
343 SVGA3D_RS_BLENDEQUATION = 34, /* SVGA3dBlendEquation */
344 SVGA3D_RS_CULLMODE = 35, /* SVGA3dFace */
345 SVGA3D_RS_ZFUNC = 36, /* SVGA3dCmpFunc */
346 SVGA3D_RS_ALPHAFUNC = 37, /* SVGA3dCmpFunc */
347 SVGA3D_RS_STENCILFUNC = 38, /* SVGA3dCmpFunc */
348 SVGA3D_RS_STENCILFAIL = 39, /* SVGA3dStencilOp */
349 SVGA3D_RS_STENCILZFAIL = 40, /* SVGA3dStencilOp */
350 SVGA3D_RS_STENCILPASS = 41, /* SVGA3dStencilOp */
351 SVGA3D_RS_ALPHAREF = 42, /* float (0.0 .. 1.0) */
352 SVGA3D_RS_FRONTWINDING = 43, /* SVGA3dFrontWinding */
353 SVGA3D_RS_COORDINATETYPE = 44, /* SVGA3dCoordinateType */
354 SVGA3D_RS_ZBIAS = 45, /* float */
355 SVGA3D_RS_RANGEFOGENABLE = 46, /* SVGA3dBool */
356 SVGA3D_RS_COLORWRITEENABLE = 47, /* SVGA3dColorMask */
357 SVGA3D_RS_VERTEXMATERIALENABLE = 48, /* SVGA3dBool */
358 SVGA3D_RS_DIFFUSEMATERIALSOURCE = 49, /* SVGA3dVertexMaterial */
359 SVGA3D_RS_SPECULARMATERIALSOURCE = 50, /* SVGA3dVertexMaterial */
360 SVGA3D_RS_AMBIENTMATERIALSOURCE = 51, /* SVGA3dVertexMaterial */
361 SVGA3D_RS_EMISSIVEMATERIALSOURCE = 52, /* SVGA3dVertexMaterial */
362 SVGA3D_RS_TEXTUREFACTOR = 53, /* SVGA3dColor */
363 SVGA3D_RS_LOCALVIEWER = 54, /* SVGA3dBool */
364 SVGA3D_RS_SCISSORTESTENABLE = 55, /* SVGA3dBool */
365 SVGA3D_RS_BLENDCOLOR = 56, /* SVGA3dColor */
366 SVGA3D_RS_STENCILENABLE2SIDED = 57, /* SVGA3dBool */
367 SVGA3D_RS_CCWSTENCILFUNC = 58, /* SVGA3dCmpFunc */
368 SVGA3D_RS_CCWSTENCILFAIL = 59, /* SVGA3dStencilOp */
369 SVGA3D_RS_CCWSTENCILZFAIL = 60, /* SVGA3dStencilOp */
370 SVGA3D_RS_CCWSTENCILPASS = 61, /* SVGA3dStencilOp */
371 SVGA3D_RS_VERTEXBLEND = 62, /* SVGA3dVertexBlendFlags */
372 SVGA3D_RS_SLOPESCALEDEPTHBIAS = 63, /* float */
373 SVGA3D_RS_DEPTHBIAS = 64, /* float */
374
375
376 /*
377 * Output Gamma Level
378 *
379 * Output gamma effects the gamma curve of colors that are output from the
380 * rendering pipeline. A value of 1.0 specifies a linear color space. If the
381 * value is <= 0.0, gamma correction is ignored and linear color space is
382 * used.
383 */
384
385 SVGA3D_RS_OUTPUTGAMMA = 65, /* float */
386 SVGA3D_RS_ZVISIBLE = 66, /* SVGA3dBool */
387 SVGA3D_RS_LASTPIXEL = 67, /* SVGA3dBool */
388 SVGA3D_RS_CLIPPING = 68, /* SVGA3dBool */
389 SVGA3D_RS_WRAP0 = 69, /* SVGA3dWrapFlags */
390 SVGA3D_RS_WRAP1 = 70, /* SVGA3dWrapFlags */
391 SVGA3D_RS_WRAP2 = 71, /* SVGA3dWrapFlags */
392 SVGA3D_RS_WRAP3 = 72, /* SVGA3dWrapFlags */
393 SVGA3D_RS_WRAP4 = 73, /* SVGA3dWrapFlags */
394 SVGA3D_RS_WRAP5 = 74, /* SVGA3dWrapFlags */
395 SVGA3D_RS_WRAP6 = 75, /* SVGA3dWrapFlags */
396 SVGA3D_RS_WRAP7 = 76, /* SVGA3dWrapFlags */
397 SVGA3D_RS_WRAP8 = 77, /* SVGA3dWrapFlags */
398 SVGA3D_RS_WRAP9 = 78, /* SVGA3dWrapFlags */
399 SVGA3D_RS_WRAP10 = 79, /* SVGA3dWrapFlags */
400 SVGA3D_RS_WRAP11 = 80, /* SVGA3dWrapFlags */
401 SVGA3D_RS_WRAP12 = 81, /* SVGA3dWrapFlags */
402 SVGA3D_RS_WRAP13 = 82, /* SVGA3dWrapFlags */
403 SVGA3D_RS_WRAP14 = 83, /* SVGA3dWrapFlags */
404 SVGA3D_RS_WRAP15 = 84, /* SVGA3dWrapFlags */
405 SVGA3D_RS_MULTISAMPLEANTIALIAS = 85, /* SVGA3dBool */
406 SVGA3D_RS_MULTISAMPLEMASK = 86, /* uint32 */
407 SVGA3D_RS_INDEXEDVERTEXBLENDENABLE = 87, /* SVGA3dBool */
408 SVGA3D_RS_TWEENFACTOR = 88, /* float */
409 SVGA3D_RS_ANTIALIASEDLINEENABLE = 89, /* SVGA3dBool */
410 SVGA3D_RS_COLORWRITEENABLE1 = 90, /* SVGA3dColorMask */
411 SVGA3D_RS_COLORWRITEENABLE2 = 91, /* SVGA3dColorMask */
412 SVGA3D_RS_COLORWRITEENABLE3 = 92, /* SVGA3dColorMask */
413 SVGA3D_RS_SEPARATEALPHABLENDENABLE = 93, /* SVGA3dBool */
414 SVGA3D_RS_SRCBLENDALPHA = 94, /* SVGA3dBlendOp */
415 SVGA3D_RS_DSTBLENDALPHA = 95, /* SVGA3dBlendOp */
416 SVGA3D_RS_BLENDEQUATIONALPHA = 96, /* SVGA3dBlendEquation */
417 SVGA3D_RS_MAX
418} SVGA3dRenderStateName;
419
420typedef enum {
421 SVGA3D_VERTEXMATERIAL_NONE = 0, /* Use the value in the current material */
422 SVGA3D_VERTEXMATERIAL_DIFFUSE = 1, /* Use the value in the diffuse component */
423 SVGA3D_VERTEXMATERIAL_SPECULAR = 2, /* Use the value in the specular component */
424} SVGA3dVertexMaterial;
425
426typedef enum {
427 SVGA3D_FILLMODE_INVALID = 0,
428 SVGA3D_FILLMODE_POINT = 1,
429 SVGA3D_FILLMODE_LINE = 2,
430 SVGA3D_FILLMODE_FILL = 3,
431 SVGA3D_FILLMODE_MAX
432} SVGA3dFillModeType;
433
434
435typedef
436union {
437 struct {
438 uint16 mode; /* SVGA3dFillModeType */
439 uint16 face; /* SVGA3dFace */
440 };
441 uint32 uintValue;
442} SVGA3dFillMode;
443
444typedef enum {
445 SVGA3D_SHADEMODE_INVALID = 0,
446 SVGA3D_SHADEMODE_FLAT = 1,
447 SVGA3D_SHADEMODE_SMOOTH = 2,
448 SVGA3D_SHADEMODE_PHONG = 3, /* Not supported */
449 SVGA3D_SHADEMODE_MAX
450} SVGA3dShadeMode;
451
452typedef
453union {
454 struct {
455 uint16 repeat;
456 uint16 pattern;
457 };
458 uint32 uintValue;
459} SVGA3dLinePattern;
460
461typedef enum {
462 SVGA3D_BLENDOP_INVALID = 0,
463 SVGA3D_BLENDOP_ZERO = 1,
464 SVGA3D_BLENDOP_ONE = 2,
465 SVGA3D_BLENDOP_SRCCOLOR = 3,
466 SVGA3D_BLENDOP_INVSRCCOLOR = 4,
467 SVGA3D_BLENDOP_SRCALPHA = 5,
468 SVGA3D_BLENDOP_INVSRCALPHA = 6,
469 SVGA3D_BLENDOP_DESTALPHA = 7,
470 SVGA3D_BLENDOP_INVDESTALPHA = 8,
471 SVGA3D_BLENDOP_DESTCOLOR = 9,
472 SVGA3D_BLENDOP_INVDESTCOLOR = 10,
473 SVGA3D_BLENDOP_SRCALPHASAT = 11,
474 SVGA3D_BLENDOP_BLENDFACTOR = 12,
475 SVGA3D_BLENDOP_INVBLENDFACTOR = 13,
476 SVGA3D_BLENDOP_MAX
477} SVGA3dBlendOp;
478
479typedef enum {
480 SVGA3D_BLENDEQ_INVALID = 0,
481 SVGA3D_BLENDEQ_ADD = 1,
482 SVGA3D_BLENDEQ_SUBTRACT = 2,
483 SVGA3D_BLENDEQ_REVSUBTRACT = 3,
484 SVGA3D_BLENDEQ_MINIMUM = 4,
485 SVGA3D_BLENDEQ_MAXIMUM = 5,
486 SVGA3D_BLENDEQ_MAX
487} SVGA3dBlendEquation;
488
489typedef enum {
490 SVGA3D_FRONTWINDING_INVALID = 0,
491 SVGA3D_FRONTWINDING_CW = 1,
492 SVGA3D_FRONTWINDING_CCW = 2,
493 SVGA3D_FRONTWINDING_MAX
494} SVGA3dFrontWinding;
495
496typedef enum {
497 SVGA3D_FACE_INVALID = 0,
498 SVGA3D_FACE_NONE = 1,
499 SVGA3D_FACE_FRONT = 2,
500 SVGA3D_FACE_BACK = 3,
501 SVGA3D_FACE_FRONT_BACK = 4,
502 SVGA3D_FACE_MAX
503} SVGA3dFace;
504
505/*
506 * The order and the values should not be changed
507 */
508
509typedef enum {
510 SVGA3D_CMP_INVALID = 0,
511 SVGA3D_CMP_NEVER = 1,
512 SVGA3D_CMP_LESS = 2,
513 SVGA3D_CMP_EQUAL = 3,
514 SVGA3D_CMP_LESSEQUAL = 4,
515 SVGA3D_CMP_GREATER = 5,
516 SVGA3D_CMP_NOTEQUAL = 6,
517 SVGA3D_CMP_GREATEREQUAL = 7,
518 SVGA3D_CMP_ALWAYS = 8,
519 SVGA3D_CMP_MAX
520} SVGA3dCmpFunc;
521
522/*
523 * SVGA3D_FOGFUNC_* specifies the fog equation, or PER_VERTEX which allows
524 * the fog factor to be specified in the alpha component of the specular
525 * (a.k.a. secondary) vertex color.
526 */
527typedef enum {
528 SVGA3D_FOGFUNC_INVALID = 0,
529 SVGA3D_FOGFUNC_EXP = 1,
530 SVGA3D_FOGFUNC_EXP2 = 2,
531 SVGA3D_FOGFUNC_LINEAR = 3,
532 SVGA3D_FOGFUNC_PER_VERTEX = 4
533} SVGA3dFogFunction;
534
535/*
536 * SVGA3D_FOGTYPE_* specifies if fog factors are computed on a per-vertex
537 * or per-pixel basis.
538 */
539typedef enum {
540 SVGA3D_FOGTYPE_INVALID = 0,
541 SVGA3D_FOGTYPE_VERTEX = 1,
542 SVGA3D_FOGTYPE_PIXEL = 2,
543 SVGA3D_FOGTYPE_MAX = 3
544} SVGA3dFogType;
545
546/*
547 * SVGA3D_FOGBASE_* selects depth or range-based fog. Depth-based fog is
548 * computed using the eye Z value of each pixel (or vertex), whereas range-
549 * based fog is computed using the actual distance (range) to the eye.
550 */
551typedef enum {
552 SVGA3D_FOGBASE_INVALID = 0,
553 SVGA3D_FOGBASE_DEPTHBASED = 1,
554 SVGA3D_FOGBASE_RANGEBASED = 2,
555 SVGA3D_FOGBASE_MAX = 3
556} SVGA3dFogBase;
557
558typedef enum {
559 SVGA3D_STENCILOP_INVALID = 0,
560 SVGA3D_STENCILOP_KEEP = 1,
561 SVGA3D_STENCILOP_ZERO = 2,
562 SVGA3D_STENCILOP_REPLACE = 3,
563 SVGA3D_STENCILOP_INCRSAT = 4,
564 SVGA3D_STENCILOP_DECRSAT = 5,
565 SVGA3D_STENCILOP_INVERT = 6,
566 SVGA3D_STENCILOP_INCR = 7,
567 SVGA3D_STENCILOP_DECR = 8,
568 SVGA3D_STENCILOP_MAX
569} SVGA3dStencilOp;
570
571typedef enum {
572 SVGA3D_CLIPPLANE_0 = (1 << 0),
573 SVGA3D_CLIPPLANE_1 = (1 << 1),
574 SVGA3D_CLIPPLANE_2 = (1 << 2),
575 SVGA3D_CLIPPLANE_3 = (1 << 3),
576 SVGA3D_CLIPPLANE_4 = (1 << 4),
577 SVGA3D_CLIPPLANE_5 = (1 << 5),
578} SVGA3dClipPlanes;
579
580typedef enum {
581 SVGA3D_CLEAR_COLOR = 0x1,
582 SVGA3D_CLEAR_DEPTH = 0x2,
583 SVGA3D_CLEAR_STENCIL = 0x4
584} SVGA3dClearFlag;
585
586typedef enum {
587 SVGA3D_RT_DEPTH = 0,
588 SVGA3D_RT_STENCIL = 1,
589 SVGA3D_RT_COLOR0 = 2,
590 SVGA3D_RT_COLOR1 = 3,
591 SVGA3D_RT_COLOR2 = 4,
592 SVGA3D_RT_COLOR3 = 5,
593 SVGA3D_RT_COLOR4 = 6,
594 SVGA3D_RT_COLOR5 = 7,
595 SVGA3D_RT_COLOR6 = 8,
596 SVGA3D_RT_COLOR7 = 9,
597 SVGA3D_RT_MAX,
598 SVGA3D_RT_INVALID = ((uint32)-1),
599} SVGA3dRenderTargetType;
600
601#define SVGA3D_MAX_RT_COLOR (SVGA3D_RT_COLOR7 - SVGA3D_RT_COLOR0 + 1)
602
603typedef
604union {
605 struct {
606 uint32 red : 1;
607 uint32 green : 1;
608 uint32 blue : 1;
609 uint32 alpha : 1;
610 };
611 uint32 uintValue;
612} SVGA3dColorMask;
613
614typedef enum {
615 SVGA3D_VBLEND_DISABLE = 0,
616 SVGA3D_VBLEND_1WEIGHT = 1,
617 SVGA3D_VBLEND_2WEIGHT = 2,
618 SVGA3D_VBLEND_3WEIGHT = 3,
619} SVGA3dVertexBlendFlags;
620
621typedef enum {
622 SVGA3D_WRAPCOORD_0 = 1 << 0,
623 SVGA3D_WRAPCOORD_1 = 1 << 1,
624 SVGA3D_WRAPCOORD_2 = 1 << 2,
625 SVGA3D_WRAPCOORD_3 = 1 << 3,
626 SVGA3D_WRAPCOORD_ALL = 0xF,
627} SVGA3dWrapFlags;
628
629/*
630 * SVGA_3D_CMD_TEXTURESTATE Types. All value types
631 * must fit in a uint32.
632 */
633
634typedef enum {
635 SVGA3D_TS_INVALID = 0,
636 SVGA3D_TS_BIND_TEXTURE = 1, /* SVGA3dSurfaceId */
637 SVGA3D_TS_COLOROP = 2, /* SVGA3dTextureCombiner */
638 SVGA3D_TS_COLORARG1 = 3, /* SVGA3dTextureArgData */
639 SVGA3D_TS_COLORARG2 = 4, /* SVGA3dTextureArgData */
640 SVGA3D_TS_ALPHAOP = 5, /* SVGA3dTextureCombiner */
641 SVGA3D_TS_ALPHAARG1 = 6, /* SVGA3dTextureArgData */
642 SVGA3D_TS_ALPHAARG2 = 7, /* SVGA3dTextureArgData */
643 SVGA3D_TS_ADDRESSU = 8, /* SVGA3dTextureAddress */
644 SVGA3D_TS_ADDRESSV = 9, /* SVGA3dTextureAddress */
645 SVGA3D_TS_MIPFILTER = 10, /* SVGA3dTextureFilter */
646 SVGA3D_TS_MAGFILTER = 11, /* SVGA3dTextureFilter */
647 SVGA3D_TS_MINFILTER = 12, /* SVGA3dTextureFilter */
648 SVGA3D_TS_BORDERCOLOR = 13, /* SVGA3dColor */
649 SVGA3D_TS_TEXCOORDINDEX = 14, /* uint32 */
650 SVGA3D_TS_TEXTURETRANSFORMFLAGS = 15, /* SVGA3dTexTransformFlags */
651 SVGA3D_TS_TEXCOORDGEN = 16, /* SVGA3dTextureCoordGen */
652 SVGA3D_TS_BUMPENVMAT00 = 17, /* float */
653 SVGA3D_TS_BUMPENVMAT01 = 18, /* float */
654 SVGA3D_TS_BUMPENVMAT10 = 19, /* float */
655 SVGA3D_TS_BUMPENVMAT11 = 20, /* float */
656 SVGA3D_TS_TEXTURE_MIPMAP_LEVEL = 21, /* uint32 */
657 SVGA3D_TS_TEXTURE_LOD_BIAS = 22, /* float */
658 SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL = 23, /* uint32 */
659 SVGA3D_TS_ADDRESSW = 24, /* SVGA3dTextureAddress */
660
661
662 /*
663 * Sampler Gamma Level
664 *
665 * Sampler gamma effects the color of samples taken from the sampler. A
666 * value of 1.0 will produce linear samples. If the value is <= 0.0 the
667 * gamma value is ignored and a linear space is used.
668 */
669
670 SVGA3D_TS_GAMMA = 25, /* float */
671 SVGA3D_TS_BUMPENVLSCALE = 26, /* float */
672 SVGA3D_TS_BUMPENVLOFFSET = 27, /* float */
673 SVGA3D_TS_COLORARG0 = 28, /* SVGA3dTextureArgData */
674 SVGA3D_TS_ALPHAARG0 = 29, /* SVGA3dTextureArgData */
675 SVGA3D_TS_MAX
676} SVGA3dTextureStateName;
677
678typedef enum {
679 SVGA3D_TC_INVALID = 0,
680 SVGA3D_TC_DISABLE = 1,
681 SVGA3D_TC_SELECTARG1 = 2,
682 SVGA3D_TC_SELECTARG2 = 3,
683 SVGA3D_TC_MODULATE = 4,
684 SVGA3D_TC_ADD = 5,
685 SVGA3D_TC_ADDSIGNED = 6,
686 SVGA3D_TC_SUBTRACT = 7,
687 SVGA3D_TC_BLENDTEXTUREALPHA = 8,
688 SVGA3D_TC_BLENDDIFFUSEALPHA = 9,
689 SVGA3D_TC_BLENDCURRENTALPHA = 10,
690 SVGA3D_TC_BLENDFACTORALPHA = 11,
691 SVGA3D_TC_MODULATE2X = 12,
692 SVGA3D_TC_MODULATE4X = 13,
693 SVGA3D_TC_DSDT = 14,
694 SVGA3D_TC_DOTPRODUCT3 = 15,
695 SVGA3D_TC_BLENDTEXTUREALPHAPM = 16,
696 SVGA3D_TC_ADDSIGNED2X = 17,
697 SVGA3D_TC_ADDSMOOTH = 18,
698 SVGA3D_TC_PREMODULATE = 19,
699 SVGA3D_TC_MODULATEALPHA_ADDCOLOR = 20,
700 SVGA3D_TC_MODULATECOLOR_ADDALPHA = 21,
701 SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR = 22,
702 SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA = 23,
703 SVGA3D_TC_BUMPENVMAPLUMINANCE = 24,
704 SVGA3D_TC_MULTIPLYADD = 25,
705 SVGA3D_TC_LERP = 26,
706 SVGA3D_TC_MAX
707} SVGA3dTextureCombiner;
708
709#define SVGA3D_TC_CAP_BIT(svga3d_tc_op) (svga3d_tc_op ? (1 << (svga3d_tc_op - 1)) : 0)
710
711typedef enum {
712 SVGA3D_TEX_ADDRESS_INVALID = 0,
713 SVGA3D_TEX_ADDRESS_WRAP = 1,
714 SVGA3D_TEX_ADDRESS_MIRROR = 2,
715 SVGA3D_TEX_ADDRESS_CLAMP = 3,
716 SVGA3D_TEX_ADDRESS_BORDER = 4,
717 SVGA3D_TEX_ADDRESS_MIRRORONCE = 5,
718 SVGA3D_TEX_ADDRESS_EDGE = 6,
719 SVGA3D_TEX_ADDRESS_MAX
720} SVGA3dTextureAddress;
721
722/*
723 * SVGA3D_TEX_FILTER_NONE as the minification filter means mipmapping is
724 * disabled, and the rasterizer should use the magnification filter instead.
725 */
726typedef enum {
727 SVGA3D_TEX_FILTER_NONE = 0,
728 SVGA3D_TEX_FILTER_NEAREST = 1,
729 SVGA3D_TEX_FILTER_LINEAR = 2,
730 SVGA3D_TEX_FILTER_ANISOTROPIC = 3,
731 SVGA3D_TEX_FILTER_FLATCUBIC = 4, // Deprecated, not implemented
732 SVGA3D_TEX_FILTER_GAUSSIANCUBIC = 5, // Deprecated, not implemented
733 SVGA3D_TEX_FILTER_PYRAMIDALQUAD = 6, // Not currently implemented
734 SVGA3D_TEX_FILTER_GAUSSIANQUAD = 7, // Not currently implemented
735 SVGA3D_TEX_FILTER_MAX
736} SVGA3dTextureFilter;
737
738typedef enum {
739 SVGA3D_TEX_TRANSFORM_OFF = 0,
740 SVGA3D_TEX_TRANSFORM_S = (1 << 0),
741 SVGA3D_TEX_TRANSFORM_T = (1 << 1),
742 SVGA3D_TEX_TRANSFORM_R = (1 << 2),
743 SVGA3D_TEX_TRANSFORM_Q = (1 << 3),
744 SVGA3D_TEX_PROJECTED = (1 << 15),
745} SVGA3dTexTransformFlags;
746
747typedef enum {
748 SVGA3D_TEXCOORD_GEN_OFF = 0,
749 SVGA3D_TEXCOORD_GEN_EYE_POSITION = 1,
750 SVGA3D_TEXCOORD_GEN_EYE_NORMAL = 2,
751 SVGA3D_TEXCOORD_GEN_REFLECTIONVECTOR = 3,
752 SVGA3D_TEXCOORD_GEN_SPHERE = 4,
753 SVGA3D_TEXCOORD_GEN_MAX
754} SVGA3dTextureCoordGen;
755
756/*
757 * Texture argument constants for texture combiner
758 */
759typedef enum {
760 SVGA3D_TA_INVALID = 0,
761 SVGA3D_TA_CONSTANT = 1,
762 SVGA3D_TA_PREVIOUS = 2,
763 SVGA3D_TA_DIFFUSE = 3,
764 SVGA3D_TA_TEXTURE = 4,
765 SVGA3D_TA_SPECULAR = 5,
766 SVGA3D_TA_MAX
767} SVGA3dTextureArgData;
768
769#define SVGA3D_TM_MASK_LEN 4
770
771/* Modifiers for texture argument constants defined above. */
772typedef enum {
773 SVGA3D_TM_NONE = 0,
774 SVGA3D_TM_ALPHA = (1 << SVGA3D_TM_MASK_LEN),
775 SVGA3D_TM_ONE_MINUS = (2 << SVGA3D_TM_MASK_LEN),
776} SVGA3dTextureArgModifier;
777
778#define SVGA3D_INVALID_ID ((uint32)-1)
779#define SVGA3D_MAX_CLIP_PLANES 6
780
781/*
782 * This is the limit to the number of fixed-function texture
783 * transforms and texture coordinates we can support. It does *not*
784 * correspond to the number of texture image units (samplers) we
785 * support!
786 */
787#define SVGA3D_MAX_TEXTURE_COORDS 8
788
789/*
790 * Vertex declarations
791 *
792 * Notes:
793 *
794 * SVGA3D_DECLUSAGE_POSITIONT is for pre-transformed vertices. If you
795 * draw with any POSITIONT vertex arrays, the programmable vertex
796 * pipeline will be implicitly disabled. Drawing will take place as if
797 * no vertex shader was bound.
798 */
799
800typedef enum {
801 SVGA3D_DECLUSAGE_POSITION = 0,
802 SVGA3D_DECLUSAGE_BLENDWEIGHT, // 1
803 SVGA3D_DECLUSAGE_BLENDINDICES, // 2
804 SVGA3D_DECLUSAGE_NORMAL, // 3
805 SVGA3D_DECLUSAGE_PSIZE, // 4
806 SVGA3D_DECLUSAGE_TEXCOORD, // 5
807 SVGA3D_DECLUSAGE_TANGENT, // 6
808 SVGA3D_DECLUSAGE_BINORMAL, // 7
809 SVGA3D_DECLUSAGE_TESSFACTOR, // 8
810 SVGA3D_DECLUSAGE_POSITIONT, // 9
811 SVGA3D_DECLUSAGE_COLOR, // 10
812 SVGA3D_DECLUSAGE_FOG, // 11
813 SVGA3D_DECLUSAGE_DEPTH, // 12
814 SVGA3D_DECLUSAGE_SAMPLE, // 13
815 SVGA3D_DECLUSAGE_MAX
816} SVGA3dDeclUsage;
817
818typedef enum {
819 SVGA3D_DECLMETHOD_DEFAULT = 0,
820 SVGA3D_DECLMETHOD_PARTIALU,
821 SVGA3D_DECLMETHOD_PARTIALV,
822 SVGA3D_DECLMETHOD_CROSSUV, // Normal
823 SVGA3D_DECLMETHOD_UV,
824 SVGA3D_DECLMETHOD_LOOKUP, // Lookup a displacement map
825 SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map
826} SVGA3dDeclMethod;
827
828typedef enum {
829 SVGA3D_DECLTYPE_FLOAT1 = 0,
830 SVGA3D_DECLTYPE_FLOAT2 = 1,
831 SVGA3D_DECLTYPE_FLOAT3 = 2,
832 SVGA3D_DECLTYPE_FLOAT4 = 3,
833 SVGA3D_DECLTYPE_D3DCOLOR = 4,
834 SVGA3D_DECLTYPE_UBYTE4 = 5,
835 SVGA3D_DECLTYPE_SHORT2 = 6,
836 SVGA3D_DECLTYPE_SHORT4 = 7,
837 SVGA3D_DECLTYPE_UBYTE4N = 8,
838 SVGA3D_DECLTYPE_SHORT2N = 9,
839 SVGA3D_DECLTYPE_SHORT4N = 10,
840 SVGA3D_DECLTYPE_USHORT2N = 11,
841 SVGA3D_DECLTYPE_USHORT4N = 12,
842 SVGA3D_DECLTYPE_UDEC3 = 13,
843 SVGA3D_DECLTYPE_DEC3N = 14,
844 SVGA3D_DECLTYPE_FLOAT16_2 = 15,
845 SVGA3D_DECLTYPE_FLOAT16_4 = 16,
846 SVGA3D_DECLTYPE_MAX,
847} SVGA3dDeclType;
848
849/*
850 * This structure is used for the divisor for geometry instancing;
851 * it's a direct translation of the Direct3D equivalent.
852 */
853typedef union {
854 struct {
855 /*
856 * For index data, this number represents the number of instances to draw.
857 * For instance data, this number represents the number of
858 * instances/vertex in this stream
859 */
860 uint32 count : 30;
861
862 /*
863 * This is 1 if this is supposed to be the data that is repeated for
864 * every instance.
865 */
866 uint32 indexedData : 1;
867
868 /*
869 * This is 1 if this is supposed to be the per-instance data.
870 */
871 uint32 instanceData : 1;
872 };
873
874 uint32 value;
875} SVGA3dVertexDivisor;
876
877typedef enum {
878 SVGA3D_PRIMITIVE_INVALID = 0,
879 SVGA3D_PRIMITIVE_TRIANGLELIST = 1,
880 SVGA3D_PRIMITIVE_POINTLIST = 2,
881 SVGA3D_PRIMITIVE_LINELIST = 3,
882 SVGA3D_PRIMITIVE_LINESTRIP = 4,
883 SVGA3D_PRIMITIVE_TRIANGLESTRIP = 5,
884 SVGA3D_PRIMITIVE_TRIANGLEFAN = 6,
885 SVGA3D_PRIMITIVE_MAX
886} SVGA3dPrimitiveType;
887
888typedef enum {
889 SVGA3D_COORDINATE_INVALID = 0,
890 SVGA3D_COORDINATE_LEFTHANDED = 1,
891 SVGA3D_COORDINATE_RIGHTHANDED = 2,
892 SVGA3D_COORDINATE_MAX
893} SVGA3dCoordinateType;
894
895typedef enum {
896 SVGA3D_TRANSFORM_INVALID = 0,
897 SVGA3D_TRANSFORM_WORLD = 1,
898 SVGA3D_TRANSFORM_VIEW = 2,
899 SVGA3D_TRANSFORM_PROJECTION = 3,
900 SVGA3D_TRANSFORM_TEXTURE0 = 4,
901 SVGA3D_TRANSFORM_TEXTURE1 = 5,
902 SVGA3D_TRANSFORM_TEXTURE2 = 6,
903 SVGA3D_TRANSFORM_TEXTURE3 = 7,
904 SVGA3D_TRANSFORM_TEXTURE4 = 8,
905 SVGA3D_TRANSFORM_TEXTURE5 = 9,
906 SVGA3D_TRANSFORM_TEXTURE6 = 10,
907 SVGA3D_TRANSFORM_TEXTURE7 = 11,
908 SVGA3D_TRANSFORM_WORLD1 = 12,
909 SVGA3D_TRANSFORM_WORLD2 = 13,
910 SVGA3D_TRANSFORM_WORLD3 = 14,
911 SVGA3D_TRANSFORM_MAX
912} SVGA3dTransformType;
913
914typedef enum {
915 SVGA3D_LIGHTTYPE_INVALID = 0,
916 SVGA3D_LIGHTTYPE_POINT = 1,
917 SVGA3D_LIGHTTYPE_SPOT1 = 2, /* 1-cone, in degrees */
918 SVGA3D_LIGHTTYPE_SPOT2 = 3, /* 2-cone, in radians */
919 SVGA3D_LIGHTTYPE_DIRECTIONAL = 4,
920 SVGA3D_LIGHTTYPE_MAX
921} SVGA3dLightType;
922
923typedef enum {
924 SVGA3D_CUBEFACE_POSX = 0,
925 SVGA3D_CUBEFACE_NEGX = 1,
926 SVGA3D_CUBEFACE_POSY = 2,
927 SVGA3D_CUBEFACE_NEGY = 3,
928 SVGA3D_CUBEFACE_POSZ = 4,
929 SVGA3D_CUBEFACE_NEGZ = 5,
930} SVGA3dCubeFace;
931
932typedef enum {
933 SVGA3D_SHADERTYPE_COMPILED_DX8 = 0,
934 SVGA3D_SHADERTYPE_VS = 1,
935 SVGA3D_SHADERTYPE_PS = 2,
936 SVGA3D_SHADERTYPE_MAX
937} SVGA3dShaderType;
938
939typedef enum {
940 SVGA3D_CONST_TYPE_FLOAT = 0,
941 SVGA3D_CONST_TYPE_INT = 1,
942 SVGA3D_CONST_TYPE_BOOL = 2,
943} SVGA3dShaderConstType;
944
945#define SVGA3D_MAX_SURFACE_FACES 6
946
947typedef enum {
948 SVGA3D_STRETCH_BLT_POINT = 0,
949 SVGA3D_STRETCH_BLT_LINEAR = 1,
950 SVGA3D_STRETCH_BLT_MAX
951} SVGA3dStretchBltMode;
952
953typedef enum {
954 SVGA3D_QUERYTYPE_OCCLUSION = 0,
955 SVGA3D_QUERYTYPE_MAX
956} SVGA3dQueryType;
957
958typedef enum {
959 SVGA3D_QUERYSTATE_PENDING = 0, /* Waiting on the host (set by guest) */
960 SVGA3D_QUERYSTATE_SUCCEEDED = 1, /* Completed successfully (set by host) */
961 SVGA3D_QUERYSTATE_FAILED = 2, /* Completed unsuccessfully (set by host) */
962 SVGA3D_QUERYSTATE_NEW = 3, /* Never submitted (For guest use only) */
963} SVGA3dQueryState;
964
965typedef enum {
966 SVGA3D_WRITE_HOST_VRAM = 1,
967 SVGA3D_READ_HOST_VRAM = 2,
968} SVGA3dTransferType;
969
970/*
971 * The maximum number of vertex arrays we're guaranteed to support in
972 * SVGA_3D_CMD_DRAWPRIMITIVES.
973 */
974#define SVGA3D_MAX_VERTEX_ARRAYS 32
975
976/*
977 * The maximum number of primitive ranges we're guaranteed to support
978 * in SVGA_3D_CMD_DRAWPRIMITIVES.
979 */
980#define SVGA3D_MAX_DRAW_PRIMITIVE_RANGES 32
981
982/*
983 * Identifiers for commands in the command FIFO.
984 *
985 * IDs between 1000 and 1039 (inclusive) were used by obsolete versions of
986 * the SVGA3D protocol and remain reserved; they should not be used in the
987 * future.
988 *
989 * IDs between 1040 and 1999 (inclusive) are available for use by the
990 * current SVGA3D protocol.
991 *
992 * FIFO clients other than SVGA3D should stay below 1000, or at 2000
993 * and up.
994 */
995
996#define SVGA_3D_CMD_LEGACY_BASE 1000
997#define SVGA_3D_CMD_BASE 1040
998
999#define SVGA_3D_CMD_SURFACE_DEFINE SVGA_3D_CMD_BASE + 0
1000#define SVGA_3D_CMD_SURFACE_DESTROY SVGA_3D_CMD_BASE + 1
1001#define SVGA_3D_CMD_SURFACE_COPY SVGA_3D_CMD_BASE + 2
1002#define SVGA_3D_CMD_SURFACE_STRETCHBLT SVGA_3D_CMD_BASE + 3
1003#define SVGA_3D_CMD_SURFACE_DMA SVGA_3D_CMD_BASE + 4
1004#define SVGA_3D_CMD_CONTEXT_DEFINE SVGA_3D_CMD_BASE + 5
1005#define SVGA_3D_CMD_CONTEXT_DESTROY SVGA_3D_CMD_BASE + 6
1006#define SVGA_3D_CMD_SETTRANSFORM SVGA_3D_CMD_BASE + 7
1007#define SVGA_3D_CMD_SETZRANGE SVGA_3D_CMD_BASE + 8
1008#define SVGA_3D_CMD_SETRENDERSTATE SVGA_3D_CMD_BASE + 9
1009#define SVGA_3D_CMD_SETRENDERTARGET SVGA_3D_CMD_BASE + 10
1010#define SVGA_3D_CMD_SETTEXTURESTATE SVGA_3D_CMD_BASE + 11
1011#define SVGA_3D_CMD_SETMATERIAL SVGA_3D_CMD_BASE + 12
1012#define SVGA_3D_CMD_SETLIGHTDATA SVGA_3D_CMD_BASE + 13
1013#define SVGA_3D_CMD_SETLIGHTENABLED SVGA_3D_CMD_BASE + 14
1014#define SVGA_3D_CMD_SETVIEWPORT SVGA_3D_CMD_BASE + 15
1015#define SVGA_3D_CMD_SETCLIPPLANE SVGA_3D_CMD_BASE + 16
1016#define SVGA_3D_CMD_CLEAR SVGA_3D_CMD_BASE + 17
1017#define SVGA_3D_CMD_PRESENT SVGA_3D_CMD_BASE + 18 // Deprecated
1018#define SVGA_3D_CMD_SHADER_DEFINE SVGA_3D_CMD_BASE + 19
1019#define SVGA_3D_CMD_SHADER_DESTROY SVGA_3D_CMD_BASE + 20
1020#define SVGA_3D_CMD_SET_SHADER SVGA_3D_CMD_BASE + 21
1021#define SVGA_3D_CMD_SET_SHADER_CONST SVGA_3D_CMD_BASE + 22
1022#define SVGA_3D_CMD_DRAW_PRIMITIVES SVGA_3D_CMD_BASE + 23
1023#define SVGA_3D_CMD_SETSCISSORRECT SVGA_3D_CMD_BASE + 24
1024#define SVGA_3D_CMD_BEGIN_QUERY SVGA_3D_CMD_BASE + 25
1025#define SVGA_3D_CMD_END_QUERY SVGA_3D_CMD_BASE + 26
1026#define SVGA_3D_CMD_WAIT_FOR_QUERY SVGA_3D_CMD_BASE + 27
1027#define SVGA_3D_CMD_PRESENT_READBACK SVGA_3D_CMD_BASE + 28 // Deprecated
1028#define SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN SVGA_3D_CMD_BASE + 29
1029#define SVGA_3D_CMD_MAX SVGA_3D_CMD_BASE + 30
1030
1031#define SVGA_3D_CMD_FUTURE_MAX 2000
1032
1033/*
1034 * Common substructures used in multiple FIFO commands:
1035 */
1036
1037typedef struct {
1038 union {
1039 struct {
1040 uint16 function; // SVGA3dFogFunction
1041 uint8 type; // SVGA3dFogType
1042 uint8 base; // SVGA3dFogBase
1043 };
1044 uint32 uintValue;
1045 };
1046} SVGA3dFogMode;
1047
1048/*
1049 * Uniquely identify one image (a 1D/2D/3D array) from a surface. This
1050 * is a surface ID as well as face/mipmap indices.
1051 */
1052
1053typedef
1054struct SVGA3dSurfaceImageId {
1055 uint32 sid;
1056 uint32 face;
1057 uint32 mipmap;
1058} SVGA3dSurfaceImageId;
1059
1060typedef
1061struct SVGA3dGuestImage {
1062 SVGAGuestPtr ptr;
1063
1064 /*
1065 * A note on interpretation of pitch: This value of pitch is the
1066 * number of bytes between vertically adjacent image
1067 * blocks. Normally this is the number of bytes between the first
1068 * pixel of two adjacent scanlines. With compressed textures,
1069 * however, this may represent the number of bytes between
1070 * compression blocks rather than between rows of pixels.
1071 *
1072 * XXX: Compressed textures currently must be tightly packed in guest memory.
1073 *
1074 * If the image is 1-dimensional, pitch is ignored.
1075 *
1076 * If 'pitch' is zero, the SVGA3D device calculates a pitch value
1077 * assuming each row of blocks is tightly packed.
1078 */
1079 uint32 pitch;
1080} SVGA3dGuestImage;
1081
1082
1083/*
1084 * FIFO command format definitions:
1085 */
1086
1087/*
1088 * The data size header following cmdNum for every 3d command
1089 */
1090typedef
1091struct {
1092 uint32 id;
1093 uint32 size;
1094} SVGA3dCmdHeader;
1095
1096/*
1097 * A surface is a hierarchy of host VRAM surfaces: 1D, 2D, or 3D, with
1098 * optional mipmaps and cube faces.
1099 */
1100
1101typedef
1102struct {
1103 uint32 width;
1104 uint32 height;
1105 uint32 depth;
1106} SVGA3dSize;
1107
1108typedef enum {
1109 SVGA3D_SURFACE_CUBEMAP = (1 << 0),
1110 SVGA3D_SURFACE_HINT_STATIC = (1 << 1),
1111 SVGA3D_SURFACE_HINT_DYNAMIC = (1 << 2),
1112 SVGA3D_SURFACE_HINT_INDEXBUFFER = (1 << 3),
1113 SVGA3D_SURFACE_HINT_VERTEXBUFFER = (1 << 4),
1114 SVGA3D_SURFACE_HINT_TEXTURE = (1 << 5),
1115 SVGA3D_SURFACE_HINT_RENDERTARGET = (1 << 6),
1116 SVGA3D_SURFACE_HINT_DEPTHSTENCIL = (1 << 7),
1117 SVGA3D_SURFACE_HINT_WRITEONLY = (1 << 8),
1118} SVGA3dSurfaceFlags;
1119
1120typedef
1121struct {
1122 uint32 numMipLevels;
1123} SVGA3dSurfaceFace;
1124
1125typedef
1126struct {
1127 uint32 sid;
1128 SVGA3dSurfaceFlags surfaceFlags;
1129 SVGA3dSurfaceFormat format;
1130 SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES];
1131 /*
1132 * Followed by an SVGA3dSize structure for each mip level in each face.
1133 *
1134 * A note on surface sizes: Sizes are always specified in pixels,
1135 * even if the true surface size is not a multiple of the minimum
1136 * block size of the surface's format. For example, a 3x3x1 DXT1
1137 * compressed texture would actually be stored as a 4x4x1 image in
1138 * memory.
1139 */
1140} SVGA3dCmdDefineSurface; /* SVGA_3D_CMD_SURFACE_DEFINE */
1141
1142typedef
1143struct {
1144 uint32 sid;
1145} SVGA3dCmdDestroySurface; /* SVGA_3D_CMD_SURFACE_DESTROY */
1146
1147typedef
1148struct {
1149 uint32 cid;
1150} SVGA3dCmdDefineContext; /* SVGA_3D_CMD_CONTEXT_DEFINE */
1151
1152typedef
1153struct {
1154 uint32 cid;
1155} SVGA3dCmdDestroyContext; /* SVGA_3D_CMD_CONTEXT_DESTROY */
1156
1157typedef
1158struct {
1159 uint32 cid;
1160 SVGA3dClearFlag clearFlag;
1161 uint32 color;
1162 float depth;
1163 uint32 stencil;
1164 /* Followed by variable number of SVGA3dRect structures */
1165} SVGA3dCmdClear; /* SVGA_3D_CMD_CLEAR */
1166
1167typedef
1168struct SVGA3dCopyRect {
1169 uint32 x;
1170 uint32 y;
1171 uint32 w;
1172 uint32 h;
1173 uint32 srcx;
1174 uint32 srcy;
1175} SVGA3dCopyRect;
1176
1177typedef
1178struct SVGA3dCopyBox {
1179 uint32 x;
1180 uint32 y;
1181 uint32 z;
1182 uint32 w;
1183 uint32 h;
1184 uint32 d;
1185 uint32 srcx;
1186 uint32 srcy;
1187 uint32 srcz;
1188} SVGA3dCopyBox;
1189
1190typedef
1191struct {
1192 uint32 x;
1193 uint32 y;
1194 uint32 w;
1195 uint32 h;
1196} SVGA3dRect;
1197
1198typedef
1199struct {
1200 uint32 x;
1201 uint32 y;
1202 uint32 z;
1203 uint32 w;
1204 uint32 h;
1205 uint32 d;
1206} SVGA3dBox;
1207
1208typedef
1209struct {
1210 uint32 x;
1211 uint32 y;
1212 uint32 z;
1213} SVGA3dPoint;
1214
1215typedef
1216struct {
1217 SVGA3dLightType type;
1218 SVGA3dBool inWorldSpace;
1219 float diffuse[4];
1220 float specular[4];
1221 float ambient[4];
1222 float position[4];
1223 float direction[4];
1224 float range;
1225 float falloff;
1226 float attenuation0;
1227 float attenuation1;
1228 float attenuation2;
1229 float theta;
1230 float phi;
1231} SVGA3dLightData;
1232
1233typedef
1234struct {
1235 uint32 sid;
1236 /* Followed by variable number of SVGA3dCopyRect structures */
1237} SVGA3dCmdPresent; /* SVGA_3D_CMD_PRESENT */
1238
1239typedef
1240struct {
1241 SVGA3dRenderStateName state;
1242 union {
1243 uint32 uintValue;
1244 float floatValue;
1245 };
1246} SVGA3dRenderState;
1247
1248typedef
1249struct {
1250 uint32 cid;
1251 /* Followed by variable number of SVGA3dRenderState structures */
1252} SVGA3dCmdSetRenderState; /* SVGA_3D_CMD_SETRENDERSTATE */
1253
1254typedef
1255struct {
1256 uint32 cid;
1257 SVGA3dRenderTargetType type;
1258 SVGA3dSurfaceImageId target;
1259} SVGA3dCmdSetRenderTarget; /* SVGA_3D_CMD_SETRENDERTARGET */
1260
1261typedef
1262struct {
1263 SVGA3dSurfaceImageId src;
1264 SVGA3dSurfaceImageId dest;
1265 /* Followed by variable number of SVGA3dCopyBox structures */
1266} SVGA3dCmdSurfaceCopy; /* SVGA_3D_CMD_SURFACE_COPY */
1267
1268typedef
1269struct {
1270 SVGA3dSurfaceImageId src;
1271 SVGA3dSurfaceImageId dest;
1272 SVGA3dBox boxSrc;
1273 SVGA3dBox boxDest;
1274 SVGA3dStretchBltMode mode;
1275} SVGA3dCmdSurfaceStretchBlt; /* SVGA_3D_CMD_SURFACE_STRETCHBLT */
1276
1277typedef
1278struct {
1279 /*
1280 * If the discard flag is present in a surface DMA operation, the host may
1281 * discard the contents of the current mipmap level and face of the target
1282 * surface before applying the surface DMA contents.
1283 */
1284 uint32 discard : 1;
1285
1286 /*
1287 * If the unsynchronized flag is present, the host may perform this upload
1288 * without syncing to pending reads on this surface.
1289 */
1290 uint32 unsynchronized : 1;
1291
1292 /*
1293 * Guests *MUST* set the reserved bits to 0 before submitting the command
1294 * suffix as future flags may occupy these bits.
1295 */
1296 uint32 reserved : 30;
1297} SVGA3dSurfaceDMAFlags;
1298
1299typedef
1300struct {
1301 SVGA3dGuestImage guest;
1302 SVGA3dSurfaceImageId host;
1303 SVGA3dTransferType transfer;
1304 /*
1305 * Followed by variable number of SVGA3dCopyBox structures. For consistency
1306 * in all clipping logic and coordinate translation, we define the
1307 * "source" in each copyBox as the guest image and the
1308 * "destination" as the host image, regardless of transfer
1309 * direction.
1310 *
1311 * For efficiency, the SVGA3D device is free to copy more data than
1312 * specified. For example, it may round copy boxes outwards such
1313 * that they lie on particular alignment boundaries.
1314 */
1315} SVGA3dCmdSurfaceDMA; /* SVGA_3D_CMD_SURFACE_DMA */
1316
1317/*
1318 * SVGA3dCmdSurfaceDMASuffix --
1319 *
1320 * This is a command suffix that will appear after a SurfaceDMA command in
1321 * the FIFO. It contains some extra information that hosts may use to
1322 * optimize performance or protect the guest. This suffix exists to preserve
1323 * backwards compatibility while also allowing for new functionality to be
1324 * implemented.
1325 */
1326
1327typedef
1328struct {
1329 uint32 suffixSize;
1330
1331 /*
1332 * The maximum offset is used to determine the maximum offset from the
1333 * guestPtr base address that will be accessed or written to during this
1334 * surfaceDMA. If the suffix is supported, the host will respect this
1335 * boundary while performing surface DMAs.
1336 *
1337 * Defaults to MAX_UINT32
1338 */
1339 uint32 maximumOffset;
1340
1341 /*
1342 * A set of flags that describes optimizations that the host may perform
1343 * while performing this surface DMA operation. The guest should never rely
1344 * on behaviour that is different when these flags are set for correctness.
1345 *
1346 * Defaults to 0
1347 */
1348 SVGA3dSurfaceDMAFlags flags;
1349} SVGA3dCmdSurfaceDMASuffix;
1350
1351/*
1352 * SVGA_3D_CMD_DRAW_PRIMITIVES --
1353 *
1354 * This command is the SVGA3D device's generic drawing entry point.
1355 * It can draw multiple ranges of primitives, optionally using an
1356 * index buffer, using an arbitrary collection of vertex buffers.
1357 *
1358 * Each SVGA3dVertexDecl defines a distinct vertex array to bind
1359 * during this draw call. The declarations specify which surface
1360 * the vertex data lives in, what that vertex data is used for,
1361 * and how to interpret it.
1362 *
1363 * Each SVGA3dPrimitiveRange defines a collection of primitives
1364 * to render using the same vertex arrays. An index buffer is
1365 * optional.
1366 */
1367
1368typedef
1369struct {
1370 /*
1371 * A range hint is an optional specification for the range of indices
1372 * in an SVGA3dArray that will be used. If 'last' is zero, it is assumed
1373 * that the entire array will be used.
1374 *
1375 * These are only hints. The SVGA3D device may use them for
1376 * performance optimization if possible, but it's also allowed to
1377 * ignore these values.
1378 */
1379 uint32 first;
1380 uint32 last;
1381} SVGA3dArrayRangeHint;
1382
1383typedef
1384struct {
1385 /*
1386 * Define the origin and shape of a vertex or index array. Both
1387 * 'offset' and 'stride' are in bytes. The provided surface will be
1388 * reinterpreted as a flat array of bytes in the same format used
1389 * by surface DMA operations. To avoid unnecessary conversions, the
1390 * surface should be created with the SVGA3D_BUFFER format.
1391 *
1392 * Index 0 in the array starts 'offset' bytes into the surface.
1393 * Index 1 begins at byte 'offset + stride', etc. Array indices may
1394 * not be negative.
1395 */
1396 uint32 surfaceId;
1397 uint32 offset;
1398 uint32 stride;
1399} SVGA3dArray;
1400
1401typedef
1402struct {
1403 /*
1404 * Describe a vertex array's data type, and define how it is to be
1405 * used by the fixed function pipeline or the vertex shader. It
1406 * isn't useful to have two VertexDecls with the same
1407 * VertexArrayIdentity in one draw call.
1408 */
1409 SVGA3dDeclType type;
1410 SVGA3dDeclMethod method;
1411 SVGA3dDeclUsage usage;
1412 uint32 usageIndex;
1413} SVGA3dVertexArrayIdentity;
1414
1415typedef
1416struct {
1417 SVGA3dVertexArrayIdentity identity;
1418 SVGA3dArray array;
1419 SVGA3dArrayRangeHint rangeHint;
1420} SVGA3dVertexDecl;
1421
1422typedef
1423struct {
1424 /*
1425 * Define a group of primitives to render, from sequential indices.
1426 *
1427 * The value of 'primitiveType' and 'primitiveCount' imply the
1428 * total number of vertices that will be rendered.
1429 */
1430 SVGA3dPrimitiveType primType;
1431 uint32 primitiveCount;
1432
1433 /*
1434 * Optional index buffer. If indexArray.surfaceId is
1435 * SVGA3D_INVALID_ID, we render without an index buffer. Rendering
1436 * without an index buffer is identical to rendering with an index
1437 * buffer containing the sequence [0, 1, 2, 3, ...].
1438 *
1439 * If an index buffer is in use, indexWidth specifies the width in
1440 * bytes of each index value. It must be less than or equal to
1441 * indexArray.stride.
1442 *
1443 * (Currently, the SVGA3D device requires index buffers to be tightly
1444 * packed. In other words, indexWidth == indexArray.stride)
1445 */
1446 SVGA3dArray indexArray;
1447 uint32 indexWidth;
1448
1449 /*
1450 * Optional index bias. This number is added to all indices from
1451 * indexArray before they are used as vertex array indices. This
1452 * can be used in multiple ways:
1453 *
1454 * - When not using an indexArray, this bias can be used to
1455 * specify where in the vertex arrays to begin rendering.
1456 *
1457 * - A positive number here is equivalent to increasing the
1458 * offset in each vertex array.
1459 *
1460 * - A negative number can be used to render using a small
1461 * vertex array and an index buffer that contains large
1462 * values. This may be used by some applications that
1463 * crop a vertex buffer without modifying their index
1464 * buffer.
1465 *
1466 * Note that rendering with a negative bias value may be slower and
1467 * use more memory than rendering with a positive or zero bias.
1468 */
1469 int32 indexBias;
1470} SVGA3dPrimitiveRange;
1471
1472typedef
1473struct {
1474 uint32 cid;
1475 uint32 numVertexDecls;
1476 uint32 numRanges;
1477
1478 /*
1479 * There are two variable size arrays after the
1480 * SVGA3dCmdDrawPrimitives structure. In order,
1481 * they are:
1482 *
1483 * 1. SVGA3dVertexDecl, quantity 'numVertexDecls', but no more than
1484 * SVGA3D_MAX_VERTEX_ARRAYS;
1485 * 2. SVGA3dPrimitiveRange, quantity 'numRanges', but no more than
1486 * SVGA3D_MAX_DRAW_PRIMITIVE_RANGES;
1487 * 3. Optionally, SVGA3dVertexDivisor, quantity 'numVertexDecls' (contains
1488 * the frequency divisor for the corresponding vertex decl).
1489 */
1490} SVGA3dCmdDrawPrimitives; /* SVGA_3D_CMD_DRAWPRIMITIVES */
1491
1492typedef
1493struct {
1494 uint32 stage;
1495 SVGA3dTextureStateName name;
1496 union {
1497 uint32 value;
1498 float floatValue;
1499 };
1500} SVGA3dTextureState;
1501
1502typedef
1503struct {
1504 uint32 cid;
1505 /* Followed by variable number of SVGA3dTextureState structures */
1506} SVGA3dCmdSetTextureState; /* SVGA_3D_CMD_SETTEXTURESTATE */
1507
1508typedef
1509struct {
1510 uint32 cid;
1511 SVGA3dTransformType type;
1512 float matrix[16];
1513} SVGA3dCmdSetTransform; /* SVGA_3D_CMD_SETTRANSFORM */
1514
1515typedef
1516struct {
1517 float min;
1518 float max;
1519} SVGA3dZRange;
1520
1521typedef
1522struct {
1523 uint32 cid;
1524 SVGA3dZRange zRange;
1525} SVGA3dCmdSetZRange; /* SVGA_3D_CMD_SETZRANGE */
1526
1527typedef
1528struct {
1529 float diffuse[4];
1530 float ambient[4];
1531 float specular[4];
1532 float emissive[4];
1533 float shininess;
1534} SVGA3dMaterial;
1535
1536typedef
1537struct {
1538 uint32 cid;
1539 SVGA3dFace face;
1540 SVGA3dMaterial material;
1541} SVGA3dCmdSetMaterial; /* SVGA_3D_CMD_SETMATERIAL */
1542
1543typedef
1544struct {
1545 uint32 cid;
1546 uint32 index;
1547 SVGA3dLightData data;
1548} SVGA3dCmdSetLightData; /* SVGA_3D_CMD_SETLIGHTDATA */
1549
1550typedef
1551struct {
1552 uint32 cid;
1553 uint32 index;
1554 uint32 enabled;
1555} SVGA3dCmdSetLightEnabled; /* SVGA_3D_CMD_SETLIGHTENABLED */
1556
1557typedef
1558struct {
1559 uint32 cid;
1560 SVGA3dRect rect;
1561} SVGA3dCmdSetViewport; /* SVGA_3D_CMD_SETVIEWPORT */
1562
1563typedef
1564struct {
1565 uint32 cid;
1566 SVGA3dRect rect;
1567} SVGA3dCmdSetScissorRect; /* SVGA_3D_CMD_SETSCISSORRECT */
1568
1569typedef
1570struct {
1571 uint32 cid;
1572 uint32 index;
1573 float plane[4];
1574} SVGA3dCmdSetClipPlane; /* SVGA_3D_CMD_SETCLIPPLANE */
1575
1576typedef
1577struct {
1578 uint32 cid;
1579 uint32 shid;
1580 SVGA3dShaderType type;
1581 /* Followed by variable number of DWORDs for shader bycode */
1582} SVGA3dCmdDefineShader; /* SVGA_3D_CMD_SHADER_DEFINE */
1583
1584typedef
1585struct {
1586 uint32 cid;
1587 uint32 shid;
1588 SVGA3dShaderType type;
1589} SVGA3dCmdDestroyShader; /* SVGA_3D_CMD_SHADER_DESTROY */
1590
1591typedef
1592struct {
1593 uint32 cid;
1594 uint32 reg; /* register number */
1595 SVGA3dShaderType type;
1596 SVGA3dShaderConstType ctype;
1597 uint32 values[4];
1598} SVGA3dCmdSetShaderConst; /* SVGA_3D_CMD_SET_SHADER_CONST */
1599
1600typedef
1601struct {
1602 uint32 cid;
1603 SVGA3dShaderType type;
1604 uint32 shid;
1605} SVGA3dCmdSetShader; /* SVGA_3D_CMD_SET_SHADER */
1606
1607typedef
1608struct {
1609 uint32 cid;
1610 SVGA3dQueryType type;
1611} SVGA3dCmdBeginQuery; /* SVGA_3D_CMD_BEGIN_QUERY */
1612
1613typedef
1614struct {
1615 uint32 cid;
1616 SVGA3dQueryType type;
1617 SVGAGuestPtr guestResult; /* Points to an SVGA3dQueryResult structure */
1618} SVGA3dCmdEndQuery; /* SVGA_3D_CMD_END_QUERY */
1619
1620typedef
1621struct {
1622 uint32 cid; /* Same parameters passed to END_QUERY */
1623 SVGA3dQueryType type;
1624 SVGAGuestPtr guestResult;
1625} SVGA3dCmdWaitForQuery; /* SVGA_3D_CMD_WAIT_FOR_QUERY */
1626
1627typedef
1628struct {
1629 uint32 totalSize; /* Set by guest before query is ended. */
1630 SVGA3dQueryState state; /* Set by host or guest. See SVGA3dQueryState. */
1631 union { /* Set by host on exit from PENDING state */
1632 uint32 result32;
1633 };
1634} SVGA3dQueryResult;
1635
1636/*
1637 * SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN --
1638 *
1639 * This is a blit from an SVGA3D surface to a Screen Object. Just
1640 * like GMR-to-screen blits, this blit may be directed at a
1641 * specific screen or to the virtual coordinate space.
1642 *
1643 * The blit copies from a rectangular region of an SVGA3D surface
1644 * image to a rectangular region of a screen or screens.
1645 *
1646 * This command takes an optional variable-length list of clipping
1647 * rectangles after the body of the command. If no rectangles are
1648 * specified, there is no clipping region. The entire destRect is
1649 * drawn to. If one or more rectangles are included, they describe
1650 * a clipping region. The clip rectangle coordinates are measured
1651 * relative to the top-left corner of destRect.
1652 *
1653 * This clipping region serves multiple purposes:
1654 *
1655 * - It can be used to perform an irregularly shaped blit more
1656 * efficiently than by issuing many separate blit commands.
1657 *
1658 * - It is equivalent to allowing blits with non-integer
1659 * source coordinates. You could blit just one half-pixel
1660 * of a source, for example, by specifying a larger
1661 * destination rectangle than you need, then removing
1662 * part of it using a clip rectangle.
1663 *
1664 * Availability:
1665 * SVGA_FIFO_CAP_SCREEN_OBJECT
1666 *
1667 * Limitations:
1668 *
1669 * - Currently, no backend supports blits from a mipmap or face
1670 * other than the first one.
1671 */
1672
1673typedef
1674struct {
1675 SVGA3dSurfaceImageId srcImage;
1676 SVGASignedRect srcRect;
1677 uint32 destScreenId; /* Screen ID or SVGA_ID_INVALID for virt. coords */
1678 SVGASignedRect destRect; /* Supports scaling if src/rest different size */
1679 /* Clipping: zero or more SVGASignedRects follow */
1680} SVGA3dCmdBlitSurfaceToScreen; /* SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN */
1681
1682
1683/*
1684 * Capability query index.
1685 *
1686 * Notes:
1687 *
1688 * 1. SVGA3D_DEVCAP_MAX_TEXTURES reflects the maximum number of
1689 * fixed-function texture units available. Each of these units
1690 * work in both FFP and Shader modes, and they support texture
1691 * transforms and texture coordinates. The host may have additional
1692 * texture image units that are only usable with shaders.
1693 *
1694 * 2. The BUFFER_FORMAT capabilities are deprecated, and they always
1695 * return TRUE. Even on physical hardware that does not support
1696 * these formats natively, the SVGA3D device will provide an emulation
1697 * which should be invisible to the guest OS.
1698 *
1699 * In general, the SVGA3D device should support any operation on
1700 * any surface format, it just may perform some of these
1701 * operations in software depending on the capabilities of the
1702 * available physical hardware.
1703 *
1704 * XXX: In the future, we will add capabilities that describe in
1705 * detail what formats are supported in hardware for what kinds
1706 * of operations.
1707 */
1708
1709typedef enum {
1710 SVGA3D_DEVCAP_3D = 0,
1711 SVGA3D_DEVCAP_MAX_LIGHTS = 1,
1712 SVGA3D_DEVCAP_MAX_TEXTURES = 2, /* See note (1) */
1713 SVGA3D_DEVCAP_MAX_CLIP_PLANES = 3,
1714 SVGA3D_DEVCAP_VERTEX_SHADER_VERSION = 4,
1715 SVGA3D_DEVCAP_VERTEX_SHADER = 5,
1716 SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION = 6,
1717 SVGA3D_DEVCAP_FRAGMENT_SHADER = 7,
1718 SVGA3D_DEVCAP_MAX_RENDER_TARGETS = 8,
1719 SVGA3D_DEVCAP_S23E8_TEXTURES = 9,
1720 SVGA3D_DEVCAP_S10E5_TEXTURES = 10,
1721 SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = 11,
1722 SVGA3D_DEVCAP_D16_BUFFER_FORMAT = 12, /* See note (2) */
1723 SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT = 13, /* See note (2) */
1724 SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT = 14, /* See note (2) */
1725 SVGA3D_DEVCAP_QUERY_TYPES = 15,
1726 SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = 16,
1727 SVGA3D_DEVCAP_MAX_POINT_SIZE = 17,
1728 SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = 18,
1729 SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH = 19,
1730 SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT = 20,
1731 SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = 21,
1732 SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = 22,
1733 SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO = 23,
1734 SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = 24,
1735 SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = 25,
1736 SVGA3D_DEVCAP_MAX_VERTEX_INDEX = 26,
1737 SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS = 27,
1738 SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS = 28,
1739 SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS = 29,
1740 SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS = 30,
1741 SVGA3D_DEVCAP_TEXTURE_OPS = 31,
1742 SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = 32,
1743 SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = 33,
1744 SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = 34,
1745 SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = 35,
1746 SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = 36,
1747 SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = 37,
1748 SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = 38,
1749 SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = 39,
1750 SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = 40,
1751 SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = 41,
1752 SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = 42,
1753 SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = 43,
1754 SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = 44,
1755 SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = 45,
1756 SVGA3D_DEVCAP_SURFACEFMT_DXT1 = 46,
1757 SVGA3D_DEVCAP_SURFACEFMT_DXT2 = 47,
1758 SVGA3D_DEVCAP_SURFACEFMT_DXT3 = 48,
1759 SVGA3D_DEVCAP_SURFACEFMT_DXT4 = 49,
1760 SVGA3D_DEVCAP_SURFACEFMT_DXT5 = 50,
1761 SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = 51,
1762 SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = 52,
1763 SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = 53,
1764 SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = 54,
1765 SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = 55,
1766 SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = 56,
1767 SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = 57,
1768 SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = 58,
1769 SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = 59,
1770 SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = 60,
1771 SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = 61,
1772 SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES = 63,
1773
1774 /*
1775 * Note that MAX_SIMULTANEOUS_RENDER_TARGETS is a maximum count of color
1776 * render targets. This does no include the depth or stencil targets.
1777 */
1778 SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS = 64,
1779
1780 SVGA3D_DEVCAP_SURFACEFMT_V16U16 = 65,
1781 SVGA3D_DEVCAP_SURFACEFMT_G16R16 = 66,
1782 SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = 67,
1783 SVGA3D_DEVCAP_SURFACEFMT_UYVY = 68,
1784 SVGA3D_DEVCAP_SURFACEFMT_YUY2 = 69,
1785
1786 /*
1787 * Don't add new caps into the previous section; the values in this
1788 * enumeration must not change. You can put new values right before
1789 * SVGA3D_DEVCAP_MAX.
1790 */
1791 SVGA3D_DEVCAP_MAX /* This must be the last index. */
1792} SVGA3dDevCapIndex;
1793
1794typedef union {
1795 Bool b;
1796 uint32 u;
1797 int32 i;
1798 float f;
1799} SVGA3dDevCapResult;
1800
1801#endif /* _SVGA3D_REG_H_ */
diff --git a/vmwgfx/vmwgfx_crtc.c b/vmwgfx/vmwgfx_crtc.c
new file mode 100644
index 0000000..eaf87b2
--- /dev/null
+++ b/vmwgfx/vmwgfx_crtc.c
@@ -0,0 +1,455 @@
1/*
2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * Copyright 2011 VMWare, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 *
27 * Author: Alan Hourihane <alanh@tungstengraphics.com>
28 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
29 * Author: Thomas Hellstrom <thellstrom@vmware.com>
30 */
31
32#include <unistd.h>
33#include <string.h>
34#include <assert.h>
35#include <stdlib.h>
36#include <math.h>
37#include <stdint.h>
38
39#include "xorg-server.h"
40#include <xf86.h>
41#include <xf86i2c.h>
42#include <xf86Crtc.h>
43#include <cursorstr.h>
44#include "vmwgfx_driver.h"
45#include "xf86Modes.h"
46#include "vmwgfx_saa.h"
47
48#ifdef HAVE_XEXTPROTO_71
49#include <X11/extensions/dpmsconst.h>
50#else
51#define DPMS_SERVER
52#include <X11/extensions/dpms.h>
53#endif
54
55struct crtc_private
56{
57 drmModeCrtcPtr drm_crtc;
58
59 /* hwcursor */
60 struct vmwgfx_dmabuf *cursor_bo;
61 uint32_t scanout_id;
62 unsigned cursor_handle;
63
64 /* Scanout info for pixmaps */
65 struct vmwgfx_screen_entry entry;
66};
67
68static void
69crtc_dpms(xf86CrtcPtr crtc, int mode)
70{
71 struct crtc_private *crtcp = crtc->driver_private;
72 /* ScrnInfoPtr pScrn = crtc->scrn; */
73
74 switch (mode) {
75 case DPMSModeOn:
76 case DPMSModeStandby:
77 case DPMSModeSuspend:
78 break;
79 case DPMSModeOff:
80
81 /*
82 * The xf86 modesetting code uses DPMS off to turn off
83 * crtcs that are not enabled. However, the DPMS code does the same.
84 * We assume, that if we get this call with the crtc not enabled,
85 * it's a permanent switch off which will only be reversed by a
86 * major modeset.
87 *
88 * If it's a DPMS switch off, (crtc->enabled == TRUE),
89 * the crtc may be turned on again by
90 * another dpms call, so don't release the scanout pixmap ref.
91 */
92 if (!crtc->enabled && crtcp->entry.pixmap) {
93 vmwgfx_scanout_unref(&crtcp->entry);
94 }
95 break;
96 }
97}
98
99/*
100 * Disable outputs and crtcs and drop the scanout reference from
101 * scanout pixmaps. This will essentialy free all kms fb allocations.
102 */
103
104void
105vmwgfx_disable_scanout(ScrnInfoPtr pScrn)
106{
107 int i;
108 Bool save_enabled;
109 xf86CrtcPtr crtc;
110 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
111
112 xf86DPMSSet(pScrn, DPMSModeOff, 0);
113 for (i=0; i < config->num_crtc; ++i) {
114 crtc = config->crtc[i];
115 save_enabled = crtc->enabled;
116 crtc->enabled = FALSE;
117 crtc_dpms(crtc, DPMSModeOff);
118 crtc->enabled = save_enabled;
119 }
120 xf86RotateFreeShadow(pScrn);
121}
122
123static Bool
124crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
125 Rotation rotation, int x, int y)
126{
127 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
128 modesettingPtr ms = modesettingPTR(crtc->scrn);
129 ScreenPtr pScreen = crtc->scrn->pScreen;
130 xf86OutputPtr output = NULL;
131 struct crtc_private *crtcp = crtc->driver_private;
132 drmModeCrtcPtr drm_crtc = crtcp->drm_crtc;
133 drmModeModeInfo drm_mode;
134 int i, ret;
135 unsigned int connector_id;
136 PixmapPtr pixmap;
137
138 for (i = 0; i < config->num_output; output = NULL, i++) {
139 output = config->output[i];
140
141 if (output->crtc == crtc)
142 break;
143 }
144
145 if (!output) {
146 LogMessage(X_ERROR, "No output for this crtc.\n");
147 return FALSE;
148 }
149
150 connector_id = xorg_output_get_id(output);
151
152 drm_mode.clock = mode->Clock;
153 drm_mode.hdisplay = mode->HDisplay;
154 drm_mode.hsync_start = mode->HSyncStart;
155 drm_mode.hsync_end = mode->HSyncEnd;
156 drm_mode.htotal = mode->HTotal;
157 drm_mode.vdisplay = mode->VDisplay;
158 drm_mode.vsync_start = mode->VSyncStart;
159 drm_mode.vsync_end = mode->VSyncEnd;
160 drm_mode.vtotal = mode->VTotal;
161 drm_mode.flags = mode->Flags;
162 drm_mode.hskew = mode->HSkew;
163 drm_mode.vscan = mode->VScan;
164 drm_mode.vrefresh = mode->VRefresh;
165 if (!mode->name)
166 xf86SetModeDefaultName(mode);
167 strncpy(drm_mode.name, mode->name, DRM_DISPLAY_MODE_LEN - 1);
168 drm_mode.name[DRM_DISPLAY_MODE_LEN - 1] = '\0';
169
170 /*
171 * Check if we need to scanout from something else than the root
172 * pixmap. In that case, xf86CrtcRotate will take care of allocating
173 * new opaque scanout buffer data "crtc->rotatedData".
174 * However, it will not wrap
175 * that data into pixmaps until the first rotated damage composite.
176 * In out case, the buffer data is actually already a pixmap.
177 */
178
179 if (!xf86CrtcRotate(crtc))
180 return FALSE;
181
182 if (crtc->transform_in_use && crtc->rotatedData) {
183 x = 0;
184 y = 0;
185 pixmap = (PixmapPtr) crtc->rotatedData;
186 } else
187 pixmap = pScreen->GetScreenPixmap(pScreen);
188
189 if (crtcp->entry.pixmap != pixmap) {
190 if (crtcp->entry.pixmap)
191 vmwgfx_scanout_unref(&crtcp->entry);
192
193 crtcp->entry.pixmap = pixmap;
194 crtcp->scanout_id = vmwgfx_scanout_ref(&crtcp->entry);
195 if (crtcp->scanout_id == -1) {
196 LogMessage(X_ERROR, "Failed to convert pixmap to scanout.\n");
197 return FALSE;
198 }
199 }
200 ret = drmModeSetCrtc(ms->fd, drm_crtc->crtc_id, crtcp->scanout_id, x, y,
201 &connector_id, 1, &drm_mode);
202 if (ret)
203 return FALSE;
204
205 vmwgfx_scanout_refresh(pixmap);
206
207 /* Only set gamma when needed, to avoid unneeded delays. */
208#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
209 if (!crtc->active && crtc->version >= 3)
210 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
211 crtc->gamma_blue, crtc->gamma_size);
212 crtc->active = TRUE;
213#endif
214
215 return TRUE;
216}
217
218static void
219crtc_gamma_set(xf86CrtcPtr crtc, CARD16 * red, CARD16 * green, CARD16 * blue,
220 int size)
221{
222 modesettingPtr ms = modesettingPTR(crtc->scrn);
223 struct crtc_private *crtcp = crtc->driver_private;
224
225 drmModeCrtcSetGamma(ms->fd, crtcp->drm_crtc->crtc_id, size, red, green, blue);
226}
227
228static void *
229crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
230{
231 ScreenPtr pScreen = crtc->scrn->pScreen;
232 PixmapPtr rootpix = pScreen->GetScreenPixmap(pScreen);
233
234 /*
235 * Use the same depth as for the root pixmap.
236 * The associated kms fb will be created on demand once this pixmap
237 * is used as scanout by a crtc.
238 */
239
240 return pScreen->CreatePixmap(pScreen, width, height,
241 rootpix->drawable.depth, 0);
242}
243
244static PixmapPtr
245crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
246{
247 return (PixmapPtr) data;
248}
249
250static void
251crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
252{
253 ScreenPtr pScreen = rotate_pixmap->drawable.pScreen;
254
255 pScreen->DestroyPixmap(rotate_pixmap);
256}
257
258
259/*
260 * Cursor functions
261 */
262
263static void
264crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
265{
266 /* XXX: See if this one is needed, as we only support ARGB cursors */
267}
268
269static void
270crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
271{
272 modesettingPtr ms = modesettingPTR(crtc->scrn);
273 struct crtc_private *crtcp = crtc->driver_private;
274
275 drmModeMoveCursor(ms->fd, crtcp->drm_crtc->crtc_id, x, y);
276}
277
278static void
279crtc_load_cursor_argb_kms(xf86CrtcPtr crtc, CARD32 * image)
280{
281 modesettingPtr ms = modesettingPTR(crtc->scrn);
282 struct crtc_private *crtcp = crtc->driver_private;
283 unsigned char *ptr;
284 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
285 CursorPtr c = config->cursor;
286
287 if (vmwgfx_cursor_bypass(ms->fd, c->bits->xhot, c->bits->yhot) != 0) {
288 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
289 "Failed to set VMWare cursor bypass.\n");
290 }
291
292 if (!crtcp->cursor_bo) {
293 size_t size = 64*64*4;
294 crtcp->cursor_bo = vmwgfx_dmabuf_alloc(ms->fd, size);
295 if (!crtcp->cursor_bo)
296 return;
297 crtcp->cursor_handle = crtcp->cursor_bo->handle;
298 }
299
300 ptr = vmwgfx_dmabuf_map(crtcp->cursor_bo);
301 if (ptr) {
302 memcpy(ptr, image, 64*64*4);
303 vmwgfx_dmabuf_unmap(crtcp->cursor_bo);
304 }
305
306 if (crtc->cursor_shown)
307 drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id,
308 crtcp->cursor_handle, 64, 64);
309
310 return;
311}
312
313static void
314crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image)
315{
316 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
317 modesettingPtr ms = modesettingPTR(crtc->scrn);
318
319 /* Older X servers have cursor reference counting bugs leading to use of
320 * freed memory and consequently random crashes. Should be fixed as of
321 * xserver 1.8, but this workaround shouldn't hurt anyway.
322 */
323 if (config->cursor)
324 config->cursor->refcnt++;
325
326 if (ms->cursor)
327 FreeCursor(ms->cursor, None);
328
329 ms->cursor = config->cursor;
330 crtc_load_cursor_argb_kms(crtc, image);
331}
332
333static void
334crtc_show_cursor(xf86CrtcPtr crtc)
335{
336 modesettingPtr ms = modesettingPTR(crtc->scrn);
337 struct crtc_private *crtcp = crtc->driver_private;
338
339 if (crtcp->cursor_bo)
340 drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id,
341 crtcp->cursor_handle, 64, 64);
342}
343
344static void
345crtc_hide_cursor(xf86CrtcPtr crtc)
346{
347 modesettingPtr ms = modesettingPTR(crtc->scrn);
348 struct crtc_private *crtcp = crtc->driver_private;
349
350 drmModeSetCursor(ms->fd, crtcp->drm_crtc->crtc_id, 0, 0, 0);
351}
352
353/**
354 * Called at vt leave
355 */
356void
357xorg_crtc_cursor_destroy(xf86CrtcPtr crtc)
358{
359 struct crtc_private *crtcp = crtc->driver_private;
360
361 if (crtcp->cursor_bo) {
362 vmwgfx_dmabuf_destroy(crtcp->cursor_bo);
363 crtcp->cursor_bo = NULL;
364 }
365}
366
367/*
368 * Misc functions
369 */
370
371static void
372crtc_destroy(xf86CrtcPtr crtc)
373{
374 struct crtc_private *crtcp = crtc->driver_private;
375
376 if (!WSBMLISTEMPTY(&crtcp->entry.scanout_head))
377 vmwgfx_scanout_unref(&crtcp->entry);
378
379 xorg_crtc_cursor_destroy(crtc);
380
381 drmModeFreeCrtc(crtcp->drm_crtc);
382
383 free(crtcp);
384 crtc->driver_private = NULL;
385}
386
387static const xf86CrtcFuncsRec crtc_funcs = {
388 .dpms = crtc_dpms,
389 .set_mode_major = crtc_set_mode_major,
390
391 .set_cursor_colors = crtc_set_cursor_colors,
392 .set_cursor_position = crtc_set_cursor_position,
393 .show_cursor = crtc_show_cursor,
394 .hide_cursor = crtc_hide_cursor,
395 .load_cursor_argb = crtc_load_cursor_argb,
396
397 .shadow_create = crtc_shadow_create,
398 .shadow_allocate = crtc_shadow_allocate,
399 .shadow_destroy = crtc_shadow_destroy,
400
401 .gamma_set = crtc_gamma_set,
402 .destroy = crtc_destroy,
403};
404
405void
406xorg_crtc_init(ScrnInfoPtr pScrn)
407{
408 modesettingPtr ms = modesettingPTR(pScrn);
409 xf86CrtcPtr crtc;
410 drmModeResPtr res;
411 drmModeCrtcPtr drm_crtc = NULL;
412 struct crtc_private *crtcp;
413 int c;
414
415 res = drmModeGetResources(ms->fd);
416 if (res == 0) {
417 ErrorF("Failed drmModeGetResources %d\n", errno);
418 return;
419 }
420
421 for (c = 0; c < res->count_crtcs; c++) {
422 drm_crtc = drmModeGetCrtc(ms->fd, res->crtcs[c]);
423
424 if (!drm_crtc)
425 continue;
426
427 crtc = xf86CrtcCreate(pScrn, &crtc_funcs);
428 if (crtc == NULL)
429 goto out;
430
431 crtcp = calloc(1, sizeof(struct crtc_private));
432 if (!crtcp) {
433 xf86CrtcDestroy(crtc);
434 goto out;
435 }
436
437 crtcp->drm_crtc = drm_crtc;
438 crtcp->entry.pixmap = NULL;
439 WSBMINITLISTHEAD(&crtcp->entry.scanout_head);
440
441 crtc->driver_private = crtcp;
442 }
443
444 out:
445 drmModeFreeResources(res);
446}
447
448PixmapPtr
449crtc_get_scanout(xf86CrtcPtr crtc)
450{
451 struct crtc_private *crtcp = crtc->driver_private;
452 return crtcp->entry.pixmap;
453}
454
455/* vim: set sw=4 ts=8 sts=4: */
diff --git a/vmwgfx/vmwgfx_ctrl.c b/vmwgfx/vmwgfx_ctrl.c
new file mode 100644
index 0000000..3185879
--- /dev/null
+++ b/vmwgfx/vmwgfx_ctrl.c
@@ -0,0 +1,523 @@
1/*
2 * Copyright 2006-2011 by VMware, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28/*
29 * vmwarectrl.c --
30 *
31 * The implementation of the VMWARE_CTRL protocol extension that
32 * allows X clients to communicate with the driver.
33 */
34
35#include <xorg-server.h>
36#include "dixstruct.h"
37#include "extnsionst.h"
38#include <X11/X.h>
39#include <X11/extensions/panoramiXproto.h>
40
41#include "vmwarectrlproto.h"
42#include "vmwgfx_driver.h"
43#include "vmwgfx_drmi.h"
44
45/*
46 *----------------------------------------------------------------------------
47 *
48 * VMwareCtrlQueryVersion --
49 *
50 * Implementation of QueryVersion command handler. Initialises and
51 * sends a reply.
52 *
53 * Results:
54 * Standard response codes.
55 *
56 * Side effects:
57 * Writes reply to client
58 *
59 *----------------------------------------------------------------------------
60 */
61
62static int
63VMwareCtrlQueryVersion(ClientPtr client)
64{
65 xVMwareCtrlQueryVersionReply rep = { 0, };
66 register int n;
67
68 REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
69
70 rep.type = X_Reply;
71 rep.length = 0;
72 rep.sequenceNumber = client->sequence;
73 rep.majorVersion = VMWARE_CTRL_MAJOR_VERSION;
74 rep.minorVersion = VMWARE_CTRL_MINOR_VERSION;
75 if (client->swapped) {
76 swaps(&rep.sequenceNumber, n);
77 swapl(&rep.length, n);
78 swapl(&rep.majorVersion, n);
79 swapl(&rep.minorVersion, n);
80 }
81 WriteToClient(client, sizeof(xVMwareCtrlQueryVersionReply), (char *)&rep);
82
83 return client->noClientException;
84}
85
86
87/*
88 *----------------------------------------------------------------------------
89 *
90 * VMwareCtrlDoSetRes --
91 *
92 * Set the custom resolution into the mode list.
93 *
94 * This is done by alternately updating one of two dynamic modes. It is
95 * done this way because the server gets upset if you try to switch
96 * to a new resolution that has the same index as the current one.
97 *
98 * Results:
99 * TRUE on success, FALSE otherwise.
100 *
101 * Side effects:
102 * One dynamic mode will be updated if successful.
103 *
104 *----------------------------------------------------------------------------
105 */
106
107static Bool
108VMwareCtrlDoSetRes(ScrnInfoPtr pScrn,
109 CARD32 x,
110 CARD32 y)
111{
112 modesettingPtr ms = modesettingPTR(pScrn);
113 struct drm_vmw_rect rect;
114 int ret;
115
116 rect.x = 0;
117 rect.y = 0;
118 rect.w = x;
119 rect.h = y;
120
121 ret = vmwgfx_update_gui_layout(ms->fd, 1, &rect);
122 return (ret == 0);
123}
124
125
126/*
127 *----------------------------------------------------------------------------
128 *
129 * VMwareCtrlSetRes --
130 *
131 * Implementation of SetRes command handler. Initialises and sends a
132 * reply.
133 *
134 * Results:
135 * Standard response codes.
136 *
137 * Side effects:
138 * Writes reply to client
139 *
140 *----------------------------------------------------------------------------
141 */
142
143static int
144VMwareCtrlSetRes(ClientPtr client)
145{
146 REQUEST(xVMwareCtrlSetResReq);
147 xVMwareCtrlSetResReply rep = { 0, };
148 ScrnInfoPtr pScrn;
149 ExtensionEntry *ext;
150 register int n;
151
152 REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq);
153
154 if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
155 return BadMatch;
156 }
157
158 pScrn = ext->extPrivate;
159 if (pScrn->scrnIndex != stuff->screen) {
160 return BadMatch;
161 }
162
163 if (!VMwareCtrlDoSetRes(pScrn, stuff->x, stuff->y)) {
164 return BadValue;
165 }
166
167 rep.type = X_Reply;
168 rep.length = (sizeof(xVMwareCtrlSetResReply) - sizeof(xGenericReply)) >> 2;
169 rep.sequenceNumber = client->sequence;
170 rep.screen = stuff->screen;
171 rep.x = stuff->x;
172 rep.y = stuff->y;
173 if (client->swapped) {
174 swaps(&rep.sequenceNumber, n);
175 swapl(&rep.length, n);
176 swapl(&rep.screen, n);
177 swapl(&rep.x, n);
178 swapl(&rep.y, n);
179 }
180 WriteToClient(client, sizeof(xVMwareCtrlSetResReply), (char *)&rep);
181
182 return client->noClientException;
183}
184
185
186/*
187 *----------------------------------------------------------------------------
188 *
189 * VMwareCtrlDoSetTopology --
190 *
191 * Set the custom topology and set a dynamic mode to the bounding box
192 * of the passed topology. If a topology is already pending, then do
193 * nothing but do not return failure.
194 *
195 * Results:
196 * TRUE on success, FALSE otherwise.
197 *
198 * Side effects:
199 * One dynamic mode and the pending xinerama state will be updated if
200 * successful.
201 *
202 *----------------------------------------------------------------------------
203 */
204
205static Bool
206VMwareCtrlDoSetTopology(ScrnInfoPtr pScrn,
207 xXineramaScreenInfo *extents,
208 unsigned long number)
209{
210 modesettingPtr ms = modesettingPTR(pScrn);
211 struct drm_vmw_rect *rects;
212 int i;
213 int ret;
214
215 rects = calloc(number, sizeof(*rects));
216 if (!rects)
217 return FALSE;
218
219 for (i = 0; i < number; i++) {
220 rects[i].x = extents[i].x_org;
221 rects[i].y = extents[i].y_org;
222 rects[i].w = extents[i].width;
223 rects[i].h = extents[i].height;
224 }
225
226 ret = vmwgfx_update_gui_layout(ms->fd, number, rects);
227
228 free(rects);
229 return (ret == 0);
230}
231
232
233/*
234 *----------------------------------------------------------------------------
235 *
236 * VMwareCtrlSetTopology --
237 *
238 * Implementation of SetTopology command handler. Initialises and sends a
239 * reply.
240 *
241 * Results:
242 * Standard response codes.
243 *
244 * Side effects:
245 * Writes reply to client
246 *
247 *----------------------------------------------------------------------------
248 */
249
250static int
251VMwareCtrlSetTopology(ClientPtr client)
252{
253 REQUEST(xVMwareCtrlSetTopologyReq);
254 xVMwareCtrlSetTopologyReply rep = { 0, };
255 ScrnInfoPtr pScrn;
256 ExtensionEntry *ext;
257 register int n;
258 xXineramaScreenInfo *extents;
259
260 REQUEST_AT_LEAST_SIZE(xVMwareCtrlSetTopologyReq);
261
262 if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
263 return BadMatch;
264 }
265
266 pScrn = ext->extPrivate;
267 if (pScrn->scrnIndex != stuff->screen) {
268 return BadMatch;
269 }
270
271 extents = (xXineramaScreenInfo *)(stuff + 1);
272 if (!VMwareCtrlDoSetTopology(pScrn, extents, stuff->number)) {
273 return BadValue;
274 }
275
276 rep.type = X_Reply;
277 rep.length = (sizeof(xVMwareCtrlSetTopologyReply) - sizeof(xGenericReply)) >> 2;
278 rep.sequenceNumber = client->sequence;
279 rep.screen = stuff->screen;
280 if (client->swapped) {
281 swaps(&rep.sequenceNumber, n);
282 swapl(&rep.length, n);
283 swapl(&rep.screen, n);
284 }
285 WriteToClient(client, sizeof(xVMwareCtrlSetTopologyReply), (char *)&rep);
286
287 return client->noClientException;
288}
289
290
291/*
292 *----------------------------------------------------------------------------
293 *
294 * VMwareCtrlDispatch --
295 *
296 * Dispatcher for VMWARE_CTRL commands. Calls the correct handler for
297 * each command type.
298 *
299 * Results:
300 * Standard response codes.
301 *
302 * Side effects:
303 * Side effects of individual command handlers.
304 *
305 *----------------------------------------------------------------------------
306 */
307
308static int
309VMwareCtrlDispatch(ClientPtr client)
310{
311 REQUEST(xReq);
312
313 switch(stuff->data) {
314 case X_VMwareCtrlQueryVersion:
315 return VMwareCtrlQueryVersion(client);
316 case X_VMwareCtrlSetRes:
317 return VMwareCtrlSetRes(client);
318 case X_VMwareCtrlSetTopology:
319 return VMwareCtrlSetTopology(client);
320 }
321 return BadRequest;
322}
323
324
325/*
326 *----------------------------------------------------------------------------
327 *
328 * SVMwareCtrlQueryVersion --
329 *
330 * Wrapper for QueryVersion handler that handles input from other-endian
331 * clients.
332 *
333 * Results:
334 * Standard response codes.
335 *
336 * Side effects:
337 * Side effects of unswapped implementation.
338 *
339 *----------------------------------------------------------------------------
340 */
341
342static int
343SVMwareCtrlQueryVersion(ClientPtr client)
344{
345 register int n;
346
347 REQUEST(xVMwareCtrlQueryVersionReq);
348 REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
349
350 swaps(&stuff->length, n);
351
352 return VMwareCtrlQueryVersion(client);
353}
354
355
356/*
357 *----------------------------------------------------------------------------
358 *
359 * SVMwareCtrlSetRes --
360 *
361 * Wrapper for SetRes handler that handles input from other-endian
362 * clients.
363 *
364 * Results:
365 * Standard response codes.
366 *
367 * Side effects:
368 * Side effects of unswapped implementation.
369 *
370 *----------------------------------------------------------------------------
371 */
372
373static int
374SVMwareCtrlSetRes(ClientPtr client)
375{
376 register int n;
377
378 REQUEST(xVMwareCtrlSetResReq);
379 REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq);
380
381 swaps(&stuff->length, n);
382 swapl(&stuff->screen, n);
383 swapl(&stuff->x, n);
384 swapl(&stuff->y, n);
385
386 return VMwareCtrlSetRes(client);
387}
388
389
390/*
391 *----------------------------------------------------------------------------
392 *
393 * SVMwareCtrlSetTopology --
394 *
395 * Wrapper for SetTopology handler that handles input from other-endian
396 * clients.
397 *
398 * Results:
399 * Standard response codes.
400 *
401 * Side effects:
402 * Side effects of unswapped implementation.
403 *
404 *----------------------------------------------------------------------------
405 */
406
407static int
408SVMwareCtrlSetTopology(ClientPtr client)
409{
410 register int n;
411
412 REQUEST(xVMwareCtrlSetTopologyReq);
413 REQUEST_SIZE_MATCH(xVMwareCtrlSetTopologyReq);
414
415 swaps(&stuff->length, n);
416 swapl(&stuff->screen, n);
417 swapl(&stuff->number, n);
418 /* Each extent is a struct of shorts. */
419 SwapRestS(stuff);
420
421 return VMwareCtrlSetTopology(client);
422}
423
424
425/*
426 *----------------------------------------------------------------------------
427 *
428 * SVMwareCtrlDispatch --
429 *
430 * Wrapper for dispatcher that handles input from other-endian clients.
431 *
432 * Results:
433 * Standard response codes.
434 *
435 * Side effects:
436 * Side effects of individual command handlers.
437 *
438 *----------------------------------------------------------------------------
439 */
440
441static int
442SVMwareCtrlDispatch(ClientPtr client)
443{
444 REQUEST(xReq);
445
446 switch(stuff->data) {
447 case X_VMwareCtrlQueryVersion:
448 return SVMwareCtrlQueryVersion(client);
449 case X_VMwareCtrlSetRes:
450 return SVMwareCtrlSetRes(client);
451 case X_VMwareCtrlSetTopology:
452 return SVMwareCtrlSetTopology(client);
453 }
454 return BadRequest;
455}
456
457
458/*
459 *----------------------------------------------------------------------------
460 *
461 * VMwareCtrlResetProc --
462 *
463 * Cleanup handler called when the extension is removed.
464 *
465 * Results:
466 * None
467 *
468 * Side effects:
469 * None
470 *
471 *----------------------------------------------------------------------------
472 */
473
474static void
475VMwareCtrlResetProc(ExtensionEntry* extEntry)
476{
477 /* Currently, no cleanup is necessary. */
478}
479
480
481/*
482 *----------------------------------------------------------------------------
483 *
484 * VMwareCtrl_ExitInit --
485 *
486 * Initialiser for the VMWARE_CTRL protocol extension.
487 *
488 * Results:
489 * None.
490 *
491 * Side effects:
492 * Protocol extension will be registered if successful.
493 *
494 *----------------------------------------------------------------------------
495 */
496
497void
498vmw_ctrl_ext_init(ScrnInfoPtr pScrn)
499{
500 ExtensionEntry *myext;
501
502 if (!(myext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
503 if (!(myext = AddExtension(VMWARE_CTRL_PROTOCOL_NAME, 0, 0,
504 VMwareCtrlDispatch,
505 SVMwareCtrlDispatch,
506 VMwareCtrlResetProc,
507 StandardMinorOpcode))) {
508 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
509 "Failed to add VMWARE_CTRL extension\n");
510 return;
511 }
512
513 /*
514 * For now, only support one screen as that's all the virtual
515 * hardware supports.
516 */
517 myext->extPrivate = pScrn;
518
519 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
520 "Initialized VMWARE_CTRL extension version %d.%d\n",
521 VMWARE_CTRL_MAJOR_VERSION, VMWARE_CTRL_MINOR_VERSION);
522 }
523}
diff --git a/vmwgfx/vmwgfx_ctrl.h b/vmwgfx/vmwgfx_ctrl.h
new file mode 100644
index 0000000..8fedbce
--- /dev/null
+++ b/vmwgfx/vmwgfx_ctrl.h
@@ -0,0 +1,48 @@
1/*
2 * Copyright 2006 by VMware, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28/*
29 * vmwgfx_ctrl.h --
30 *
31 * The definitions used by the VMWARE_CTRL protocol extension that
32 * allows X clients to communicate with the driver.
33 */
34
35
36#ifndef _VMWGFX_CTRL_H_
37#define _VMWGFX_CTRL_H_
38
39#define VMWARE_CTRL_PROTOCOL_NAME "VMWARE_CTRL"
40
41#define VMWARE_CTRL_MAJOR_VERSION 0
42#define VMWARE_CTRL_MINOR_VERSION 2
43
44#define X_VMwareCtrlQueryVersion 0
45#define X_VMwareCtrlSetRes 1
46#define X_VMwareCtrlSetTopology 2
47
48#endif /* _VMW_CTRL_H_ */
diff --git a/vmwgfx/vmwgfx_dri2.c b/vmwgfx/vmwgfx_dri2.c
new file mode 100644
index 0000000..1b82ac4
--- /dev/null
+++ b/vmwgfx/vmwgfx_dri2.c
@@ -0,0 +1,426 @@
1/*
2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * Copyright 2011 VMWare, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 *
27 * Author: Alan Hourihane <alanh@tungstengraphics.com>
28 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
29 * Author: Thomas Hellstrom <thellstrom@vmware.com>
30 *
31 */
32
33#include "xorg-server.h"
34#include "xf86.h"
35#include "xf86_OSproc.h"
36
37#include "vmwgfx_driver.h"
38#include "../saa/saa.h"
39
40#include "dri2.h"
41#include "gcstruct.h"
42#include "gc.h"
43#include "vmwgfx_saa.h"
44#include "wsbm_util.h"
45#include <unistd.h>
46
47#define VMWGFX_FD_PATH_LEN 80
48
49typedef struct {
50 int refcount;
51 PixmapPtr pPixmap;
52 struct xa_surface *srf;
53 unsigned int dri2_depth;
54} *BufferPrivatePtr;
55
56
57/*
58 * Attempt to guess what the dri state tracker is up to.
59 * Currently it sends only bpp as format.
60 */
61
62static unsigned int
63vmwgfx_color_format_to_depth(unsigned int format)
64{
65 return format;
66}
67
68static unsigned int
69vmwgfx_zs_format_to_depth(unsigned int format)
70{
71 if (format == 24)
72 return 32;
73 return format;
74}
75
76static unsigned int
77vmwgfx_z_format_to_depth(unsigned int format)
78{
79 return format;
80}
81
82static Bool
83dri2_do_create_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer, unsigned int format)
84{
85 ScreenPtr pScreen = pDraw->pScreen;
86 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
87 modesettingPtr ms = modesettingPTR(pScrn);
88 BufferPrivatePtr private = buffer->driverPrivate;
89 PixmapPtr pPixmap;
90 struct vmwgfx_saa_pixmap *vpix;
91 struct xa_surface *srf = NULL;
92 unsigned int depth;
93
94
95 if (pDraw->type == DRAWABLE_PIXMAP)
96 pPixmap = (PixmapPtr) pDraw;
97 else
98 pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr) pDraw);
99
100 vpix = vmwgfx_saa_pixmap(pPixmap);
101 private->refcount = 0;
102
103 switch (buffer->attachment) {
104 default:
105 depth = (format) ? vmwgfx_color_format_to_depth(format) :
106 pDraw->depth;
107
108 if (buffer->attachment != DRI2BufferFakeFrontLeft ||
109 &pPixmap->drawable != pDraw) {
110
111 pPixmap = (*pScreen->CreatePixmap)(pScreen,
112 pDraw->width,
113 pDraw->height,
114 depth,
115 0);
116 if (pPixmap == NullPixmap)
117 return FALSE;
118
119 private->pPixmap = pPixmap;
120 private->dri2_depth = depth;
121 vpix = vmwgfx_saa_pixmap(pPixmap);
122 }
123 break;
124 case DRI2BufferFrontLeft:
125 if (&pPixmap->drawable == pDraw)
126 break;
127 buffer->name = 0;
128 buffer->pitch = 0;
129 buffer->cpp = pDraw->bitsPerPixel / 8;
130 buffer->driverPrivate = private;
131 buffer->flags = 0; /* not tiled */
132 buffer->format = pDraw->bitsPerPixel;
133 if (!private->pPixmap) {
134 private->dri2_depth = 0;
135 private->pPixmap = pPixmap;
136 pPixmap->refcnt++;
137 }
138 return TRUE;
139 case DRI2BufferStencil:
140 case DRI2BufferDepthStencil:
141
142 depth = (format) ? vmwgfx_zs_format_to_depth(format) : 32;
143
144 /*
145 * The SVGA device uses the zs ordering.
146 */
147
148 srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height,
149 depth, xa_type_zs, xa_format_unknown,
150 XA_FLAG_SHARED );
151 if (!srf)
152 return FALSE;
153
154 private->dri2_depth = depth;
155
156 break;
157 case DRI2BufferDepth:
158 depth = (format) ? vmwgfx_z_format_to_depth(format) :
159 pDraw->bitsPerPixel;
160
161 if (depth == 24)
162 srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height,
163 depth, xa_type_zs, xa_format_unknown,
164 XA_FLAG_SHARED );
165 else
166 srf = xa_surface_create(ms->xat, pDraw->width, pDraw->height,
167 depth,
168 xa_type_z, xa_format_unknown,
169 XA_FLAG_SHARED);
170 if (!srf)
171 return FALSE;
172
173 private->dri2_depth = depth;
174
175 break;
176 }
177
178 if (!private->pPixmap) {
179 private->pPixmap = pPixmap;
180 pPixmap->refcnt++;
181 }
182
183 if (!srf) {
184 depth = (format) ? vmwgfx_color_format_to_depth(format) :
185 pDraw->depth;
186
187 if (!vmwgfx_hw_dri2_validate(pPixmap, depth))
188 return FALSE;
189
190 srf = vpix->hw;
191 private->refcount++;
192 private->dri2_depth = depth;
193
194 /*
195 * Compiz workaround. See vmwgfx_dirty();
196 */
197
198 if (buffer->attachment == DRI2BufferFrontLeft ||
199 buffer->attachment == DRI2BufferFakeFrontLeft)
200 vpix->hw_is_dri2_fronts++;
201 }
202
203 private->srf = srf;
204 if (xa_surface_handle(srf, &buffer->name, &buffer->pitch) != 0)
205 return FALSE;
206
207 buffer->cpp = xa_format_depth(xa_surface_format(srf)) / 8;
208 buffer->driverPrivate = private;
209 buffer->flags = 0; /* not tiled */
210 buffer->format = format;
211 private->refcount++;
212
213 return TRUE;
214}
215
216static void
217dri2_do_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer)
218{
219 BufferPrivatePtr private = buffer->driverPrivate;
220 struct xa_surface *srf = private->srf;
221 ScreenPtr pScreen = pDraw->pScreen;
222 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(private->pPixmap);
223
224 if (--private->refcount == 0 && srf) {
225 xa_surface_destroy(srf);
226 }
227
228 /*
229 * Compiz workaround. See vmwgfx_dirty();
230 */
231
232 if ((buffer->attachment == DRI2BufferFrontLeft ||
233 buffer->attachment == DRI2BufferFakeFrontLeft) &&
234 private->refcount == 1 &&
235 --vpix->hw_is_dri2_fronts == 0)
236 WSBMLISTDELINIT(&vpix->sync_x_head);
237
238 private->srf = NULL;
239 pScreen->DestroyPixmap(private->pPixmap);
240}
241
242
243static DRI2Buffer2Ptr
244dri2_create_buffer(DrawablePtr pDraw, unsigned int attachment, unsigned int format)
245{
246 DRI2Buffer2Ptr buffer;
247 BufferPrivatePtr private;
248
249 buffer = calloc(1, sizeof *buffer);
250 if (!buffer)
251 return NULL;
252
253 private = calloc(1, sizeof *private);
254 if (!private) {
255 goto fail;
256 }
257
258 buffer->attachment = attachment;
259 buffer->driverPrivate = private;
260
261 if (dri2_do_create_buffer(pDraw, buffer, format))
262 return buffer;
263
264 free(private);
265fail:
266 free(buffer);
267 return NULL;
268}
269
270static void
271dri2_destroy_buffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer)
272{
273 /* So far it is safe to downcast a DRI2Buffer2Ptr to DRI2BufferPtr */
274 dri2_do_destroy_buffer(pDraw, (DRI2BufferPtr)buffer);
275
276 free(buffer->driverPrivate);
277 free(buffer);
278}
279
280static void
281dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
282 DRI2Buffer2Ptr pDestBuffer, DRI2Buffer2Ptr pSrcBuffer)
283{
284
285
286 ScreenPtr pScreen = pDraw->pScreen;
287 BufferPrivatePtr dst_priv = pDestBuffer->driverPrivate;
288 BufferPrivatePtr src_priv = pSrcBuffer->driverPrivate;
289 DrawablePtr src_draw;
290 DrawablePtr dst_draw;
291 RegionPtr myClip;
292 GCPtr gc;
293
294 /*
295 * In driCreateBuffers we dewrap windows into the
296 * backing pixmaps in order to get to the texture.
297 * We need to use the real drawable in CopyArea
298 * so that cliprects and offsets are correct.
299 */
300 src_draw = (pSrcBuffer->attachment == DRI2BufferFrontLeft) ? pDraw :
301 &src_priv->pPixmap->drawable;
302 dst_draw = (pDestBuffer->attachment == DRI2BufferFrontLeft) ? pDraw :
303 &dst_priv->pPixmap->drawable;
304
305 /*
306 * The clients implements glXWaitX with a copy front to fake and then
307 * waiting on the server to signal its completion of it. While
308 * glXWaitGL is a client side flush and a copy from fake to front.
309 * This is how it is done in the DRI2 protocol, how ever depending
310 * which type of drawables the server does things a bit differently
311 * then what the protocol says as the fake and front are the same.
312 *
313 * for pixmaps glXWaitX is a server flush.
314 * for pixmaps glXWaitGL is a client flush.
315 * for windows glXWaitX is a copy from front to fake then a server flush.
316 * for windows glXWaitGL is a client flush then a copy from fake to front.
317 *
318 * XXX in the windows case this code always flushes but that isn't a
319 * must in the glXWaitGL case but we don't know if this is a glXWaitGL
320 * or a glFlush/glFinish call.
321 */
322 if (dst_priv->pPixmap == src_priv->pPixmap) {
323 /* pixmap glXWaitX */
324 if (pSrcBuffer->attachment == DRI2BufferFrontLeft &&
325 pDestBuffer->attachment == DRI2BufferFakeFrontLeft) {
326
327 if (!vmwgfx_hw_dri2_validate(dst_priv->pPixmap,
328 dst_priv->dri2_depth))
329 return;
330 }
331 /* pixmap glXWaitGL */
332 if (pDestBuffer->attachment == DRI2BufferFrontLeft &&
333 pSrcBuffer->attachment == DRI2BufferFakeFrontLeft) {
334 return;
335 } else {
336 vmwgfx_flush_dri2(pScreen);
337 return;
338 }
339 }
340
341 gc = GetScratchGC(pDraw->depth, pScreen);
342 myClip = REGION_CREATE(pScreen, REGION_RECTS(pRegion),
343 REGION_NUM_RECTS(pRegion));
344 (*gc->funcs->ChangeClip) (gc, CT_REGION, myClip, 0);
345 ValidateGC(dst_draw, gc);
346
347 /*
348 * Damage the src drawable in order for damageCopyArea to pick up
349 * that something changed.
350 */
351 DamageRegionAppend(src_draw, pRegion);
352 if (pSrcBuffer->attachment != DRI2BufferFrontLeft)
353 saa_drawable_dirty(src_draw, TRUE, pRegion);
354 DamageRegionProcessPending(src_draw);
355
356 /*
357 * Call CopyArea. This usually means a call to damageCopyArea that
358 * is wrapping saa_copy_area. The damageCopyArea function will make
359 * sure the destination drawable is appropriately damaged.
360 */
361 (*gc->ops->CopyArea)(src_draw, dst_draw, gc,
362 0, 0, pDraw->width, pDraw->height, 0, 0);
363
364 /*
365 * FreeScratchGC will free myClip as well.
366 */
367 myClip = NULL;
368 FreeScratchGC(gc);
369}
370
371Bool
372xorg_dri2_init(ScreenPtr pScreen)
373{
374 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
375 modesettingPtr ms = modesettingPTR(pScrn);
376 DRI2InfoRec dri2info;
377 int major, minor;
378 char fdPath[VMWGFX_FD_PATH_LEN];
379 ssize_t numChar;
380
381 if (xf86LoaderCheckSymbol("DRI2Version")) {
382 DRI2Version(&major, &minor);
383 } else {
384 /* Assume version 1.0 */
385 major = 1;
386 minor = 0;
387 }
388
389 dri2info.version = min(DRI2INFOREC_VERSION, 3);
390 dri2info.fd = ms->fd;
391 dri2info.driverName = "vmwgfx";
392
393 /*
394 * This way of obtaining the DRM device name is a bit
395 * os-specific. It would be better to obtain it from
396 * drmOpen. Currently this works only for Linux.
397 */
398 memset(fdPath, 0, VMWGFX_FD_PATH_LEN);
399 snprintf(fdPath, VMWGFX_FD_PATH_LEN - 1, "/proc/self/fd/%d", ms->fd);
400 numChar = readlink(fdPath, ms->dri2_device_name, VMWGFX_DRI_DEVICE_LEN);
401 if (numChar <= 0 || numChar >= VMWGFX_DRI_DEVICE_LEN) {
402 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
403 "Could not find the drm device name. Disabling dri2.\n");
404 return FALSE;
405 }
406 ms->dri2_device_name[numChar] = 0;
407 dri2info.deviceName = ms->dri2_device_name;
408 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
409 "Path of drm device is \"%s\".\n", ms->dri2_device_name);
410
411 dri2info.CreateBuffer = dri2_create_buffer;
412 dri2info.DestroyBuffer = dri2_destroy_buffer;
413
414 dri2info.CopyRegion = dri2_copy_region;
415 dri2info.Wait = NULL;
416
417 return DRI2ScreenInit(pScreen, &dri2info);
418}
419
420void
421xorg_dri2_close(ScreenPtr pScreen)
422{
423 DRI2CloseScreen(pScreen);
424}
425
426/* vim: set sw=4 ts=8 sts=4: */
diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c
new file mode 100644
index 0000000..dcb6c83
--- /dev/null
+++ b/vmwgfx/vmwgfx_driver.c
@@ -0,0 +1,1200 @@
1/*
2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * Copyright 2011 VMWare, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 *
27 * Author: Alan Hourihane <alanh@tungstengraphics.com>
28 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
29 * Author: Thomas Hellstrom <thellstrom@vmware.com>
30 */
31
32
33#include <unistd.h>
34#include "xorg-server.h"
35#include "xf86.h"
36#include "xf86_OSproc.h"
37#include "compiler.h"
38#include "xf86PciInfo.h"
39#include "xf86Pci.h"
40#include "mipointer.h"
41#include "micmap.h"
42#include <X11/extensions/randr.h>
43#include "fb.h"
44#include "edid.h"
45#include "xf86i2c.h"
46#include "xf86Crtc.h"
47#include "miscstruct.h"
48#include "dixstruct.h"
49#include "xf86cmap.h"
50#include "xf86xv.h"
51#include "xorgVersion.h"
52#ifndef XSERVER_LIBPCIACCESS
53#error "libpciaccess needed"
54#endif
55
56#include <pciaccess.h>
57
58#include "vmwgfx_driver.h"
59
60#include <saa.h>
61#include "vmwgfx_saa.h"
62#include "../src/vmware_bootstrap.h"
63#include "../src/vmware_common.h"
64
65/*
66 * We can't incude svga_types.h due to conflicting types for Bool.
67 */
68typedef int64_t int64;
69typedef uint64_t uint64;
70
71typedef int32_t int32;
72typedef uint32_t uint32;
73
74typedef int16_t int16;
75typedef uint16_t uint16;
76
77typedef int8_t int8;
78typedef uint8_t uint8;
79#include "./src/svga_reg.h"
80
81#define XA_VERSION_MINOR_REQUIRED 6
82#define DRM_VERSION_MAJOR_REQUIRED 2
83#define DRM_VERSION_MINOR_REQUIRED 3
84
85/*
86 * Some macros to deal with function wrapping.
87 */
88#define vmwgfx_wrap(priv, real, mem, func) {\
89 (priv)->saved_##mem = (real)->mem; \
90 (real)->mem = func; \
91}
92
93#define vmwgfx_unwrap(priv, real, mem) {\
94 (real)->mem = (priv)->saved_##mem; \
95}
96
97#define vmwgfx_swap(priv, real, mem) {\
98 void *tmp = (priv)->saved_##mem; \
99 (priv)->saved_##mem = (real)->mem; \
100 (real)->mem = tmp; \
101}
102
103/*
104 * Functions and symbols exported to Xorg via pointers.
105 */
106
107static Bool drv_pre_init(ScrnInfoPtr pScrn, int flags);
108static Bool drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc,
109 char **argv);
110static Bool drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags);
111static void drv_adjust_frame(int scrnIndex, int x, int y, int flags);
112static Bool drv_enter_vt(int scrnIndex, int flags);
113static void drv_leave_vt(int scrnIndex, int flags);
114static void drv_free_screen(int scrnIndex, int flags);
115static ModeStatus drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose,
116 int flags);
117
118extern void xorg_tracker_set_functions(ScrnInfoPtr scrn);
119
120void
121vmwgfx_hookup(ScrnInfoPtr pScrn)
122{
123 pScrn->PreInit = drv_pre_init;
124 pScrn->ScreenInit = drv_screen_init;
125 pScrn->SwitchMode = drv_switch_mode;
126 pScrn->FreeScreen = drv_free_screen;
127 pScrn->ValidMode = drv_valid_mode;
128}
129
130/*
131 * Internal function definitions
132 */
133
134static Bool drv_close_screen(int scrnIndex, ScreenPtr pScreen);
135
136/*
137 * Internal functions
138 */
139
140static Bool
141drv_get_rec(ScrnInfoPtr pScrn)
142{
143 if (pScrn->driverPrivate)
144 return TRUE;
145
146 pScrn->driverPrivate = xnfcalloc(1, sizeof(modesettingRec));
147
148 return TRUE;
149}
150
151static void
152drv_free_rec(ScrnInfoPtr pScrn)
153{
154 if (!pScrn)
155 return;
156
157 if (!pScrn->driverPrivate)
158 return;
159
160 free(pScrn->driverPrivate);
161
162 pScrn->driverPrivate = NULL;
163}
164
165static void
166drv_probe_ddc(ScrnInfoPtr pScrn, int index)
167{
168 ConfiguredMonitor = NULL;
169}
170
171static Bool
172drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height)
173{
174 modesettingPtr ms = modesettingPTR(pScrn);
175 ScreenPtr pScreen = pScrn->pScreen;
176 int old_width, old_height;
177 PixmapPtr rootPixmap;
178
179 if (width == pScrn->virtualX && height == pScrn->virtualY)
180 return TRUE;
181
182 if (ms->check_fb_size) {
183 size_t size = width*(pScrn->bitsPerPixel / 8) * height + 1024;
184
185 if (size > ms->max_fb_size) {
186 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
187 "Requested framebuffer size %dx%dx%d will not fit "
188 "in display memory.\n",
189 width, height, pScrn->bitsPerPixel);
190 return FALSE;
191 }
192 }
193
194 old_width = pScrn->virtualX;
195 old_height = pScrn->virtualY;
196 pScrn->virtualX = width;
197 pScrn->virtualY = height;
198
199 /* ms->create_front_buffer will remove the old front buffer */
200
201 rootPixmap = pScreen->GetScreenPixmap(pScreen);
202 vmwgfx_disable_scanout(pScrn);
203 if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL))
204 goto error_modify;
205
206 pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8);
207
208 xf86SetDesiredModes(pScrn);
209 return TRUE;
210
211 /*
212 * FIXME: Try out this error recovery path and fix problems.
213
214 */
215 //error_create:
216 if (!pScreen->ModifyPixmapHeader(rootPixmap, old_width, old_height, -1, -1, -1, NULL))
217 FatalError("failed to resize rootPixmap error path\n");
218
219 pScrn->displayWidth = rootPixmap->devKind /
220 (rootPixmap->drawable.bitsPerPixel / 8);
221
222
223error_modify:
224 pScrn->virtualX = old_width;
225 pScrn->virtualY = old_height;
226
227 if (xf86SetDesiredModes(pScrn))
228 return FALSE;
229
230 FatalError("failed to setup old framebuffer\n");
231 return FALSE;
232}
233
234static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
235 .resize = drv_crtc_resize
236};
237
238static Bool
239drv_init_drm(ScrnInfoPtr pScrn)
240{
241 modesettingPtr ms = modesettingPTR(pScrn);
242
243 /* deal with server regeneration */
244 if (ms->fd < 0) {
245 char *BusID;
246
247 BusID = malloc(64);
248 sprintf(BusID, "PCI:%d:%d:%d",
249 ((ms->PciInfo->domain << 8) | ms->PciInfo->bus),
250 ms->PciInfo->dev, ms->PciInfo->func
251 );
252
253
254 ms->fd = drmOpen("vmwgfx", BusID);
255 ms->isMaster = TRUE;
256 free(BusID);
257
258 if (ms->fd >= 0) {
259 drmVersionPtr ver = drmGetVersion(ms->fd);
260
261 if (ver == NULL) {
262 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
263 "Could not determine DRM version.\n");
264 return FALSE;
265 }
266
267 ms->drm_major = ver->version_major;
268 ms->drm_minor = ver->version_minor;
269 ms->drm_patch = ver->version_patchlevel;
270
271 drmFreeVersion(ver);
272 return TRUE;
273 }
274
275 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
276 "Failed to open drm.\n");
277
278 return FALSE;
279 }
280
281 return TRUE;
282}
283
284/**
285 * vmwgfx_set_topology - Set the GUI topology according to an option string
286 *
287 * @pScrn: Pointer to a ScrnInfo struct.
288 * @topology: String containing the topology description.
289 * @info: Info describing the option used to invoke this function.
290 *
291 * This function reads a GUI topology according from @topology, and
292 * calls into the kernel to set that topology.
293 */
294static Bool
295vmwgfx_set_topology(ScrnInfoPtr pScrn, const char *topology, const char *info)
296{
297 modesettingPtr ms = modesettingPTR(pScrn);
298 unsigned int num_outputs;
299 xXineramaScreenInfo *screen_info;
300 struct drm_vmw_rect *rects;
301 int ret;
302 unsigned int i;
303
304 screen_info = VMWAREParseTopologyString(pScrn, topology, &num_outputs,
305 info);
306
307 if (screen_info == NULL)
308 return FALSE;
309
310 rects = calloc(num_outputs, sizeof(*rects));
311 if (rects == NULL) {
312 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
313 "Failed to allocate topology data.\n");
314 goto out_no_rects;
315 }
316
317 for(i = 0; i < num_outputs; ++i) {
318 rects[i].x = screen_info[i].x_org;
319 rects[i].y = screen_info[i].y_org;
320 rects[i].w = screen_info[i].width;
321 rects[i].h = screen_info[i].height;
322 }
323
324 ret = vmwgfx_update_gui_layout(ms->fd, num_outputs, rects);
325 free(rects);
326 free(screen_info);
327
328 return (ret == 0);
329
330 out_no_rects:
331 free(screen_info);
332 return FALSE;
333}
334
335static Bool
336drv_pre_init(ScrnInfoPtr pScrn, int flags)
337{
338 xf86CrtcConfigPtr xf86_config;
339 modesettingPtr ms;
340 rgb defaultWeight = { 0, 0, 0 };
341 EntityInfoPtr pEnt;
342 uint64_t cap;
343 Bool ret = TRUE;
344
345 if (pScrn->numEntities != 1)
346 return FALSE;
347
348 pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
349
350 if (flags & PROBE_DETECT) {
351 drv_probe_ddc(pScrn, pEnt->index);
352 return TRUE;
353 }
354
355 pScrn->driverPrivate = NULL;
356
357 /* Allocate driverPrivate */
358 if (!drv_get_rec(pScrn)) {
359 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
360 "Failed to allocate driver private.\n");
361 }
362
363 ms = modesettingPTR(pScrn);
364 ms->pEnt = pEnt;
365
366 pScrn->displayWidth = 640; /* default it */
367
368 if (ms->pEnt->location.type != BUS_PCI) {
369 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
370 "Incorrect bus for device.\n");
371 goto out_err_bus;
372 }
373
374 ms->PciInfo = xf86GetPciInfoForEntity(ms->pEnt->index);
375 xf86SetPrimInitDone(pScrn->entityList[0]);
376
377 ms->fd = -1;
378 if (!drv_init_drm(pScrn))
379 goto out_err_bus;
380
381 if (ms->drm_major != DRM_VERSION_MAJOR_REQUIRED ||
382 ms->drm_minor < DRM_VERSION_MINOR_REQUIRED) {
383 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
384 "DRM driver version is %d.%d.%d\n",
385 ms->drm_major, ms->drm_minor, ms->drm_patch);
386 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
387 "But KMS- and 3D functionality needs at least "
388 "%d.%d.0 to work.\n",
389 DRM_VERSION_MAJOR_REQUIRED,
390 DRM_VERSION_MINOR_REQUIRED);
391 goto out_drm_version;
392 } else {
393 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
394 "DRM driver version is %d.%d.%d\n",
395 ms->drm_major, ms->drm_minor, ms->drm_patch);
396 }
397
398 ms->check_fb_size = (vmwgfx_max_fb_size(ms->fd, &ms->max_fb_size) == 0);
399
400 pScrn->monitor = pScrn->confScreen->monitor;
401 pScrn->progClock = TRUE;
402 pScrn->rgbBits = 8;
403
404 if (!xf86SetDepthBpp
405 (pScrn, 0, 0, 0,
406 PreferConvert24to32 | SupportConvert24to32 | Support32bppFb)) {
407 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set depth and bpp.\n");
408 goto out_depth;
409 }
410
411 if (vmwgfx_get_param(ms->fd, DRM_VMW_PARAM_HW_CAPS, &cap) != 0) {
412 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to detect device "
413 "screen object capability.\n");
414 goto out_depth;
415 }
416
417 if ((cap & SVGA_CAP_SCREEN_OBJECT_2) == 0) {
418 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Device is not screen object "
419 "capable.\n");
420 goto out_depth;
421 }
422
423 switch (pScrn->depth) {
424 case 15:
425 case 16:
426 case 24:
427 break;
428 default:
429 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
430 "Given depth (%d) is not supported with KMS enabled.\n",
431 pScrn->depth);
432 goto out_depth;
433 }
434 xf86PrintDepthBpp(pScrn);
435
436 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
437 goto out_depth;
438 if (!xf86SetDefaultVisual(pScrn, -1))
439 goto out_depth;
440
441 /* Process the options */
442 xf86CollectOptions(pScrn, NULL);
443 if (!(ms->Options = VMWARECopyOptions()))
444 goto out_depth;
445 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, ms->Options);
446
447 ms->accelerate_render = TRUE;
448 ms->from_render = xf86GetOptValBool(ms->Options, OPTION_RENDER_ACCEL,
449 &ms->accelerate_render) ?
450 X_CONFIG : X_PROBED;
451
452 ms->rendercheck = FALSE;
453 ms->from_rendercheck = xf86GetOptValBool(ms->Options, OPTION_RENDERCHECK,
454 &ms->rendercheck) ?
455 X_CONFIG : X_DEFAULT;
456
457 ms->enable_dri = ms->accelerate_render;
458 ms->from_dri = xf86GetOptValBool(ms->Options, OPTION_DRI,
459 &ms->enable_dri) ?
460 X_CONFIG : X_PROBED;
461
462 ms->direct_presents = FALSE;
463 ms->from_dp = xf86GetOptValBool(ms->Options, OPTION_DIRECT_PRESENTS,
464 &ms->direct_presents) ?
465 X_CONFIG : X_DEFAULT;
466
467 ms->only_hw_presents = FALSE;
468 ms->from_hwp = xf86GetOptValBool(ms->Options, OPTION_HW_PRESENTS,
469 &ms->only_hw_presents) ?
470 X_CONFIG : X_DEFAULT;
471
472 /* Allocate an xf86CrtcConfig */
473 xf86CrtcConfigInit(pScrn, &crtc_config_funcs);
474 xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
475
476 /* get max width and height */
477 {
478 drmModeResPtr res;
479 int max_width, max_height;
480
481 res = drmModeGetResources(ms->fd);
482 max_width = res->max_width;
483 max_height = res->max_height;
484
485 xf86CrtcSetSizeRange(pScrn, res->min_width,
486 res->min_height, max_width, max_height);
487 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
488 "Min width %d, Max Width %d.\n",
489 res->min_width, max_width);
490 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
491 "Min height %d, Max Height %d.\n",
492 res->min_height, max_height);
493 drmModeFreeResources(res);
494 }
495
496
497 if (!xf86ReturnOptValBool(ms->Options, OPTION_HW_CURSOR, TRUE)) {
498 ms->SWCursor = TRUE;
499 }
500
501 if (xf86IsOptionSet(ms->Options, OPTION_GUI_LAYOUT)) {
502 char *topology =
503 xf86GetOptValString(ms->Options, OPTION_GUI_LAYOUT);
504
505 ret = FALSE;
506 if (topology) {
507 ret = vmwgfx_set_topology(pScrn, topology, "gui");
508 free(topology);
509 }
510
511 } else if (xf86IsOptionSet(ms->Options, OPTION_STATIC_XINERAMA)) {
512 char *topology =
513 xf86GetOptValString(ms->Options, OPTION_STATIC_XINERAMA);
514
515 ret = FALSE;
516 if (topology) {
517 ret = vmwgfx_set_topology(pScrn, topology, "static Xinerama");
518 free(topology);
519 }
520 }
521
522 if (!ret)
523 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Falied parsing or setting "
524 "gui topology from config file.\n");
525
526 xorg_crtc_init(pScrn);
527 xorg_output_init(pScrn);
528
529 if (!xf86InitialConfiguration(pScrn, TRUE)) {
530 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
531 goto out_modes;
532 }
533
534 /*
535 * If the driver can do gamma correction, it should call xf86SetGamma() here.
536 */
537 {
538 Gamma zeros = { 0.0, 0.0, 0.0 };
539
540 if (!xf86SetGamma(pScrn, zeros)) {
541 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set gamma.\n");
542 goto out_modes;
543 }
544 }
545
546 if (pScrn->modes == NULL) {
547 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No available modes.\n");
548 goto out_modes;
549 }
550
551 pScrn->currentMode = pScrn->modes;
552
553 /* Set display resolution */
554 xf86SetDpi(pScrn, 0, 0);
555
556 /* Load the required sub modules */
557 if (!xf86LoadSubModule(pScrn, "fb")) {
558 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load fb module.\n");
559 goto out_modes;
560 }
561
562 if (!xf86LoadSubModule(pScrn, "dri2")) {
563 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load dri2 module.\n");
564 goto out_modes;
565 }
566
567 return TRUE;
568
569 out_modes:
570 free(ms->Options);
571 out_depth:
572 out_drm_version:
573 close(ms->fd);
574 out_err_bus:
575 drv_free_rec(pScrn);
576 return FALSE;
577
578}
579
580static Bool
581vmwgfx_scanout_update(int drm_fd, int fb_id, RegionPtr dirty)
582{
583 unsigned num_cliprects = REGION_NUM_RECTS(dirty);
584 drmModeClip *clip = alloca(num_cliprects * sizeof(drmModeClip));
585 BoxPtr rect = REGION_RECTS(dirty);
586 int i, ret;
587
588 if (!num_cliprects)
589 return TRUE;
590
591 for (i = 0; i < num_cliprects; i++, rect++) {
592 clip[i].x1 = rect->x1;
593 clip[i].y1 = rect->y1;
594 clip[i].x2 = rect->x2;
595 clip[i].y2 = rect->y2;
596 }
597
598 ret = drmModeDirtyFB(drm_fd, fb_id, clip, num_cliprects);
599 if (ret)
600 LogMessage(X_ERROR, "%s: failed to send dirty (%i, %s)\n",
601 __func__, ret, strerror(-ret));
602 return (ret == 0);
603}
604
605static Bool
606vmwgfx_scanout_present(ScreenPtr pScreen, int drm_fd,
607 struct vmwgfx_saa_pixmap *vpix,
608 RegionPtr dirty)
609{
610 uint32_t handle;
611 unsigned int dummy;
612
613 if (!REGION_NOTEMPTY(pScreen, dirty))
614 return TRUE;
615
616 if (!vpix->hw) {
617 LogMessage(X_ERROR, "No surface to present from.\n");
618 return FALSE;
619 }
620
621 if (xa_surface_handle(vpix->hw, &handle, &dummy) != 0) {
622 LogMessage(X_ERROR, "Could not get present surface handle.\n");
623 return FALSE;
624 }
625
626 if (vmwgfx_present(drm_fd, vpix->fb_id, 0, 0, dirty, handle) != 0) {
627 LogMessage(X_ERROR, "Failed present kernel call.\n");
628 return FALSE;
629 }
630
631 return TRUE;
632}
633
634void xorg_flush(ScreenPtr pScreen)
635{
636 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
637 modesettingPtr ms = modesettingPTR(pScrn);
638 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
639 PixmapPtr pixmap = NULL;
640 struct vmwgfx_saa_pixmap *vpix;
641 int i;
642 xf86CrtcPtr crtc;
643 PixmapPtr *pixmaps = calloc(config->num_crtc, sizeof(*pixmaps));
644 unsigned int num_scanout = 0;
645 unsigned int j;
646
647 if (!pixmaps) {
648 LogMessage(X_ERROR, "Failed memory allocation during screen "
649 "update.\n");
650 return;
651 }
652
653 /*
654 * Get an array of pixmaps from which we scan out.
655 */
656 for (i=0; i<config->num_crtc; ++i) {
657 crtc = config->crtc[i];
658 if (crtc->enabled) {
659 pixmap = crtc_get_scanout(crtc);
660 if (pixmap) {
661 unsigned int j;
662
663 /*
664 * Remove duplicates.
665 */
666 for (j=0; j<num_scanout; ++j) {
667 if (pixmap == pixmaps[j])
668 break;
669 }
670
671 if (j == num_scanout)
672 pixmaps[num_scanout++] = pixmap;
673 }
674 }
675 }
676
677 if (!num_scanout)
678 return;
679
680 for (j=0; j<num_scanout; ++j) {
681 pixmap = pixmaps[j];
682 vpix = vmwgfx_saa_pixmap(pixmap);
683
684 if (vpix->fb_id != -1) {
685 if (vpix->pending_update) {
686 if (ms->only_hw_presents &&
687 REGION_NOTEMPTY(pscreen, vpix->pending_update)) {
688 (void) vmwgfx_hw_accel_validate(pixmap, 0, XA_FLAG_SCANOUT,
689 0, NULL);
690 REGION_UNION(pScreen, vpix->pending_present,
691 vpix->pending_present, vpix->pending_update);
692 } else
693 (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id,
694 vpix->pending_update);
695 REGION_EMPTY(pScreen, vpix->pending_update);
696 }
697 if (vpix->pending_present) {
698 if (ms->only_hw_presents)
699 (void) vmwgfx_scanout_update(ms->fd, vpix->fb_id,
700 vpix->pending_present);
701 else
702 (void) vmwgfx_scanout_present(pScreen, ms->fd, vpix,
703 vpix->pending_present);
704 REGION_EMPTY(pScreen, vpix->pending_present);
705 }
706 }
707 }
708 free(pixmaps);
709}
710
711static void drv_block_handler(int i, pointer blockData, pointer pTimeout,
712 pointer pReadmask)
713{
714 ScreenPtr pScreen = screenInfo.screens[i];
715 modesettingPtr ms = modesettingPTR(xf86Screens[pScreen->myNum]);
716
717 vmwgfx_swap(ms, pScreen, BlockHandler);
718 pScreen->BlockHandler(i, blockData, pTimeout, pReadmask);
719 vmwgfx_swap(ms, pScreen, BlockHandler);
720
721 vmwgfx_flush_dri2(pScreen);
722 xorg_flush(pScreen);
723}
724
725static Bool
726drv_create_screen_resources(ScreenPtr pScreen)
727{
728 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
729 modesettingPtr ms = modesettingPTR(pScrn);
730 Bool ret;
731
732 vmwgfx_swap(ms, pScreen, CreateScreenResources);
733 ret = pScreen->CreateScreenResources(pScreen);
734 vmwgfx_swap(ms, pScreen, CreateScreenResources);
735
736 drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
737
738 return drv_enter_vt(pScreen->myNum, 1);
739}
740
741static Bool
742drv_set_master(ScrnInfoPtr pScrn)
743{
744 modesettingPtr ms = modesettingPTR(pScrn);
745
746 if (!ms->isMaster && drmSetMaster(ms->fd) != 0) {
747 if (errno == EINVAL) {
748 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
749 "drmSetMaster failed: 2.6.29 or newer kernel required for "
750 "multi-server DRI\n");
751 } else {
752 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
753 "drmSetMaster failed: %s\n", strerror(errno));
754 }
755 return FALSE;
756 }
757
758 ms->isMaster = TRUE;
759 return TRUE;
760}
761
762/**
763 * vmwgfx_use_hw_cursor_argb - wrapper around hw argb cursor check.
764 *
765 * screen: Pointer to the current screen metadata.
766 * cursor: Pointer to the current cursor metadata.
767 *
768 * In addition to the default test, also check whether we might be
769 * needing more than one hw cursor (which we don't support).
770 */
771static Bool
772vmwgfx_use_hw_cursor_argb(ScreenPtr screen, CursorPtr cursor)
773{
774 ScrnInfoPtr pScrn = xf86Screens[screen->myNum];
775 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
776 xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
777 modesettingPtr ms = modesettingPTR(pScrn);
778 Bool ret;
779
780 vmwgfx_swap(ms, cursor_info, UseHWCursorARGB);
781 ret = cursor_info->UseHWCursorARGB(screen, cursor);
782 vmwgfx_swap(ms, cursor_info, UseHWCursorARGB);
783 if (!ret)
784 return FALSE;
785
786 /*
787 * If there is a chance we might need two cursors,
788 * revert to sw cursor.
789 */
790 return !vmwgfx_output_explicit_overlap(pScrn);
791}
792
793/**
794 * vmwgfx_use_hw_cursor - wrapper around hw cursor check.
795 *
796 * screen: Pointer to the current screen metadata.
797 * cursor: Pointer to the current cursor metadata.
798 *
799 * In addition to the default test, also check whether we might be
800 * needing more than one hw cursor (which we don't support).
801 */
802static Bool
803vmwgfx_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
804{
805 ScrnInfoPtr pScrn = xf86Screens[screen->myNum];
806 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
807 xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
808 modesettingPtr ms = modesettingPTR(pScrn);
809 Bool ret;
810
811 vmwgfx_swap(ms, cursor_info, UseHWCursor);
812 ret = cursor_info->UseHWCursor(screen, cursor);
813 vmwgfx_swap(ms, cursor_info, UseHWCursor);
814 if (!ret)
815 return FALSE;
816
817 /*
818 * If there is a chance we might need two simultaneous cursors,
819 * revert to sw cursor.
820 */
821 return !vmwgfx_output_explicit_overlap(pScrn);
822}
823
824/**
825 * vmwgfx_wrap_use_hw_cursor - Wrap functions that check for hw cursor
826 * support.
827 *
828 * pScrn: Pointer to current screen info.
829 *
830 * Enables the device-specific hw cursor support check functions.
831 */
832static void vmwgfx_wrap_use_hw_cursor(ScrnInfoPtr pScrn)
833{
834 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
835 xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
836 modesettingPtr ms = modesettingPTR(pScrn);
837
838 vmwgfx_wrap(ms, cursor_info, UseHWCursor, vmwgfx_use_hw_cursor);
839 vmwgfx_wrap(ms, cursor_info, UseHWCursorARGB, vmwgfx_use_hw_cursor_argb);
840}
841
842
843static void drv_load_palette(ScrnInfoPtr pScrn, int numColors,
844 int *indices, LOCO *colors, VisualPtr pVisual)
845{
846 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
847 modesettingPtr ms = modesettingPTR(pScrn);
848 int index, j, i;
849 int c;
850
851 switch(pScrn->depth) {
852 case 15:
853 for (i = 0; i < numColors; i++) {
854 index = indices[i];
855 for (j = 0; j < 8; j++) {
856 ms->lut_r[index * 8 + j] = colors[index].red << 8;
857 ms->lut_g[index * 8 + j] = colors[index].green << 8;
858 ms->lut_b[index * 8 + j] = colors[index].blue << 8;
859 }
860 }
861 break;
862 case 16:
863 for (i = 0; i < numColors; i++) {
864 index = indices[i];
865
866 if (index < 32) {
867 for (j = 0; j < 8; j++) {
868 ms->lut_r[index * 8 + j] = colors[index].red << 8;
869 ms->lut_b[index * 8 + j] = colors[index].blue << 8;
870 }
871 }
872
873 for (j = 0; j < 4; j++) {
874 ms->lut_g[index * 4 + j] = colors[index].green << 8;
875 }
876 }
877 break;
878 default:
879 for (i = 0; i < numColors; i++) {
880 index = indices[i];
881 ms->lut_r[index] = colors[index].red << 8;
882 ms->lut_g[index] = colors[index].green << 8;
883 ms->lut_b[index] = colors[index].blue << 8;
884 }
885 break;
886 }
887
888 for (c = 0; c < xf86_config->num_crtc; c++) {
889 xf86CrtcPtr crtc = xf86_config->crtc[c];
890
891 /* Make the change through RandR */
892#ifdef RANDR_12_INTERFACE
893 if (crtc->randr_crtc)
894 RRCrtcGammaSet(crtc->randr_crtc, ms->lut_r, ms->lut_g, ms->lut_b);
895 else
896#endif
897 crtc->funcs->gamma_set(crtc, ms->lut_r, ms->lut_g, ms->lut_b, 256);
898 }
899}
900
901
902static Bool
903drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
904{
905 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
906 modesettingPtr ms = modesettingPTR(pScrn);
907 VisualPtr visual;
908
909 if (!drv_set_master(pScrn))
910 return FALSE;
911
912 pScrn->pScreen = pScreen;
913
914 /* HW dependent - FIXME */
915 pScrn->displayWidth = pScrn->virtualX;
916
917 miClearVisualTypes();
918
919 if (!miSetVisualTypes(pScrn->depth,
920 miGetDefaultVisualMask(pScrn->depth),
921 pScrn->rgbBits, pScrn->defaultVisual))
922 return FALSE;
923
924 if (!miSetPixmapDepths())
925 return FALSE;
926
927 pScrn->memPhysBase = 0;
928 pScrn->fbOffset = 0;
929
930 if (!fbScreenInit(pScreen, NULL,
931 pScrn->virtualX, pScrn->virtualY,
932 pScrn->xDpi, pScrn->yDpi,
933 pScrn->displayWidth, pScrn->bitsPerPixel))
934 return FALSE;
935
936 if (pScrn->bitsPerPixel > 8) {
937 /* Fixup RGB ordering */
938 visual = pScreen->visuals + pScreen->numVisuals;
939 while (--visual >= pScreen->visuals) {
940 if ((visual->class | DynamicClass) == DirectColor) {
941 visual->offsetRed = pScrn->offset.red;
942 visual->offsetGreen = pScrn->offset.green;
943 visual->offsetBlue = pScrn->offset.blue;
944 visual->redMask = pScrn->mask.red;
945 visual->greenMask = pScrn->mask.green;
946 visual->blueMask = pScrn->mask.blue;
947 }
948 }
949 }
950
951 fbPictureInit(pScreen, NULL, 0);
952
953 vmwgfx_wrap(ms, pScreen, BlockHandler, drv_block_handler);
954 vmwgfx_wrap(ms, pScreen, CreateScreenResources,
955 drv_create_screen_resources);
956
957 xf86SetBlackWhitePixels(pScreen);
958
959 vmw_ctrl_ext_init(pScrn);
960
961 if (ms->accelerate_render) {
962 ms->xat = xa_tracker_create(ms->fd);
963 if (!ms->xat) {
964 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
965 "Failed to initialize Gallium3D Xa. "
966 "No render acceleration available.\n");
967 ms->from_render = X_PROBED;
968 } else {
969 int major, minor, patch;
970
971 xa_tracker_version(&major, &minor, &patch);
972 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
973 "Gallium3D XA version: %d.%d.%d.\n",
974 major, minor, patch);
975
976 if (XA_TRACKER_VERSION_MAJOR == 0) {
977 if (minor != XA_TRACKER_VERSION_MINOR) {
978 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
979 "Expecting XA version 0.%d.x.\n",
980 XA_TRACKER_VERSION_MINOR);
981 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
982 "No render acceleration available.\n");
983 xa_tracker_destroy(ms->xat);
984 ms->xat = NULL;
985 ms->from_render = X_PROBED;
986 }
987 }
988 if (major != XA_TRACKER_VERSION_MAJOR ||
989 minor < XA_VERSION_MINOR_REQUIRED) {
990 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
991 "Expecting %d.%d.x >= XA version < %d.0.0.\n",
992 XA_TRACKER_VERSION_MAJOR,
993 XA_VERSION_MINOR_REQUIRED,
994 XA_TRACKER_VERSION_MAJOR + 1);
995 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
996 "No render acceleration available.\n");
997 xa_tracker_destroy(ms->xat);
998 ms->xat = NULL;
999 ms->from_render = X_PROBED;
1000 }
1001 }
1002 if (ms->xat == NULL && ms->rendercheck) {
1003 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1004 "Turning off renercheck mode.\n");
1005 ms->rendercheck = FALSE;
1006 ms->from_rendercheck = X_PROBED;
1007 }
1008 }
1009
1010 if (!vmwgfx_saa_init(pScreen, ms->fd, ms->xat, &xorg_flush,
1011 ms->direct_presents,
1012 ms->only_hw_presents,
1013 ms->rendercheck)) {
1014 FatalError("Failed to initialize SAA.\n");
1015 }
1016
1017 ms->dri2_available = FALSE;
1018 if (ms->enable_dri) {
1019 if (ms->xat) {
1020 ms->dri2_available = xorg_dri2_init(pScreen);
1021 if (!ms->dri2_available)
1022 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1023 "Failed to initialize direct rendering.\n");
1024 } else {
1025 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1026 "Skipped initialization of direct rendering due "
1027 "to lack of render acceleration.\n");
1028 ms->from_dri = X_PROBED;
1029 }
1030 }
1031
1032 xf86DrvMsg(pScrn->scrnIndex, ms->from_render, "Render acceleration is %s.\n",
1033 (ms->xat != NULL) ? "enabled" : "disabled");
1034
1035 xf86DrvMsg(pScrn->scrnIndex, ms->from_rendercheck,
1036 "Rendercheck mode is %s.\n",
1037 (ms->rendercheck) ? "enabled" : "disabled");
1038
1039 xf86DrvMsg(pScrn->scrnIndex, ms->from_dri, "Direct rendering (3D) is %s.\n",
1040 (ms->dri2_available) ? "enabled" : "disabled");
1041 if (ms->xat != NULL) {
1042 xf86DrvMsg(pScrn->scrnIndex, ms->from_dp, "Direct presents are %s.\n",
1043 (ms->direct_presents) ? "enabled" : "disabled");
1044 xf86DrvMsg(pScrn->scrnIndex, ms->from_hwp, "Hardware only presents "
1045 "are %s.\n",
1046 (ms->only_hw_presents) ? "enabled" : "disabled");
1047 }
1048
1049 miInitializeBackingStore(pScreen);
1050 xf86SetBackingStore(pScreen);
1051 xf86SetSilkenMouse(pScreen);
1052 miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1053
1054 /* Need to extend HWcursor support to handle mask interleave */
1055 if (!ms->SWCursor) {
1056 xf86_cursors_init(pScreen, 64, 64,
1057 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
1058 HARDWARE_CURSOR_ARGB |
1059 HARDWARE_CURSOR_UPDATE_UNHIDDEN);
1060 vmwgfx_wrap_use_hw_cursor(pScrn);
1061 }
1062
1063 /* Must force it before EnterVT, so we are in control of VT and
1064 * later memory should be bound when allocating, e.g rotate_mem */
1065 pScrn->vtSema = TRUE;
1066
1067 pScreen->SaveScreen = xf86SaveScreen;
1068 vmwgfx_wrap(ms, pScreen, CloseScreen, drv_close_screen);
1069
1070 if (!xf86CrtcScreenInit(pScreen))
1071 return FALSE;
1072
1073 if (!miCreateDefColormap(pScreen))
1074 return FALSE;
1075 if (!xf86HandleColormaps(pScreen, 256, 8, drv_load_palette, NULL,
1076 CMAP_PALETTED_TRUECOLOR |
1077 CMAP_RELOAD_ON_MODE_SWITCH))
1078 return FALSE;
1079
1080 xf86DPMSInit(pScreen, xf86DPMSSet, 0);
1081
1082 if (serverGeneration == 1)
1083 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1084
1085
1086 vmwgfx_wrap(ms, pScrn, EnterVT, drv_enter_vt);
1087 vmwgfx_wrap(ms, pScrn, LeaveVT, drv_leave_vt);
1088 vmwgfx_wrap(ms, pScrn, AdjustFrame, drv_adjust_frame);
1089
1090 /*
1091 * Must be called _after_ function wrapping.
1092 */
1093 xorg_xv_init(pScreen);
1094
1095 return TRUE;
1096}
1097
1098static void
1099drv_adjust_frame(int scrnIndex, int x, int y, int flags)
1100{
1101 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1102 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1103 xf86OutputPtr output = config->output[config->compat_output];
1104 xf86CrtcPtr crtc = output->crtc;
1105
1106 if (crtc && crtc->enabled) {
1107 // crtc->funcs->set_mode_major(crtc, pScrn->currentMode,
1108 // RR_Rotate_0, x, y);
1109 crtc->x = output->initial_x + x;
1110 crtc->y = output->initial_y + y;
1111 }
1112}
1113
1114static void
1115drv_free_screen(int scrnIndex, int flags)
1116{
1117 drv_free_rec(xf86Screens[scrnIndex]);
1118}
1119
1120static void
1121drv_leave_vt(int scrnIndex, int flags)
1122{
1123 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1124 modesettingPtr ms = modesettingPTR(pScrn);
1125
1126 vmwgfx_cursor_bypass(ms->fd, 0, 0);
1127 vmwgfx_disable_scanout(pScrn);
1128
1129 if (drmDropMaster(ms->fd))
1130 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1131 "drmDropMaster failed: %s\n", strerror(errno));
1132
1133 ms->isMaster = FALSE;
1134 pScrn->vtSema = FALSE;
1135}
1136
1137/*
1138 * This gets called when gaining control of the VT, and from ScreenInit().
1139 */
1140static Bool
1141drv_enter_vt(int scrnIndex, int flags)
1142{
1143 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1144
1145 if (!drv_set_master(pScrn))
1146 return FALSE;
1147
1148 if (!xf86SetDesiredModes(pScrn))
1149 return FALSE;
1150
1151 return TRUE;
1152}
1153
1154static Bool
1155drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags)
1156{
1157 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1158
1159 return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
1160}
1161
1162static Bool
1163drv_close_screen(int scrnIndex, ScreenPtr pScreen)
1164{
1165 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1166 modesettingPtr ms = modesettingPTR(pScrn);
1167
1168 if (ms->cursor) {
1169 FreeCursor(ms->cursor, None);
1170 ms->cursor = NULL;
1171 }
1172
1173 if (ms->dri2_available)
1174 xorg_dri2_close(pScreen);
1175
1176 if (pScrn->vtSema)
1177 pScrn->LeaveVT(scrnIndex, 0);
1178
1179 pScrn->vtSema = FALSE;
1180
1181 vmwgfx_unwrap(ms, pScrn, EnterVT);
1182 vmwgfx_unwrap(ms, pScrn, LeaveVT);
1183 vmwgfx_unwrap(ms, pScrn, AdjustFrame);
1184 vmwgfx_unwrap(ms, pScreen, CloseScreen);
1185 vmwgfx_unwrap(ms, pScreen, BlockHandler);
1186 vmwgfx_unwrap(ms, pScreen, CreateScreenResources);
1187
1188 if (ms->xat)
1189 xa_tracker_destroy(ms->xat);
1190
1191 return (*pScreen->CloseScreen) (scrnIndex, pScreen);
1192}
1193
1194static ModeStatus
1195drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
1196{
1197 return MODE_OK;
1198}
1199
1200/* vim: set sw=4 ts=8 sts=4: */
diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h
new file mode 100644
index 0000000..3290f0e
--- /dev/null
+++ b/vmwgfx/vmwgfx_driver.h
@@ -0,0 +1,186 @@
1/*
2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * Copyright 2011 VMWare, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright n<otice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 *
27 * Author: Alan Hourihane <alanh@tungstengraphics.com>
28 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
29 * Author: Thomas Hellstrom <thellstrom@vmware.com>
30 */
31
32#ifndef _VMWGFX_DRIVER_H_
33#define _VMWGFX_DRIVER_H_
34
35
36#include <stddef.h>
37#include <stdint.h>
38#include <errno.h>
39#include <drm.h>
40#include <xf86drm.h>
41#include <xf86drmMode.h>
42#include <xorg-server.h>
43#include <xf86.h>
44#include <xf86Crtc.h>
45#include <xf86xv.h>
46#include <xa_tracker.h>
47
48#ifdef DRI2
49#include <dri2.h>
50#if (!defined(DRI2INFOREC_VERSION) || (DRI2INFOREC_VERSION < 3))
51#undef DRI2
52#endif
53#endif
54
55#define DRV_ERROR(msg) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, msg);
56#define debug_printf(...)
57
58#define VMWGFX_DRI_DEVICE_LEN 80
59
60typedef struct
61{
62 int lastInstance;
63 int refCount;
64 ScrnInfoPtr pScrn_1;
65 ScrnInfoPtr pScrn_2;
66} EntRec, *EntPtr;
67
68#define XORG_NR_FENCES 3
69
70enum xorg_throttling_reason {
71 THROTTLE_RENDER,
72 THROTTLE_SWAP
73};
74
75typedef struct _modesettingRec
76{
77 /* drm */
78 int fd;
79 int drm_major;
80 int drm_minor;
81 int drm_patch;
82
83 /* X */
84 EntPtr entityPrivate;
85
86 int Chipset;
87 EntityInfoPtr pEnt;
88 struct pci_device *PciInfo;
89
90 /* Accel */
91 Bool accelerate_render;
92 MessageType from_render;
93 Bool rendercheck;
94 MessageType from_rendercheck;
95 Bool SWCursor;
96 CursorPtr cursor;
97 Bool enable_dri;
98 MessageType from_dri;
99 Bool direct_presents;
100 MessageType from_dp;
101 Bool only_hw_presents;
102 MessageType from_hwp;
103 Bool isMaster;
104
105
106 /* Broken-out options. */
107 OptionInfoPtr Options;
108
109 ScreenBlockHandlerProcPtr saved_BlockHandler;
110 CreateScreenResourcesProcPtr saved_CreateScreenResources;
111 CloseScreenProcPtr saved_CloseScreen;
112 Bool (*saved_EnterVT)(int, int);
113 void (*saved_LeaveVT)(int, int);
114 void (*saved_AdjustFrame)(int, int, int, int);
115 Bool (*saved_UseHWCursor)(ScreenPtr, CursorPtr);
116 Bool (*saved_UseHWCursorARGB)(ScreenPtr, CursorPtr);
117
118 uint16_t lut_r[256], lut_g[256], lut_b[256];
119
120 Bool check_fb_size;
121 size_t max_fb_size;
122
123 struct xa_tracker *xat;
124#ifdef DRI2
125 Bool dri2_available;
126 char dri2_device_name[VMWGFX_DRI_DEVICE_LEN];
127#endif
128} modesettingRec, *modesettingPtr;
129
130#define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate))
131
132void xorg_flush(ScreenPtr pScreen);
133/***********************************************************************
134 * xorg_dri2.c
135 */
136Bool
137xorg_dri2_init(ScreenPtr pScreen);
138
139void
140xorg_dri2_close(ScreenPtr pScreen);
141
142
143/***********************************************************************
144 * xorg_crtc.c
145 */
146void
147xorg_crtc_init(ScrnInfoPtr pScrn);
148
149void
150xorg_crtc_cursor_destroy(xf86CrtcPtr crtc);
151
152void
153vmwgfx_disable_scanout(ScrnInfoPtr pScrn);
154
155PixmapPtr
156crtc_get_scanout(xf86CrtcPtr crtc);
157
158
159/***********************************************************************
160 * xorg_output.c
161 */
162void
163xorg_output_init(ScrnInfoPtr pScrn);
164
165unsigned
166xorg_output_get_id(xf86OutputPtr output);
167
168Bool
169vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn);
170
171
172/***********************************************************************
173 * xorg_xv.c
174 */
175void
176xorg_xv_init(ScreenPtr pScreen);
177
178XF86VideoAdaptorPtr
179vmw_video_init_adaptor(ScrnInfoPtr pScrn);
180void
181vmw_video_free_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports);
182
183void
184vmw_ctrl_ext_init(ScrnInfoPtr pScrn);
185
186#endif /* _XORG_TRACKER_H_ */
diff --git a/vmwgfx/vmwgfx_drm.h b/vmwgfx/vmwgfx_drm.h
new file mode 100644
index 0000000..906a41c
--- /dev/null
+++ b/vmwgfx/vmwgfx_drm.h
@@ -0,0 +1,792 @@
1/**************************************************************************
2 *
3 * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#ifndef __VMWGFX_DRM_H__
29#define __VMWGFX_DRM_H__
30#include <drm.h>
31
32#define DRM_VMW_MAX_SURFACE_FACES 6
33#define DRM_VMW_MAX_MIP_LEVELS 24
34
35
36#define DRM_VMW_GET_PARAM 0
37#define DRM_VMW_ALLOC_DMABUF 1
38#define DRM_VMW_UNREF_DMABUF 2
39#define DRM_VMW_CURSOR_BYPASS 3
40/* guarded by DRM_VMW_PARAM_NUM_STREAMS != 0*/
41#define DRM_VMW_CONTROL_STREAM 4
42#define DRM_VMW_CLAIM_STREAM 5
43#define DRM_VMW_UNREF_STREAM 6
44/* guarded by DRM_VMW_PARAM_3D == 1 */
45#define DRM_VMW_CREATE_CONTEXT 7
46#define DRM_VMW_UNREF_CONTEXT 8
47#define DRM_VMW_CREATE_SURFACE 9
48#define DRM_VMW_UNREF_SURFACE 10
49#define DRM_VMW_REF_SURFACE 11
50#define DRM_VMW_EXECBUF 12
51#define DRM_VMW_GET_3D_CAP 13
52#define DRM_VMW_FENCE_WAIT 14
53#define DRM_VMW_FENCE_SIGNALED 15
54#define DRM_VMW_FENCE_UNREF 16
55#define DRM_VMW_FENCE_EVENT 17
56#define DRM_VMW_PRESENT 18
57#define DRM_VMW_PRESENT_READBACK 19
58#define DRM_VMW_UPDATE_LAYOUT 20
59
60/*************************************************************************/
61/**
62 * DRM_VMW_GET_PARAM - get device information.
63 *
64 * DRM_VMW_PARAM_FIFO_OFFSET:
65 * Offset to use to map the first page of the FIFO read-only.
66 * The fifo is mapped using the mmap() system call on the drm device.
67 *
68 * DRM_VMW_PARAM_OVERLAY_IOCTL:
69 * Does the driver support the overlay ioctl.
70 */
71
72#define DRM_VMW_PARAM_NUM_STREAMS 0
73#define DRM_VMW_PARAM_NUM_FREE_STREAMS 1
74#define DRM_VMW_PARAM_3D 2
75#define DRM_VMW_PARAM_HW_CAPS 3
76#define DRM_VMW_PARAM_FIFO_CAPS 4
77#define DRM_VMW_PARAM_MAX_FB_SIZE 5
78#define DRM_VMW_PARAM_FIFO_HW_VERSION 6
79
80/**
81 * struct drm_vmw_getparam_arg
82 *
83 * @value: Returned value. //Out
84 * @param: Parameter to query. //In.
85 *
86 * Argument to the DRM_VMW_GET_PARAM Ioctl.
87 */
88
89struct drm_vmw_getparam_arg {
90 uint64_t value;
91 uint32_t param;
92 uint32_t pad64;
93};
94
95/*************************************************************************/
96/**
97 * DRM_VMW_CREATE_CONTEXT - Create a host context.
98 *
99 * Allocates a device unique context id, and queues a create context command
100 * for the host. Does not wait for host completion.
101 */
102
103/**
104 * struct drm_vmw_context_arg
105 *
106 * @cid: Device unique context ID.
107 *
108 * Output argument to the DRM_VMW_CREATE_CONTEXT Ioctl.
109 * Input argument to the DRM_VMW_UNREF_CONTEXT Ioctl.
110 */
111
112struct drm_vmw_context_arg {
113 int32_t cid;
114 uint32_t pad64;
115};
116
117/*************************************************************************/
118/**
119 * DRM_VMW_UNREF_CONTEXT - Create a host context.
120 *
121 * Frees a global context id, and queues a destroy host command for the host.
122 * Does not wait for host completion. The context ID can be used directly
123 * in the command stream and shows up as the same context ID on the host.
124 */
125
126/*************************************************************************/
127/**
128 * DRM_VMW_CREATE_SURFACE - Create a host suface.
129 *
130 * Allocates a device unique surface id, and queues a create surface command
131 * for the host. Does not wait for host completion. The surface ID can be
132 * used directly in the command stream and shows up as the same surface
133 * ID on the host.
134 */
135
136/**
137 * struct drm_wmv_surface_create_req
138 *
139 * @flags: Surface flags as understood by the host.
140 * @format: Surface format as understood by the host.
141 * @mip_levels: Number of mip levels for each face.
142 * An unused face should have 0 encoded.
143 * @size_addr: Address of a user-space array of sruct drm_vmw_size
144 * cast to an uint64_t for 32-64 bit compatibility.
145 * The size of the array should equal the total number of mipmap levels.
146 * @shareable: Boolean whether other clients (as identified by file descriptors)
147 * may reference this surface.
148 * @scanout: Boolean whether the surface is intended to be used as a
149 * scanout.
150 *
151 * Input data to the DRM_VMW_CREATE_SURFACE Ioctl.
152 * Output data from the DRM_VMW_REF_SURFACE Ioctl.
153 */
154
155struct drm_vmw_surface_create_req {
156 uint32_t flags;
157 uint32_t format;
158 uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES];
159 uint64_t size_addr;
160 int32_t shareable;
161 int32_t scanout;
162};
163
164/**
165 * struct drm_wmv_surface_arg
166 *
167 * @sid: Surface id of created surface or surface to destroy or reference.
168 *
169 * Output data from the DRM_VMW_CREATE_SURFACE Ioctl.
170 * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl.
171 * Input argument to the DRM_VMW_REF_SURFACE Ioctl.
172 */
173
174struct drm_vmw_surface_arg {
175 int32_t sid;
176 uint32_t pad64;
177};
178
179/**
180 * struct drm_vmw_size ioctl.
181 *
182 * @width - mip level width
183 * @height - mip level height
184 * @depth - mip level depth
185 *
186 * Description of a mip level.
187 * Input data to the DRM_WMW_CREATE_SURFACE Ioctl.
188 */
189
190struct drm_vmw_size {
191 uint32_t width;
192 uint32_t height;
193 uint32_t depth;
194 uint32_t pad64;
195};
196
197/**
198 * union drm_vmw_surface_create_arg
199 *
200 * @rep: Output data as described above.
201 * @req: Input data as described above.
202 *
203 * Argument to the DRM_VMW_CREATE_SURFACE Ioctl.
204 */
205
206union drm_vmw_surface_create_arg {
207 struct drm_vmw_surface_arg rep;
208 struct drm_vmw_surface_create_req req;
209};
210
211/*************************************************************************/
212/**
213 * DRM_VMW_REF_SURFACE - Reference a host surface.
214 *
215 * Puts a reference on a host surface with a give sid, as previously
216 * returned by the DRM_VMW_CREATE_SURFACE ioctl.
217 * A reference will make sure the surface isn't destroyed while we hold
218 * it and will allow the calling client to use the surface ID in the command
219 * stream.
220 *
221 * On successful return, the Ioctl returns the surface information given
222 * in the DRM_VMW_CREATE_SURFACE ioctl.
223 */
224
225/**
226 * union drm_vmw_surface_reference_arg
227 *
228 * @rep: Output data as described above.
229 * @req: Input data as described above.
230 *
231 * Argument to the DRM_VMW_REF_SURFACE Ioctl.
232 */
233
234union drm_vmw_surface_reference_arg {
235 struct drm_vmw_surface_create_req rep;
236 struct drm_vmw_surface_arg req;
237};
238
239/*************************************************************************/
240/**
241 * DRM_VMW_UNREF_SURFACE - Unreference a host surface.
242 *
243 * Clear a reference previously put on a host surface.
244 * When all references are gone, including the one implicitly placed
245 * on creation,
246 * a destroy surface command will be queued for the host.
247 * Does not wait for completion.
248 */
249
250/*************************************************************************/
251/**
252 * DRM_VMW_EXECBUF
253 *
254 * Submit a command buffer for execution on the host, and return a
255 * fence seqno that when signaled, indicates that the command buffer has
256 * executed.
257 */
258
259/**
260 * struct drm_vmw_execbuf_arg
261 *
262 * @commands: User-space address of a command buffer cast to an uint64_t.
263 * @command-size: Size in bytes of the command buffer.
264 * @throttle-us: Sleep until software is less than @throttle_us
265 * microseconds ahead of hardware. The driver may round this value
266 * to the nearest kernel tick.
267 * @fence_rep: User-space address of a struct drm_vmw_fence_rep cast to an
268 * uint64_t.
269 * @version: Allows expanding the execbuf ioctl parameters without breaking
270 * backwards compatibility, since user-space will always tell the kernel
271 * which version it uses.
272 * @flags: Execbuf flags. None currently.
273 *
274 * Argument to the DRM_VMW_EXECBUF Ioctl.
275 */
276
277#define DRM_VMW_EXECBUF_VERSION 1
278
279struct drm_vmw_execbuf_arg {
280 uint64_t commands;
281 uint32_t command_size;
282 uint32_t throttle_us;
283 uint64_t fence_rep;
284 uint32_t version;
285 uint32_t flags;
286};
287
288/**
289 * struct drm_vmw_fence_rep
290 *
291 * @handle: Fence object handle for fence associated with a command submission.
292 * @mask: Fence flags relevant for this fence object.
293 * @seqno: Fence sequence number in fifo. A fence object with a lower
294 * seqno will signal the EXEC flag before a fence object with a higher
295 * seqno. This can be used by user-space to avoid kernel calls to determine
296 * whether a fence has signaled the EXEC flag. Note that @seqno will
297 * wrap at 32-bit.
298 * @passed_seqno: The highest seqno number processed by the hardware
299 * so far. This can be used to mark user-space fence objects as signaled, and
300 * to determine whether a fence seqno might be stale.
301 * @error: This member should've been set to -EFAULT on submission.
302 * The following actions should be take on completion:
303 * error == -EFAULT: Fence communication failed. The host is synchronized.
304 * Use the last fence id read from the FIFO fence register.
305 * error != 0 && error != -EFAULT:
306 * Fence submission failed. The host is synchronized. Use the fence_seq member.
307 * error == 0: All is OK, The host may not be synchronized.
308 * Use the fence_seq member.
309 *
310 * Input / Output data to the DRM_VMW_EXECBUF Ioctl.
311 */
312
313struct drm_vmw_fence_rep {
314 uint32_t handle;
315 uint32_t mask;
316 uint32_t seqno;
317 uint32_t passed_seqno;
318 uint32_t pad64;
319 int32_t error;
320};
321
322/*************************************************************************/
323/**
324 * DRM_VMW_ALLOC_DMABUF
325 *
326 * Allocate a DMA buffer that is visible also to the host.
327 * NOTE: The buffer is
328 * identified by a handle and an offset, which are private to the guest, but
329 * useable in the command stream. The guest kernel may translate these
330 * and patch up the command stream accordingly. In the future, the offset may
331 * be zero at all times, or it may disappear from the interface before it is
332 * fixed.
333 *
334 * The DMA buffer may stay user-space mapped in the guest at all times,
335 * and is thus suitable for sub-allocation.
336 *
337 * DMA buffers are mapped using the mmap() syscall on the drm device.
338 */
339
340/**
341 * struct drm_vmw_alloc_dmabuf_req
342 *
343 * @size: Required minimum size of the buffer.
344 *
345 * Input data to the DRM_VMW_ALLOC_DMABUF Ioctl.
346 */
347
348struct drm_vmw_alloc_dmabuf_req {
349 uint32_t size;
350 uint32_t pad64;
351};
352
353/**
354 * struct drm_vmw_dmabuf_rep
355 *
356 * @map_handle: Offset to use in the mmap() call used to map the buffer.
357 * @handle: Handle unique to this buffer. Used for unreferencing.
358 * @cur_gmr_id: GMR id to use in the command stream when this buffer is
359 * referenced. See not above.
360 * @cur_gmr_offset: Offset to use in the command stream when this buffer is
361 * referenced. See note above.
362 *
363 * Output data from the DRM_VMW_ALLOC_DMABUF Ioctl.
364 */
365
366struct drm_vmw_dmabuf_rep {
367 uint64_t map_handle;
368 uint32_t handle;
369 uint32_t cur_gmr_id;
370 uint32_t cur_gmr_offset;
371 uint32_t pad64;
372};
373
374/**
375 * union drm_vmw_dmabuf_arg
376 *
377 * @req: Input data as described above.
378 * @rep: Output data as described above.
379 *
380 * Argument to the DRM_VMW_ALLOC_DMABUF Ioctl.
381 */
382
383union drm_vmw_alloc_dmabuf_arg {
384 struct drm_vmw_alloc_dmabuf_req req;
385 struct drm_vmw_dmabuf_rep rep;
386};
387
388/*************************************************************************/
389/**
390 * DRM_VMW_UNREF_DMABUF - Free a DMA buffer.
391 *
392 */
393
394/**
395 * struct drm_vmw_unref_dmabuf_arg
396 *
397 * @handle: Handle indicating what buffer to free. Obtained from the
398 * DRM_VMW_ALLOC_DMABUF Ioctl.
399 *
400 * Argument to the DRM_VMW_UNREF_DMABUF Ioctl.
401 */
402
403struct drm_vmw_unref_dmabuf_arg {
404 uint32_t handle;
405 uint32_t pad64;
406};
407
408/*************************************************************************/
409/**
410 * DRM_VMW_CONTROL_STREAM - Control overlays, aka streams.
411 *
412 * This IOCTL controls the overlay units of the svga device.
413 * The SVGA overlay units does not work like regular hardware units in
414 * that they do not automaticaly read back the contents of the given dma
415 * buffer. But instead only read back for each call to this ioctl, and
416 * at any point between this call being made and a following call that
417 * either changes the buffer or disables the stream.
418 */
419
420/**
421 * struct drm_vmw_rect
422 *
423 * Defines a rectangle. Used in the overlay ioctl to define
424 * source and destination rectangle.
425 */
426
427struct drm_vmw_rect {
428 int32_t x;
429 int32_t y;
430 uint32_t w;
431 uint32_t h;
432};
433
434/**
435 * struct drm_vmw_control_stream_arg
436 *
437 * @stream_id: Stearm to control
438 * @enabled: If false all following arguments are ignored.
439 * @handle: Handle to buffer for getting data from.
440 * @format: Format of the overlay as understood by the host.
441 * @width: Width of the overlay.
442 * @height: Height of the overlay.
443 * @size: Size of the overlay in bytes.
444 * @pitch: Array of pitches, the two last are only used for YUV12 formats.
445 * @offset: Offset from start of dma buffer to overlay.
446 * @src: Source rect, must be within the defined area above.
447 * @dst: Destination rect, x and y may be negative.
448 *
449 * Argument to the DRM_VMW_CONTROL_STREAM Ioctl.
450 */
451
452struct drm_vmw_control_stream_arg {
453 uint32_t stream_id;
454 uint32_t enabled;
455
456 uint32_t flags;
457 uint32_t color_key;
458
459 uint32_t handle;
460 uint32_t offset;
461 int32_t format;
462 uint32_t size;
463 uint32_t width;
464 uint32_t height;
465 uint32_t pitch[3];
466
467 uint32_t pad64;
468 struct drm_vmw_rect src;
469 struct drm_vmw_rect dst;
470};
471
472/*************************************************************************/
473/**
474 * DRM_VMW_CURSOR_BYPASS - Give extra information about cursor bypass.
475 *
476 */
477
478#define DRM_VMW_CURSOR_BYPASS_ALL (1 << 0)
479#define DRM_VMW_CURSOR_BYPASS_FLAGS (1)
480
481/**
482 * struct drm_vmw_cursor_bypass_arg
483 *
484 * @flags: Flags.
485 * @crtc_id: Crtc id, only used if DMR_CURSOR_BYPASS_ALL isn't passed.
486 * @xpos: X position of cursor.
487 * @ypos: Y position of cursor.
488 * @xhot: X hotspot.
489 * @yhot: Y hotspot.
490 *
491 * Argument to the DRM_VMW_CURSOR_BYPASS Ioctl.
492 */
493
494struct drm_vmw_cursor_bypass_arg {
495 uint32_t flags;
496 uint32_t crtc_id;
497 int32_t xpos;
498 int32_t ypos;
499 int32_t xhot;
500 int32_t yhot;
501};
502
503/*************************************************************************/
504/**
505 * DRM_VMW_CLAIM_STREAM - Claim a single stream.
506 */
507
508/**
509 * struct drm_vmw_context_arg
510 *
511 * @stream_id: Device unique context ID.
512 *
513 * Output argument to the DRM_VMW_CREATE_CONTEXT Ioctl.
514 * Input argument to the DRM_VMW_UNREF_CONTEXT Ioctl.
515 */
516
517struct drm_vmw_stream_arg {
518 uint32_t stream_id;
519 uint32_t pad64;
520};
521
522/*************************************************************************/
523/**
524 * DRM_VMW_UNREF_STREAM - Unclaim a stream.
525 *
526 * Return a single stream that was claimed by this process. Also makes
527 * sure that the stream has been stopped.
528 */
529
530/*************************************************************************/
531/**
532 * DRM_VMW_GET_3D_CAP
533 *
534 * Read 3D capabilities from the FIFO
535 *
536 */
537
538/**
539 * struct drm_vmw_get_3d_cap_arg
540 *
541 * @buffer: Pointer to a buffer for capability data, cast to an uint64_t
542 * @size: Max size to copy
543 *
544 * Input argument to the DRM_VMW_GET_3D_CAP_IOCTL
545 * ioctls.
546 */
547
548struct drm_vmw_get_3d_cap_arg {
549 uint64_t buffer;
550 uint32_t max_size;
551 uint32_t pad64;
552};
553
554
555/*************************************************************************/
556/**
557 * DRM_VMW_FENCE_WAIT
558 *
559 * Waits for a fence object to signal. The wait is interruptible, so that
560 * signals may be delivered during the interrupt. The wait may timeout,
561 * in which case the calls returns -EBUSY. If the wait is restarted,
562 * that is restarting without resetting @cookie_valid to zero,
563 * the timeout is computed from the first call.
564 *
565 * The flags argument to the DRM_VMW_FENCE_WAIT ioctl indicates what to wait
566 * on:
567 * DRM_VMW_FENCE_FLAG_EXEC: All commands ahead of the fence in the command
568 * stream
569 * have executed.
570 * DRM_VMW_FENCE_FLAG_QUERY: All query results resulting from query finish
571 * commands
572 * in the buffer given to the EXECBUF ioctl returning the fence object handle
573 * are available to user-space.
574 *
575 * DRM_VMW_WAIT_OPTION_UNREF: If this wait option is given, and the
576 * fenc wait ioctl returns 0, the fence object has been unreferenced after
577 * the wait.
578 */
579
580#define DRM_VMW_FENCE_FLAG_EXEC (1 << 0)
581#define DRM_VMW_FENCE_FLAG_QUERY (1 << 1)
582
583#define DRM_VMW_WAIT_OPTION_UNREF (1 << 0)
584
585/**
586 * struct drm_vmw_fence_wait_arg
587 *
588 * @handle: Fence object handle as returned by the DRM_VMW_EXECBUF ioctl.
589 * @cookie_valid: Must be reset to 0 on first call. Left alone on restart.
590 * @kernel_cookie: Set to 0 on first call. Left alone on restart.
591 * @timeout_us: Wait timeout in microseconds. 0 for indefinite timeout.
592 * @lazy: Set to 1 if timing is not critical. Allow more than a kernel tick
593 * before returning.
594 * @flags: Fence flags to wait on.
595 * @wait_options: Options that control the behaviour of the wait ioctl.
596 *
597 * Input argument to the DRM_VMW_FENCE_WAIT ioctl.
598 */
599
600struct drm_vmw_fence_wait_arg {
601 uint32_t handle;
602 int32_t cookie_valid;
603 uint64_t kernel_cookie;
604 uint64_t timeout_us;
605 int32_t lazy;
606 int32_t flags;
607 int32_t wait_options;
608 int32_t pad64;
609};
610
611/*************************************************************************/
612/**
613 * DRM_VMW_FENCE_SIGNALED
614 *
615 * Checks if a fence object is signaled..
616 */
617
618/**
619 * struct drm_vmw_fence_signaled_arg
620 *
621 * @handle: Fence object handle as returned by the DRM_VMW_EXECBUF ioctl.
622 * @flags: Fence object flags input to DRM_VMW_FENCE_SIGNALED ioctl
623 * @signaled: Out: Flags signaled.
624 * @sequence: Out: Highest sequence passed so far. Can be used to signal the
625 * EXEC flag of user-space fence objects.
626 *
627 * Input/Output argument to the DRM_VMW_FENCE_SIGNALED and DRM_VMW_FENCE_UNREF
628 * ioctls.
629 */
630
631struct drm_vmw_fence_signaled_arg {
632 uint32_t handle;
633 uint32_t flags;
634 int32_t signaled;
635 uint32_t passed_seqno;
636 uint32_t signaled_flags;
637 uint32_t pad64;
638};
639
640/*************************************************************************/
641/**
642 * DRM_VMW_FENCE_UNREF
643 *
644 * Unreferences a fence object, and causes it to be destroyed if there are no
645 * other references to it.
646 *
647 */
648
649/**
650 * struct drm_vmw_fence_arg
651 *
652 * @handle: Fence object handle as returned by the DRM_VMW_EXECBUF ioctl.
653 *
654 * Input/Output argument to the DRM_VMW_FENCE_UNREF ioctl..
655 */
656
657struct drm_vmw_fence_arg {
658 uint32_t handle;
659 uint32_t pad64;
660};
661
662
663/*************************************************************************/
664/**
665 * DRM_VMW_FENCE_EVENT
666 *
667 * Queues an event on a fence to be delivered on the drm character device
668 * when the fence has signaled the DRM_VMW_FENCE_FLAG_EXEC flag.
669 * Optionally the approximate time when the fence signaled is
670 * given by the event.
671 */
672
673/*
674 * The event type
675 */
676#define DRM_VMW_EVENT_FENCE_SIGNALED 0x80000000
677
678struct drm_vmw_event_fence {
679 struct drm_event base;
680 uint64_t user_data;
681 uint32_t tv_sec;
682 uint32_t tv_usec;
683};
684
685/*
686 * Flags that may be given to the command.
687 */
688/* Request fence signaled time on the event. */
689#define DRM_VMW_FE_FLAG_REQ_TIME (1 << 0)
690
691/**
692 * struct drm_vmw_fence_event_arg
693 *
694 * @fence_rep: Pointer to fence_rep structure cast to uint64_t or 0 if
695 * the fence is not supposed to be referenced by user-space.
696 * @user_info: Info to be delivered with the event.
697 * @handle: Attach the event to this fence only.
698 * @flags: A set of flags as defined above.
699 */
700struct drm_vmw_fence_event_arg {
701 uint64_t fence_rep;
702 uint64_t user_data;
703 uint32_t handle;
704 uint32_t flags;
705};
706
707
708/*************************************************************************/
709/**
710 * DRM_VMW_PRESENT
711 *
712 * Executes an SVGA present on a given fb for a given surface. The surface
713 * is placed on the framebuffer. Cliprects are given relative to the given
714 * point (the point disignated by dest_{x|y}).
715 *
716 */
717
718/**
719 * struct drm_vmw_present_arg
720 * @fb_id: framebuffer id to present / read back from.
721 * @sid: Surface id to present from.
722 * @dest_x: X placement coordinate for surface.
723 * @dest_y: Y placement coordinate for surface.
724 * @clips_ptr: Pointer to an array of clip rects cast to an uint64_t.
725 * @num_clips: Number of cliprects given relative to the framebuffer origin,
726 * in the same coordinate space as the frame buffer.
727 * @pad64: Unused 64-bit padding.
728 *
729 * Input argument to the DRM_VMW_PRESENT ioctl.
730 */
731
732struct drm_vmw_present_arg {
733 uint32_t fb_id;
734 uint32_t sid;
735 int32_t dest_x;
736 int32_t dest_y;
737 uint64_t clips_ptr;
738 uint32_t num_clips;
739 uint32_t pad64;
740};
741
742
743/*************************************************************************/
744/**
745 * DRM_VMW_PRESENT_READBACK
746 *
747 * Executes an SVGA present readback from a given fb to the dma buffer
748 * currently bound as the fb. If there is no dma buffer bound to the fb,
749 * an error will be returned.
750 *
751 */
752
753/**
754 * struct drm_vmw_present_arg
755 * @fb_id: fb_id to present / read back from.
756 * @num_clips: Number of cliprects.
757 * @clips_ptr: Pointer to an array of clip rects cast to an uint64_t.
758 * @fence_rep: Pointer to a struct drm_vmw_fence_rep, cast to an uint64_t.
759 * If this member is NULL, then the ioctl should not return a fence.
760 */
761
762struct drm_vmw_present_readback_arg {
763 uint32_t fb_id;
764 uint32_t num_clips;
765 uint64_t clips_ptr;
766 uint64_t fence_rep;
767};
768
769/*************************************************************************/
770/**
771 * DRM_VMW_UPDATE_LAYOUT - Update layout
772 *
773 * Updates the preferred modes and connection status for connectors. The
774 * command consists of one drm_vmw_update_layout_arg pointing to an array
775 * of num_outputs drm_vmw_rect's.
776 */
777
778/**
779 * struct drm_vmw_update_layout_arg
780 *
781 * @num_outputs: number of active connectors
782 * @rects: pointer to array of drm_vmw_rect cast to an uint64_t
783 *
784 * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
785 */
786struct drm_vmw_update_layout_arg {
787 uint32_t num_outputs;
788 uint32_t pad64;
789 uint64_t rects;
790};
791
792#endif
diff --git a/vmwgfx/vmwgfx_drmi.c b/vmwgfx/vmwgfx_drmi.c
new file mode 100644
index 0000000..e326d31
--- /dev/null
+++ b/vmwgfx/vmwgfx_drmi.c
@@ -0,0 +1,502 @@
1/*
2 * Copyright 2011 VMWare, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
26 * Author: Thomas Hellstrom <thellstrom@vmware.com>
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <stdint.h>
34#include <errno.h>
35#include <sys/mman.h>
36#include "vmwgfx_drm.h"
37#include <xf86drm.h>
38#include "vmwgfx_drmi.h"
39
40#define uint32 uint32_t
41#define int32 int32_t
42#define uint16 uint16_t
43#define uint8 uint8_t
44
45#include "svga3d_reg.h"
46#include "vmwgfx_driver.h"
47
48static int
49vmwgfx_fence_wait(int drm_fd, uint32_t handle, Bool unref)
50{
51 struct drm_vmw_fence_wait_arg farg;
52 memset(&farg, 0, sizeof(farg));
53
54 farg.handle = handle;
55 farg.flags = DRM_VMW_FENCE_FLAG_EXEC;
56 farg.timeout_us = 10*1000000;
57 farg.cookie_valid = 0;
58
59 if (unref)
60 farg.wait_options |= DRM_VMW_WAIT_OPTION_UNREF;
61
62 return drmCommandWriteRead(drm_fd, DRM_VMW_FENCE_WAIT, &farg,
63 sizeof(farg));
64}
65
66static void
67vmwgfx_fence_unref(int drm_fd, uint32_t handle)
68{
69 struct drm_vmw_fence_arg farg;
70 memset(&farg, 0, sizeof(farg));
71
72 farg.handle = handle;
73
74 (void) drmCommandWrite(drm_fd, DRM_VMW_FENCE_UNREF, &farg,
75 sizeof(farg));
76}
77
78
79int
80vmwgfx_present_readback(int drm_fd, uint32_t fb_id, RegionPtr region)
81{
82 BoxPtr clips = REGION_RECTS(region);
83 unsigned int num_clips = REGION_NUM_RECTS(region);
84 struct drm_vmw_fence_rep rep;
85 struct drm_vmw_present_readback_arg arg;
86 int ret;
87 unsigned i;
88 struct drm_vmw_rect *rects, *r;
89
90 rects = calloc(num_clips, sizeof(*rects));
91 if (!rects) {
92 LogMessage(X_ERROR, "Failed to alloc cliprects for "
93 "present readback.\n");
94 return -1;
95 }
96
97 memset(&arg, 0, sizeof(arg));
98 memset(&rep, 0, sizeof(rep));
99
100 arg.fb_id = fb_id;
101 arg.num_clips = num_clips;
102 arg.clips_ptr = (unsigned long) rects;
103 arg.fence_rep = (unsigned long) &rep;
104 rep.error = -EFAULT;
105
106 for (i = 0, r = rects; i < num_clips; ++i, ++r, ++clips) {
107 r->x = clips->x1;
108 r->y = clips->y1;
109 r->w = clips->x2 - clips->x1;
110 r->h = clips->y2 - clips->y1;
111 }
112
113 ret = drmCommandWrite(drm_fd, DRM_VMW_PRESENT_READBACK, &arg, sizeof(arg));
114 if (ret)
115 LogMessage(X_ERROR, "Present readback error %s.\n", strerror(-ret));
116 free(rects);
117
118 /*
119 * Sync to avoid racing with Xorg SW rendering.
120 */
121
122 if (rep.error == 0) {
123 ret = vmwgfx_fence_wait(drm_fd, rep.handle, TRUE);
124 if (ret) {
125 LogMessage(X_ERROR, "Present readback fence wait error %s.\n",
126 strerror(-ret));
127 vmwgfx_fence_unref(drm_fd, rep.handle);
128 }
129 }
130
131 return 0;
132}
133
134
135int
136vmwgfx_present(int drm_fd, uint32_t fb_id, unsigned int dst_x,
137 unsigned int dst_y, RegionPtr region, uint32_t handle)
138{
139 BoxPtr clips = REGION_RECTS(region);
140 unsigned int num_clips = REGION_NUM_RECTS(region);
141 struct drm_vmw_present_arg arg;
142 unsigned int i;
143 struct drm_vmw_rect *rects, *r;
144 int ret;
145
146 if (num_clips == 0)
147 return 0;
148
149 rects = calloc(num_clips, sizeof(*rects));
150 if (!rects) {
151 LogMessage(X_ERROR, "Failed to alloc cliprects for "
152 "present.\n");
153 return -1;
154 }
155
156 memset(&arg, 0, sizeof(arg));
157 arg.fb_id = fb_id;
158 arg.sid = handle;
159 arg.dest_x = dst_x;
160 arg.dest_y = dst_y;
161 arg.num_clips = num_clips;
162 arg.clips_ptr = (unsigned long) rects;
163
164 for (i = 0, r = rects; i < num_clips; ++i, ++r, ++clips) {
165 r->x = clips->x1;
166 r->y = clips->y1;
167 r->w = clips->x2 - clips->x1;
168 r->h = clips->y2 - clips->y1;
169 }
170
171 ret = drmCommandWrite(drm_fd, DRM_VMW_PRESENT, &arg, sizeof(arg));
172 if (ret) {
173 LogMessage(X_ERROR, "Present error %s.\n", strerror(-ret));
174 }
175
176 free(rects);
177 return ((ret != 0) ? -1 : 0);
178}
179
180
181struct vmwgfx_int_dmabuf {
182 struct vmwgfx_dmabuf buf;
183 uint64_t map_handle;
184 uint64_t sync_handle;
185 int sync_valid;
186 int drm_fd;
187 uint32_t map_count;
188 void *addr;
189};
190
191static inline struct vmwgfx_int_dmabuf *
192vmwgfx_int_dmabuf(struct vmwgfx_dmabuf *buf)
193{
194 return (struct vmwgfx_int_dmabuf *) buf;
195}
196
197struct vmwgfx_dmabuf*
198vmwgfx_dmabuf_alloc(int drm_fd, size_t size)
199{
200 union drm_vmw_alloc_dmabuf_arg arg;
201 struct vmwgfx_dmabuf *buf;
202 struct vmwgfx_int_dmabuf *ibuf;
203 int ret;
204
205 ibuf = calloc(1, sizeof(*ibuf));
206 if (!ibuf)
207 return NULL;
208
209 buf = &ibuf->buf;
210 memset(&arg, 0, sizeof(arg));
211 arg.req.size = size;
212
213 ret = drmCommandWriteRead(drm_fd, DRM_VMW_ALLOC_DMABUF, &arg,
214 sizeof(arg));
215 if (ret)
216 goto out_kernel_fail;
217
218 ibuf = vmwgfx_int_dmabuf(buf);
219 ibuf->map_handle = arg.rep.map_handle;
220 ibuf->drm_fd = drm_fd;
221 buf->handle = arg.rep.handle;
222 buf->gmr_id = arg.rep.cur_gmr_id;
223 buf->gmr_offset = arg.rep.cur_gmr_offset;
224 buf->size = size;
225
226 return buf;
227 out_kernel_fail:
228 free(buf);
229 return NULL;
230}
231
232void *
233vmwgfx_dmabuf_map(struct vmwgfx_dmabuf *buf)
234{
235 struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf);
236
237 if (ibuf->addr)
238 return ibuf->addr;
239
240 ibuf->addr = mmap(NULL, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED,
241 ibuf->drm_fd, ibuf->map_handle);
242
243 if (ibuf->addr == MAP_FAILED) {
244 ibuf->addr = NULL;
245 return NULL;
246 }
247
248 ibuf->map_count++;
249 return ibuf->addr;
250}
251
252void
253vmwgfx_dmabuf_unmap(struct vmwgfx_dmabuf *buf)
254{
255 struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf);
256
257 if (--ibuf->map_count)
258 return;
259
260 /*
261 * It's a pretty important performance optimzation not to call
262 * munmap here, although we should watch out for cases where we might fill
263 * the virtual memory space of the process.
264 */
265}
266
267void
268vmwgfx_dmabuf_destroy(struct vmwgfx_dmabuf *buf)
269{
270 struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf);
271 struct drm_vmw_unref_dmabuf_arg arg;
272
273 if (ibuf->addr) {
274 munmap(ibuf->addr, buf->size);
275 ibuf->addr = NULL;
276 }
277
278 memset(&arg, 0, sizeof(arg));
279 arg.handle = buf->handle;
280
281 (void) drmCommandWrite(ibuf->drm_fd, DRM_VMW_UNREF_DMABUF, &arg,
282 sizeof(arg));
283 free(buf);
284}
285
286int
287vmwgfx_dma(unsigned int host_x, unsigned int host_y,
288 RegionPtr region, struct vmwgfx_dmabuf *buf,
289 uint32_t buf_pitch, uint32_t surface_handle, int to_surface)
290{
291 BoxPtr clips = REGION_RECTS(region);
292 unsigned int num_clips = REGION_NUM_RECTS(region);
293 struct drm_vmw_execbuf_arg arg;
294 struct drm_vmw_fence_rep rep;
295 int ret;
296 unsigned int size;
297 unsigned i;
298 SVGA3dCopyBox *cb;
299 SVGA3dCmdSurfaceDMASuffix *suffix;
300 SVGA3dCmdSurfaceDMA *body;
301 struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf);
302
303 struct {
304 SVGA3dCmdHeader header;
305 SVGA3dCmdSurfaceDMA body;
306 SVGA3dCopyBox cb;
307 } *cmd;
308
309 if (num_clips == 0)
310 return 0;
311
312 size = sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cb) +
313 sizeof(*suffix);
314 cmd = malloc(size);
315 if (!cmd)
316 return -1;
317
318 cmd->header.id = SVGA_3D_CMD_SURFACE_DMA;
319 cmd->header.size = sizeof(cmd->body) + num_clips * sizeof(cmd->cb) +
320 sizeof(*suffix);
321 cb = &cmd->cb;
322
323 suffix = (SVGA3dCmdSurfaceDMASuffix *) &cb[num_clips];
324 suffix->suffixSize = sizeof(*suffix);
325 suffix->maximumOffset = (uint32_t) -1;
326 suffix->flags.discard = 0;
327 suffix->flags.unsynchronized = 0;
328 suffix->flags.reserved = 0;
329
330 body = &cmd->body;
331 body->guest.ptr.gmrId = buf->gmr_id;
332 body->guest.ptr.offset = buf->gmr_offset;
333 body->guest.pitch = buf_pitch;
334 body->host.sid = surface_handle;
335 body->host.face = 0;
336 body->host.mipmap = 0;
337
338 body->transfer = (to_surface ? SVGA3D_WRITE_HOST_VRAM :
339 SVGA3D_READ_HOST_VRAM);
340
341
342 for (i=0; i < num_clips; i++, cb++, clips++) {
343 cb->x = (uint16_t) clips->x1 + host_x;
344 cb->y = (uint16_t) clips->y1 + host_y;
345 cb->z = 0;
346 cb->srcx = (uint16_t) clips->x1;
347 cb->srcy = (uint16_t) clips->y1;
348 cb->srcz = 0;
349 cb->w = (uint16_t) (clips->x2 - clips->x1);
350 cb->h = (uint16_t) (clips->y2 - clips->y1);
351 cb->d = 1;
352#if 0
353 LogMessage(X_INFO, "DMA! x: %u y: %u srcx: %u srcy: %u w: %u h: %u %s\n",
354 cb->x, cb->y, cb->srcx, cb->srcy, cb->w, cb->h,
355 to_surface ? "to" : "from");
356#endif
357
358 }
359
360 memset(&arg, 0, sizeof(arg));
361 memset(&rep, 0, sizeof(rep));
362
363 rep.error = -EFAULT;
364 arg.fence_rep = ((to_surface) ? 0UL : (unsigned long)&rep);
365 arg.commands = (unsigned long)cmd;
366 arg.command_size = size;
367 arg.throttle_us = 0;
368 arg.version = DRM_VMW_EXECBUF_VERSION;
369
370 ret = drmCommandWrite(ibuf->drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg));
371 if (ret) {
372 LogMessage(X_ERROR, "DMA error %s.\n", strerror(-ret));
373 }
374
375 free(cmd);
376
377 if (rep.error == 0) {
378 ret = vmwgfx_fence_wait(ibuf->drm_fd, rep.handle, TRUE);
379 if (ret) {
380 LogMessage(X_ERROR, "DMA from host fence wait error %s.\n",
381 strerror(-ret));
382 vmwgfx_fence_unref(ibuf->drm_fd, rep.handle);
383 }
384 }
385
386 return 0;
387}
388
389int
390vmwgfx_get_param(int drm_fd, uint32_t param, uint64_t *out)
391{
392 struct drm_vmw_getparam_arg gp_arg;
393 int ret;
394
395 memset(&gp_arg, 0, sizeof(gp_arg));
396 gp_arg.param = param;
397 ret = drmCommandWriteRead(drm_fd, DRM_VMW_GET_PARAM,
398 &gp_arg, sizeof(gp_arg));
399
400 if (ret == 0) {
401 *out = gp_arg.value;
402 }
403
404 return ret;
405}
406
407int
408vmwgfx_num_streams(int drm_fd, uint32_t *ntot, uint32_t *nfree)
409{
410 uint64_t v1, v2;
411 int ret;
412
413 ret = vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_NUM_STREAMS, &v1);
414 if (ret)
415 return ret;
416
417 ret = vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_NUM_FREE_STREAMS, &v2);
418 if (ret)
419 return ret;
420
421 *ntot = (uint32_t)v1;
422 *nfree = (uint32_t)v2;
423
424 return 0;
425}
426
427int
428vmwgfx_claim_stream(int drm_fd, uint32_t *out)
429{
430 struct drm_vmw_stream_arg s_arg;
431 int ret;
432
433 ret = drmCommandRead(drm_fd, DRM_VMW_CLAIM_STREAM,
434 &s_arg, sizeof(s_arg));
435
436 if (ret)
437 return -1;
438
439 *out = s_arg.stream_id;
440 return 0;
441}
442
443int
444vmwgfx_unref_stream(int drm_fd, uint32_t stream_id)
445{
446 struct drm_vmw_stream_arg s_arg;
447 int ret;
448
449 memset(&s_arg, 0, sizeof(s_arg));
450 s_arg.stream_id = stream_id;
451
452 ret = drmCommandWrite(drm_fd, DRM_VMW_UNREF_STREAM,
453 &s_arg, sizeof(s_arg));
454
455 return 0;
456}
457
458int
459vmwgfx_cursor_bypass(int drm_fd, int xhot, int yhot)
460{
461 struct drm_vmw_cursor_bypass_arg arg;
462 int ret;
463
464 memset(&arg, 0, sizeof(arg));
465 arg.flags = DRM_VMW_CURSOR_BYPASS_ALL;
466 arg.xhot = xhot;
467 arg.yhot = yhot;
468
469 ret = drmCommandWrite(drm_fd, DRM_VMW_CURSOR_BYPASS,
470 &arg, sizeof(arg));
471
472 return ret;
473}
474
475int
476vmwgfx_update_gui_layout(int drm_fd, unsigned int num_rects,
477 struct drm_vmw_rect *rects)
478{
479 struct drm_vmw_update_layout_arg arg;
480
481 memset(&arg, 0, sizeof(arg));
482
483 arg.num_outputs = num_rects;
484 arg.rects = (unsigned long) rects;
485
486 return drmCommandWrite(drm_fd, DRM_VMW_UPDATE_LAYOUT, &arg,
487 sizeof(arg));
488}
489
490
491int
492vmwgfx_max_fb_size(int drm_fd, size_t *size)
493{
494 uint64_t tmp_size;
495
496 if (vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_MAX_FB_SIZE, &tmp_size) != 0)
497 return -1;
498
499 *size = tmp_size;
500
501 return 0;
502}
diff --git a/vmwgfx/vmwgfx_drmi.h b/vmwgfx/vmwgfx_drmi.h
new file mode 100644
index 0000000..2435009
--- /dev/null
+++ b/vmwgfx/vmwgfx_drmi.h
@@ -0,0 +1,87 @@
1/*
2 * Copyright 2011 VMWare, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
26 * Author: Thomas Hellstrom <thellstrom@vmware.com>
27 */
28
29#ifndef _VMWGFX_DRMI_H_
30#define _VMWGFX_DRMI_H_
31
32#include <xorg-server.h>
33#include <regionstr.h>
34#include <stdint.h>
35#include "vmwgfx_drm.h"
36
37struct vmwgfx_dma_ctx;
38
39extern int
40vmwgfx_present_readback(int drm_fd, uint32_t fb_id, RegionPtr region);
41
42extern int
43vmwgfx_present(int drm_fd, uint32_t fb_id, unsigned int dst_x,
44 unsigned int dst_y, RegionPtr region, uint32_t handle);
45
46struct vmwgfx_dmabuf {
47 uint32_t handle;
48 uint32_t gmr_id;
49 uint32_t gmr_offset;
50 size_t size;
51};
52
53extern struct vmwgfx_dmabuf*
54vmwgfx_dmabuf_alloc(int drm_fd, size_t size);
55extern void
56vmwgfx_dmabuf_destroy(struct vmwgfx_dmabuf *buf);
57extern void *
58vmwgfx_dmabuf_map(struct vmwgfx_dmabuf *buf);
59extern void
60vmwgfx_dmabuf_unmap(struct vmwgfx_dmabuf *buf);
61
62extern int
63vmwgfx_dma(unsigned int host_x, unsigned int host_y,
64 RegionPtr region, struct vmwgfx_dmabuf *buf,
65 uint32_t buf_pitch, uint32_t surface_handle, int to_surface);
66
67extern int
68vmwgfx_num_streams(int drm_fd, uint32_t *ntot, uint32_t *nfree);
69
70extern int
71vmwgfx_claim_stream(int drm_fd, uint32_t *out);
72
73extern int
74vmwgfx_unref_stream(int drm_fd, uint32_t stream_id);
75
76int
77vmwgfx_cursor_bypass(int drm_fd, int xhot, int yhot);
78
79int
80vmwgfx_max_fb_size(int drm_fd, size_t *size);
81
82int
83vmwgfx_update_gui_layout(int drm_fd, unsigned int num_rects,
84 struct drm_vmw_rect *rects);
85int
86vmwgfx_get_param(int drm_fd, uint32_t param, uint64_t *out);
87#endif
diff --git a/vmwgfx/vmwgfx_output.c b/vmwgfx/vmwgfx_output.c
new file mode 100644
index 0000000..4f52f1d
--- /dev/null
+++ b/vmwgfx/vmwgfx_output.c
@@ -0,0 +1,393 @@
1/*
2 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 *
26 * Author: Alan Hourihane <alanh@tungstengraphics.com>
27 * Author: Jakob Bornecrantz <wallbraker@gmail.com>
28 *
29 */
30
31#include "xorg-server.h"
32#include <xf86.h>
33#include <xf86i2c.h>
34#include <xf86Crtc.h>
35#include <errno.h>
36#include <fcntl.h>
37#include <unistd.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <stdint.h>
41#include <string.h>
42#include <sys/stat.h>
43#include <sys/types.h>
44
45#ifdef HAVE_XEXTPROTO_71
46#include <X11/extensions/dpmsconst.h>
47#else
48#define DPMS_SERVER
49#include <X11/extensions/dpms.h>
50#endif
51
52#include "vmwgfx_driver.h"
53
54struct output_private
55{
56 drmModeConnectorPtr drm_connector;
57
58 int c;
59
60 Bool is_implicit;
61};
62
63static char *output_enum_list[] = {
64 "Unknown",
65 "VGA",
66 "DVI",
67 "DVI",
68 "DVI",
69 "Composite",
70 "SVIDEO",
71 "LVDS",
72 "CTV",
73 "DIN",
74 "DP",
75 "HDMI",
76 "HDMI",
77 "TV",
78 "EDP",
79 "Virtual",
80};
81
82static void
83output_create_resources(xf86OutputPtr output)
84{
85#ifdef RANDR_12_INTERFACE
86#endif /* RANDR_12_INTERFACE */
87}
88
89static void
90output_dpms(xf86OutputPtr output, int mode)
91{
92}
93
94static xf86OutputStatus
95output_detect(xf86OutputPtr output)
96{
97 modesettingPtr ms = modesettingPTR(output->scrn);
98 struct output_private *priv = output->driver_private;
99 drmModeConnectorPtr drm_connector;
100 xf86OutputStatus status;
101
102 drm_connector = drmModeGetConnector(ms->fd, priv->drm_connector->connector_id);
103 if (drm_connector) {
104 drmModeFreeConnector(priv->drm_connector);
105 priv->drm_connector = drm_connector;
106 } else {
107 drm_connector = priv->drm_connector;
108 }
109
110 switch (drm_connector->connection) {
111 case DRM_MODE_CONNECTED:
112 status = XF86OutputStatusConnected;
113 break;
114 case DRM_MODE_DISCONNECTED:
115 status = XF86OutputStatusDisconnected;
116 break;
117 default:
118 status = XF86OutputStatusUnknown;
119 }
120
121 return status;
122}
123
124static DisplayModePtr
125output_get_modes(xf86OutputPtr output)
126{
127 struct output_private *priv = output->driver_private;
128 drmModeConnectorPtr drm_connector = priv->drm_connector;
129 drmModeModeInfoPtr drm_mode = NULL;
130 DisplayModePtr modes = NULL, mode = NULL;
131 int i;
132
133 for (i = 0; i < drm_connector->count_modes; i++) {
134 drm_mode = &drm_connector->modes[i];
135 if (drm_mode) {
136 mode = calloc(1, sizeof(DisplayModeRec));
137 if (!mode)
138 continue;
139 mode->Clock = drm_mode->clock;
140 mode->HDisplay = drm_mode->hdisplay;
141 mode->HSyncStart = drm_mode->hsync_start;
142 mode->HSyncEnd = drm_mode->hsync_end;
143 mode->HTotal = drm_mode->htotal;
144 mode->VDisplay = drm_mode->vdisplay;
145 mode->VSyncStart = drm_mode->vsync_start;
146 mode->VSyncEnd = drm_mode->vsync_end;
147 mode->VTotal = drm_mode->vtotal;
148 mode->Flags = drm_mode->flags;
149 mode->HSkew = drm_mode->hskew;
150 mode->VScan = drm_mode->vscan;
151 mode->VRefresh = xf86ModeVRefresh(mode);
152 mode->Private = (void *)drm_mode;
153 mode->type = 0;
154 if (drm_mode->type & DRM_MODE_TYPE_PREFERRED)
155 mode->type |= M_T_PREFERRED;
156 if (drm_mode->type & DRM_MODE_TYPE_DRIVER)
157 mode->type |= M_T_DRIVER;
158 xf86SetModeDefaultName(mode);
159 modes = xf86ModesAdd(modes, mode);
160 xf86PrintModeline(0, mode);
161 }
162 }
163
164 return modes;
165}
166
167static int
168output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
169{
170 // modesettingPtr ms = modesettingPTR(output->scrn);
171 // CustomizerPtr cust = ms->cust;
172
173#if 0
174 if (cust && cust->winsys_check_fb_size &&
175 !cust->winsys_check_fb_size(cust, pMode->HDisplay *
176 output->scrn->bitsPerPixel / 8,
177 pMode->VDisplay))
178 return MODE_BAD;
179#endif
180 return MODE_OK;
181}
182
183#ifdef RANDR_12_INTERFACE
184static Bool
185output_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr value)
186{
187 return TRUE;
188}
189#endif /* RANDR_12_INTERFACE */
190
191#ifdef RANDR_13_INTERFACE
192static Bool
193output_get_property(xf86OutputPtr output, Atom property)
194{
195 return TRUE;
196}
197#endif /* RANDR_13_INTERFACE */
198
199static void
200output_destroy(xf86OutputPtr output)
201{
202 struct output_private *priv = output->driver_private;
203 drmModeFreeConnector(priv->drm_connector);
204 free(priv);
205 output->driver_private = NULL;
206}
207
208static const xf86OutputFuncsRec output_funcs = {
209 .create_resources = output_create_resources,
210#ifdef RANDR_12_INTERFACE
211 .set_property = output_set_property,
212#endif
213#ifdef RANDR_13_INTERFACE
214 .get_property = output_get_property,
215#endif
216 .dpms = output_dpms,
217 .detect = output_detect,
218
219 .get_modes = output_get_modes,
220 .mode_valid = output_mode_valid,
221 .destroy = output_destroy,
222};
223
224/**
225 * vmwgfx_output_explicit_overlap -- Check for explicit output overlaps
226 *
227 * This function returns TRUE iff the bounding box in screen space of an
228 * exlplicit output overlaps the bounding box in screen space of any other
229 * output.
230 */
231Bool
232vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn)
233{
234 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
235 xf86OutputPtr output;
236 ScreenPtr pScreen = pScrn->pScreen;
237 RegionRec output_union;
238 RegionRec cur_output;
239 RegionRec result;
240 struct output_private *priv;
241 xf86CrtcPtr crtc;
242 Bool overlap = FALSE;
243 int i;
244
245 (void) pScreen;
246 REGION_NULL(pScreen, &output_union);
247 REGION_NULL(pScreen, &cur_output);
248 REGION_NULL(pScreen, &result);
249
250 /*
251 * Collect a region of implicit outputs. These may overlap.
252 */
253 for (i = 0; i < config->num_output; i++) {
254 output = config->output[i];
255 priv = output->driver_private;
256 crtc = output->crtc;
257
258 if (!crtc || !crtc->enabled || !priv->is_implicit)
259 continue;
260
261 REGION_RESET(pScreen, &cur_output, &crtc->bounds);
262 REGION_UNION(pScreen, &output_union, &output_union, &cur_output);
263 }
264
265 /*
266 * Explicit outputs may not overlap any other output.
267 */
268 for (i = 0; i < config->num_output; i++) {
269 output = config->output[i];
270 priv = output->driver_private;
271 crtc = output->crtc;
272
273 if (!crtc || !crtc->enabled || priv->is_implicit)
274 continue;
275
276 REGION_RESET(pScreen, &cur_output, &crtc->bounds);
277 REGION_NULL(pScreen, &result);
278 REGION_INTERSECT(pScreen, &result, &output_union, &cur_output);
279 overlap = REGION_NOTEMPTY(vsaa->pScreen, &result);
280 if (overlap)
281 break;
282
283 REGION_UNION(pScreen, &output_union, &output_union, &cur_output);
284 }
285
286 REGION_UNINIT(pScreen, &output_union);
287 REGION_UNINIT(pScreen, &cur_output);
288 REGION_UNINIT(pScreen, &result);
289
290 return overlap;
291}
292
293void
294xorg_output_init(ScrnInfoPtr pScrn)
295{
296 modesettingPtr ms = modesettingPTR(pScrn);
297 xf86OutputPtr output;
298 drmModeResPtr res;
299 drmModeConnectorPtr drm_connector = NULL;
300 drmModeEncoderPtr drm_encoder = NULL;
301 struct output_private *priv;
302 char name[32];
303 int c, p;
304
305 res = drmModeGetResources(ms->fd);
306 if (res == 0) {
307 DRV_ERROR("Failed drmModeGetResources\n");
308 return;
309 }
310
311 for (c = 0; c < res->count_connectors; c++) {
312 Bool is_implicit = TRUE;
313
314 drm_connector = drmModeGetConnector(ms->fd, res->connectors[c]);
315 if (!drm_connector)
316 goto out;
317
318
319 for (p = 0; p < drm_connector->count_props; p++) {
320 drmModePropertyPtr prop;
321
322 prop = drmModeGetProperty(ms->fd, drm_connector->props[p]);
323
324 if (prop) {
325
326#if 0
327 /*
328 * Disabled until we sort out what the interface should
329 * look like.
330 */
331
332 if (strcmp(prop->name, "implicit placement") == 0) {
333 drmModeConnectorSetProperty(ms->fd,
334 drm_connector->connector_id,
335 prop->prop_id,
336 0);
337 is_implicit = FALSE;
338 }
339#endif
340 drmModeFreeProperty(prop);
341 }
342 }
343
344 if (drm_connector->connector_type >=
345 sizeof(output_enum_list) / sizeof(output_enum_list[0]))
346 drm_connector->connector_type = 0;
347
348 snprintf(name, 32, "%s%d",
349 output_enum_list[drm_connector->connector_type],
350 drm_connector->connector_type_id);
351
352
353 priv = calloc(sizeof(*priv), 1);
354 if (!priv) {
355 continue;
356 }
357
358 output = xf86OutputCreate(pScrn, &output_funcs, name);
359 if (!output) {
360 free(priv);
361 continue;
362 }
363
364 priv->is_implicit = is_implicit;
365
366 drm_encoder = drmModeGetEncoder(ms->fd, drm_connector->encoders[0]);
367 if (drm_encoder) {
368 output->possible_crtcs = drm_encoder->possible_crtcs;
369 output->possible_clones = drm_encoder->possible_clones;
370 } else {
371 output->possible_crtcs = 0;
372 output->possible_clones = 0;
373 }
374 priv->c = c;
375 priv->drm_connector = drm_connector;
376 output->driver_private = priv;
377 output->subpixel_order = SubPixelHorizontalRGB;
378 output->interlaceAllowed = FALSE;
379 output->doubleScanAllowed = FALSE;
380 }
381
382 out:
383 drmModeFreeResources(res);
384}
385
386unsigned
387xorg_output_get_id(xf86OutputPtr output)
388{
389 struct output_private *priv = output->driver_private;
390 return priv->drm_connector->connector_id;
391}
392
393/* vim: set sw=4 ts=8 sts=4: */
diff --git a/vmwgfx/vmwgfx_overlay.c b/vmwgfx/vmwgfx_overlay.c
new file mode 100644
index 0000000..6624a10
--- /dev/null
+++ b/vmwgfx/vmwgfx_overlay.c
@@ -0,0 +1,893 @@
1/*
2 * Copyright 2007-2011 by VMware, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 *
27 */
28
29/*
30 * vmwarevideo.c --
31 *
32 * Xv extension support.
33 * See http://www.xfree86.org/current/DESIGN16.html
34 *
35 */
36
37
38#include "xf86xv.h"
39#include "fourcc.h"
40#define debug_printf(...)
41
42/*
43 * We can't incude svga_types.h due to conflicting types for Bool.
44 */
45typedef int64_t int64;
46typedef uint64_t uint64;
47
48typedef int32_t int32;
49typedef uint32_t uint32;
50
51typedef int16_t int16;
52typedef uint16_t uint16;
53
54typedef int8_t int8;
55typedef uint8_t uint8;
56
57#include "../src/svga_reg.h"
58#include "../src/svga_escape.h"
59#include "../src/svga_overlay.h"
60
61#include <X11/extensions/Xv.h>
62
63#include "xf86drm.h"
64#include "vmwgfx_drm.h"
65#include "vmwgfx_drmi.h"
66#include "vmwgfx_driver.h"
67
68#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
69
70/*
71 * Number of videos that can be played simultaneously
72 */
73#define VMWARE_VID_NUM_PORTS 1
74
75/*
76 * Using a dark shade as the default colorKey
77 */
78#define VMWARE_VIDEO_COLORKEY 0x100701
79
80/*
81 * Maximum dimensions
82 */
83#define VMWARE_VID_MAX_WIDTH 2048
84#define VMWARE_VID_MAX_HEIGHT 2048
85
86#define VMWARE_VID_NUM_ENCODINGS 1
87static XF86VideoEncodingRec vmwareVideoEncodings[] =
88{
89 {
90 0,
91 "XV_IMAGE",
92 VMWARE_VID_MAX_WIDTH, VMWARE_VID_MAX_HEIGHT,
93 {1, 1}
94 }
95};
96
97#define VMWARE_VID_NUM_FORMATS 2
98static XF86VideoFormatRec vmwareVideoFormats[] =
99{
100 { 16, TrueColor},
101 { 24, TrueColor}
102};
103
104#define VMWARE_VID_NUM_IMAGES 3
105static XF86ImageRec vmwareVideoImages[] =
106{
107 XVIMAGE_YV12,
108 XVIMAGE_YUY2,
109 XVIMAGE_UYVY
110};
111
112#define VMWARE_VID_NUM_ATTRIBUTES 2
113static XF86AttributeRec vmwareVideoAttributes[] =
114{
115 {
116 XvGettable | XvSettable,
117 0x000000,
118 0xffffff,
119 "XV_COLORKEY"
120 },
121 {
122 XvGettable | XvSettable,
123 0,
124 1,
125 "XV_AUTOPAINT_COLORKEY"
126 }
127};
128
129/*
130 * Video frames are stored in a circular list of buffers.
131 * Must be power or two, See vmw_video_port_play.
132 */
133#define VMWARE_VID_NUM_BUFFERS 1
134
135/*
136 * Defines the structure used to hold and pass video data to the host
137 */
138struct vmw_video_buffer
139{
140 int size;
141 void *data;
142 struct vmwgfx_dmabuf *buf;
143};
144
145
146/**
147 * Structure representing a single video stream, aka port.
148 *
149 * Ports maps one to one to a SVGA stream. Port is just
150 * what Xv calls a SVGA stream.
151 */
152struct vmwgfx_overlay_port
153{
154 /*
155 * Function prototype same as XvPutImage.
156 *
157 * This is either set to vmw_video_port_init or vmw_video_port_play.
158 * At init this function is set to port_init. In port_init we set it
159 * to port_play and call it, after initializing the struct.
160 */
161 int (*play)(ScrnInfoPtr, struct vmwgfx_overlay_port *,
162 short, short, short, short, short,
163 short, short, short, int, unsigned char*,
164 short, short, RegionPtr);
165
166 /* values to go into the SVGAOverlayUnit */
167 uint32 streamId;
168 uint32 colorKey;
169 uint32 flags;
170
171 /* round robin of buffers */
172 unsigned currBuf;
173 struct vmw_video_buffer bufs[VMWARE_VID_NUM_BUFFERS];
174
175 /* properties that applies to all buffers */
176 int size;
177 int pitches[3];
178 int offsets[3];
179
180 /* things for X */
181 RegionRec clipBoxes;
182 Bool isAutoPaintColorkey;
183 int drm_fd;
184};
185
186/*
187 * Callback functions exported to Xv, prefixed with vmw_xv_*.
188 */
189static int vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y,
190 short drw_x, short drw_y, short src_w, short src_h,
191 short drw_w, short drw_h, int image,
192 unsigned char *buf, short width, short height,
193 Bool sync, RegionPtr clipBoxes, pointer data,
194 DrawablePtr dst);
195static void vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool Cleanup);
196static int vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format,
197 unsigned short *width,
198 unsigned short *height, int *pitches,
199 int *offsets);
200static int vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute,
201 INT32 value, pointer data);
202static int vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute,
203 INT32 *value, pointer data);
204static void vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion,
205 short vid_w, short vid_h, short drw_w,
206 short drw_h, unsigned int *p_w,
207 unsigned int *p_h, pointer data);
208
209
210/*
211 * Local functions.
212 */
213static int vmw_video_port_init(ScrnInfoPtr pScrn,
214 struct vmwgfx_overlay_port *port,
215 short src_x, short src_y, short drw_x,
216 short drw_y, short src_w, short src_h,
217 short drw_w, short drw_h, int format,
218 unsigned char *buf, short width,
219 short height, RegionPtr clipBoxes);
220static int vmw_video_port_play(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port,
221 short src_x, short src_y, short drw_x,
222 short drw_y, short src_w, short src_h,
223 short drw_w, short drw_h, int format,
224 unsigned char *buf, short width,
225 short height, RegionPtr clipBoxes);
226static void vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port);
227
228static int vmw_video_buffer_alloc(int drm_fd, int size,
229 struct vmw_video_buffer *out);
230static int vmw_video_buffer_free(struct vmw_video_buffer *out);
231
232
233static struct vmwgfx_overlay_port *
234vmwgfx_overlay_port_create(int drm_fd, ScreenPtr pScreen)
235{
236 struct vmwgfx_overlay_port *port = calloc(1, sizeof(*port));
237
238 if (!port)
239 return NULL;
240
241 port->drm_fd = drm_fd;
242 port->play = vmw_video_port_init;
243 port->flags = SVGA_VIDEO_FLAG_COLORKEY;
244 port->colorKey = VMWARE_VIDEO_COLORKEY;
245 port->isAutoPaintColorkey = TRUE;
246 return port;
247}
248
249void
250vmw_video_free_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports)
251{
252 if (free_ports) {
253 int i;
254
255 for(i=0; i<adaptor->nPorts; ++i) {
256 free(adaptor->pPortPrivates[i].ptr);
257 }
258 }
259
260 free(adaptor->pPortPrivates);
261 xf86XVFreeVideoAdaptorRec(adaptor);
262}
263
264/*
265 *-----------------------------------------------------------------------------
266 *
267 * vmw_video_init_adaptor --
268 *
269 * Initializes a XF86VideoAdaptor structure with the capabilities and
270 * functions supported by this video driver.
271 *
272 * Results:
273 * On success initialized XF86VideoAdaptor struct or NULL on error
274 *
275 * Side effects:
276 * None.
277 *
278 *-----------------------------------------------------------------------------
279 */
280
281XF86VideoAdaptorPtr
282vmw_video_init_adaptor(ScrnInfoPtr pScrn)
283{
284 XF86VideoAdaptorPtr adaptor;
285 modesettingPtr ms = modesettingPTR(pScrn);
286 int i;
287 DevUnion *dev_unions;
288 uint32_t ntot, nfree;
289
290 if (vmwgfx_num_streams(ms->fd, &ntot, &nfree) != 0) {
291 debug_printf("No stream ioctl support\n");
292 return NULL;
293 }
294 if (nfree == 0) {
295 debug_printf("No free streams\n");
296 return NULL;
297 }
298 adaptor = xf86XVAllocateVideoAdaptorRec(pScrn);
299 dev_unions = calloc(VMWARE_VID_NUM_PORTS, sizeof(DevUnion));
300 if (adaptor == NULL || dev_unions == NULL) {
301 xf86XVFreeVideoAdaptorRec(adaptor);
302 free(dev_unions);
303 return NULL;
304 }
305
306 adaptor->type = XvInputMask | XvImageMask | XvWindowMask;
307
308 /**
309 * Note: CLIP_TO_VIEWPORT was removed from the flags, since with the
310 * crtc/output based modesetting, the viewport is not updated on
311 * RandR modeswitches. Hence the video may incorrectly be clipped away.
312 * The correct approach, (if needed) would be to clip against the
313 * scanout area union of all active crtcs. Revisit if needed.
314 */
315
316 adaptor->flags = VIDEO_OVERLAID_IMAGES;
317 adaptor->name = "VMware Overlay Video Engine";
318 adaptor->nEncodings = VMWARE_VID_NUM_ENCODINGS;
319 adaptor->pEncodings = vmwareVideoEncodings;
320 adaptor->nFormats = VMWARE_VID_NUM_FORMATS;
321 adaptor->pFormats = vmwareVideoFormats;
322 adaptor->nPorts = VMWARE_VID_NUM_PORTS;
323 adaptor->pPortPrivates = dev_unions;
324
325 for (i = 0; i < VMWARE_VID_NUM_PORTS; ++i) {
326 struct vmwgfx_overlay_port *priv =
327 vmwgfx_overlay_port_create(ms->fd, pScrn->pScreen);
328
329 adaptor->pPortPrivates[i].ptr = (pointer) priv;
330 }
331
332 adaptor->nAttributes = VMWARE_VID_NUM_ATTRIBUTES;
333 adaptor->pAttributes = vmwareVideoAttributes;
334 adaptor->nImages = VMWARE_VID_NUM_IMAGES;
335 adaptor->pImages = vmwareVideoImages;
336
337 adaptor->PutVideo = NULL;
338 adaptor->PutStill = NULL;
339 adaptor->GetVideo = NULL;
340 adaptor->GetStill = NULL;
341 adaptor->StopVideo = vmw_xv_stop_video;
342 adaptor->SetPortAttribute = vmw_xv_set_port_attribute;
343 adaptor->GetPortAttribute = vmw_xv_get_port_attribute;
344 adaptor->QueryBestSize = vmw_xv_query_best_size;
345 adaptor->PutImage = vmw_xv_put_image;
346 adaptor->QueryImageAttributes = vmw_xv_query_image_attributes;
347
348 return adaptor;
349}
350
351
352/*
353 *-----------------------------------------------------------------------------
354 *
355 * vmw_video_port_init --
356 *
357 * Initializes a video stream in response to the first PutImage() on a
358 * video stream. The process goes as follows:
359 * - Figure out characteristics according to format
360 * - Allocate offscreen memory
361 * - Pass on video to Play() functions
362 *
363 * Results:
364 * Success or XvBadAlloc on failure.
365 *
366 * Side effects:
367 * Video stream is initialized and its first frame sent to the host
368 * (done by VideoPlay() function called at the end)
369 *
370 *-----------------------------------------------------------------------------
371 */
372
373static int
374vmw_video_port_init(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port,
375 short src_x, short src_y, short drw_x,
376 short drw_y, short src_w, short src_h,
377 short drw_w, short drw_h, int format,
378 unsigned char *buf, short width,
379 short height, RegionPtr clipBoxes)
380{
381 unsigned short w, h;
382 int i, ret;
383
384 debug_printf("\t%s: id %d, format %d\n", __func__, port->streamId, format);
385
386 ret = vmwgfx_claim_stream(port->drm_fd, &port->streamId);
387 if (ret != 0)
388 return XvBadAlloc;
389
390 w = width;
391 h = height;
392 /* init all the format attributes, used for buffers */
393 port->size = vmw_xv_query_image_attributes(pScrn, format, &w, &h,
394 port->pitches, port->offsets);
395
396 if (port->size == -1) {
397 ret = XvBadAlloc;
398 goto out_bad_size;
399 }
400
401 for (i = 0; i < VMWARE_VID_NUM_BUFFERS; ++i) {
402 ret = vmw_video_buffer_alloc(port->drm_fd, port->size, &port->bufs[i]);
403 if (ret != Success)
404 goto out_no_buffer;
405 }
406
407 port->currBuf = 0;
408 REGION_NULL(pScrn->pScreen, &port->clipBoxes);
409 port->play = vmw_video_port_play;
410 return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h,
411 drw_w, drw_h, format, buf, width, height, clipBoxes);
412
413 out_no_buffer:
414 while(i-- != 0) {
415 vmw_video_buffer_free(&port->bufs[i]);
416 }
417 out_bad_size:
418 (void) vmwgfx_unref_stream(port->drm_fd, port->streamId);
419
420 return ret;
421}
422
423
424/*
425 *-----------------------------------------------------------------------------
426 *
427 * vmw_video_port_play --
428 *
429 * Sends all the attributes associated with the video frame using the
430 * FIFO ESCAPE mechanism to the host.
431 *
432 * Results:
433 * Always returns Success.
434 *
435 * Side effects:
436 * None.
437 *
438 *-----------------------------------------------------------------------------
439 */
440
441static int
442vmw_video_port_play(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port,
443 short src_x, short src_y, short drw_x,
444 short drw_y, short src_w, short src_h,
445 short drw_w, short drw_h, int format,
446 unsigned char *buf, short width,
447 short height, RegionPtr clipBoxes)
448{
449 struct drm_vmw_control_stream_arg arg;
450 unsigned short w, h;
451 int size;
452 int ret;
453
454 debug_printf("\t%s: enter\n", __func__);
455
456 w = width;
457 h = height;
458
459 /* we don't update the ports size */
460 size = vmw_xv_query_image_attributes(pScrn, format, &w, &h,
461 port->pitches, port->offsets);
462
463 if (size != port->size) {
464 vmw_xv_stop_video(pScrn, port, TRUE);
465 return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w,
466 src_h, drw_w, drw_h, format, buf, width, height,
467 clipBoxes);
468 }
469
470 memcpy(port->bufs[port->currBuf].data, buf, port->size);
471
472 memset(&arg, 0, sizeof(arg));
473
474 arg.stream_id = port->streamId;
475 arg.enabled = TRUE;
476 arg.flags = port->flags;
477 arg.color_key = port->colorKey;
478 arg.handle = port->bufs[port->currBuf].buf->handle;
479 arg.format = format;
480 arg.size = port->size;
481 arg.width = w;
482 arg.height = h;
483 arg.src.x = src_x;
484 arg.src.y = src_y;
485 arg.src.w = src_w;
486 arg.src.h = src_h;
487 arg.dst.x = drw_x;
488 arg.dst.y = drw_y;
489 arg.dst.w = drw_w;
490 arg.dst.h = drw_h;
491 arg.pitch[0] = port->pitches[0];
492 arg.pitch[1] = port->pitches[1];
493 arg.pitch[2] = port->pitches[2];
494 arg.offset = 0;
495
496 /*
497 * Update the clipList and paint the colorkey, if required.
498 */
499 if (!REGION_EQUAL(pScrn->pScreen, &port->clipBoxes, clipBoxes)) {
500 REGION_COPY(pScrn->pScreen, &port->clipBoxes, clipBoxes);
501 if (port->isAutoPaintColorkey)
502 xf86XVFillKeyHelper(pScrn->pScreen, port->colorKey, clipBoxes);
503 }
504
505 xorg_flush(pScrn->pScreen);
506 ret = drmCommandWrite(port->drm_fd, DRM_VMW_CONTROL_STREAM, &arg, sizeof(arg));
507 if (ret) {
508 vmw_video_port_cleanup(pScrn, port);
509 return XvBadAlloc;
510 }
511
512 if (++(port->currBuf) >= VMWARE_VID_NUM_BUFFERS)
513 port->currBuf = 0;
514
515 return Success;
516}
517
518
519/*
520 *-----------------------------------------------------------------------------
521 *
522 * vmw_video_port_cleanup --
523 *
524 * Frees up all resources (if any) taken by a video stream.
525 *
526 * Results:
527 * None.
528 *
529 * Side effects:
530 * Same as above.
531 *
532 *-----------------------------------------------------------------------------
533 */
534
535static void
536vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port)
537{
538 int i;
539
540 debug_printf("\t%s: enter\n", __func__);
541
542 if (port->play == vmw_video_port_init)
543 return;
544
545 port->play = vmw_video_port_init;
546 (void) vmwgfx_unref_stream(port->drm_fd, port->streamId);
547
548 for (i = 0; i < VMWARE_VID_NUM_BUFFERS; i++) {
549 vmw_video_buffer_free(&port->bufs[i]);
550 }
551
552 REGION_UNINIT(pScreen->pScreen, &port->clipBoxes);
553}
554
555
556/*
557 *-----------------------------------------------------------------------------
558 *
559 * vmw_video_buffer_alloc --
560 *
561 * Allocates and map a kernel buffer to be used as data storage.
562 *
563 * Results:
564 * XvBadAlloc on failure, otherwise Success.
565 *
566 * Side effects:
567 * Calls into the kernel, sets members of out.
568 *
569 *-----------------------------------------------------------------------------
570 */
571
572static int
573vmw_video_buffer_alloc(int drm_fd, int size,
574 struct vmw_video_buffer *out)
575{
576 out->buf = vmwgfx_dmabuf_alloc(drm_fd, size);
577 if (!out->buf)
578 return XvBadAlloc;
579
580 out->data = vmwgfx_dmabuf_map(out->buf);
581 if (!out->data) {
582 vmwgfx_dmabuf_destroy(out->buf);
583 out->buf = NULL;
584 return XvBadAlloc;
585 }
586
587 out->size = size;
588 debug_printf("\t\t%s: allocated buffer %p of size %i\n", __func__, out, size);
589
590 return Success;
591}
592
593
594/*
595 *-----------------------------------------------------------------------------
596 *
597 * vmw_video_buffer_free --
598 *
599 * Frees and unmaps an allocated kernel buffer.
600 *
601 * Results:
602 * Success.
603 *
604 * Side effects:
605 * Calls into the kernel, sets members of out to 0.
606 *
607 *-----------------------------------------------------------------------------
608 */
609
610static int
611vmw_video_buffer_free(struct vmw_video_buffer *out)
612{
613 if (out->size == 0)
614 return Success;
615
616 vmwgfx_dmabuf_unmap(out->buf);
617 vmwgfx_dmabuf_destroy(out->buf);
618
619 out->buf = NULL;
620 out->data = NULL;
621 out->size = 0;
622
623 debug_printf("\t\t%s: freed buffer %p\n", __func__, out);
624
625 return Success;
626}
627
628
629/*
630 *-----------------------------------------------------------------------------
631 *
632 * vmw_xv_put_image --
633 *
634 * Main video playback function. It copies the passed data which is in
635 * the specified format (e.g. FOURCC_YV12) into the overlay.
636 *
637 * If sync is TRUE the driver should not return from this
638 * function until it is through reading the data from buf.
639 *
640 * Results:
641 * Success or XvBadAlloc on failure
642 *
643 * Side effects:
644 * Video port will be played(initialized if 1st frame) on success
645 * or will fail on error.
646 *
647 *-----------------------------------------------------------------------------
648 */
649
650static int
651vmw_xv_put_image(ScrnInfoPtr pScrn, short src_x, short src_y,
652 short drw_x, short drw_y, short src_w, short src_h,
653 short drw_w, short drw_h, int format,
654 unsigned char *buf, short width, short height,
655 Bool sync, RegionPtr clipBoxes, pointer data,
656 DrawablePtr dst)
657{
658 struct vmwgfx_overlay_port *port = data;
659
660 debug_printf("%s: enter (%u, %u) (%ux%u) (%u, %u) (%ux%u) (%ux%u)\n", __func__,
661 src_x, src_y, src_w, src_h,
662 drw_x, drw_y, drw_w, drw_h,
663 width, height);
664
665 return port->play(pScrn, port, src_x, src_y, drw_x, drw_y, src_w, src_h,
666 drw_w, drw_h, format, buf, width, height, clipBoxes);
667}
668
669
670/*
671 *-----------------------------------------------------------------------------
672 *
673 * vmw_xv_stop_video --
674 *
675 * Called when we should stop playing video for a particular stream. If
676 * Cleanup is FALSE, the "stop" operation is only temporary, and thus we
677 * don't do anything. If Cleanup is TRUE we kill the video port by
678 * sending a message to the host and freeing up the stream.
679 *
680 * Results:
681 * None.
682 *
683 * Side effects:
684 * See above.
685 *
686 *-----------------------------------------------------------------------------
687 */
688
689static void
690vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
691{
692 struct vmwgfx_overlay_port *port = data;
693
694 debug_printf("%s: cleanup is %s\n", __func__, cleanup ? "TRUE" : "FALSE");
695 REGION_EMPTY(pScrn->pScreen, &port->clipBoxes);
696
697 if (!cleanup)
698 return;
699
700 vmw_video_port_cleanup(pScrn, port);
701}
702
703
704/*
705 *-----------------------------------------------------------------------------
706 *
707 * vmw_xv_query_image_attributes --
708 *
709 * From the spec: This function is called to let the driver specify how data
710 * for a particular image of size width by height should be stored.
711 * Sometimes only the size and corrected width and height are needed. In
712 * that case pitches and offsets are NULL.
713 *
714 * Results:
715 * The size of the memory required for the image, or -1 on error.
716 *
717 * Side effects:
718 * None.
719 *
720 *-----------------------------------------------------------------------------
721 */
722
723static int
724vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format,
725 unsigned short *width, unsigned short *height,
726 int *pitches, int *offsets)
727{
728 INT32 size, tmp;
729
730 if (*width > VMWARE_VID_MAX_WIDTH) {
731 *width = VMWARE_VID_MAX_WIDTH;
732 }
733 if (*height > VMWARE_VID_MAX_HEIGHT) {
734 *height = VMWARE_VID_MAX_HEIGHT;
735 }
736
737 *width = (*width + 1) & ~1;
738 if (offsets != NULL) {
739 offsets[0] = 0;
740 }
741
742 switch (format) {
743 case FOURCC_YV12:
744 *height = (*height + 1) & ~1;
745 size = (*width + 3) & ~3;
746 if (pitches) {
747 pitches[0] = size;
748 }
749 size *= *height;
750 if (offsets) {
751 offsets[1] = size;
752 }
753 tmp = ((*width >> 1) + 3) & ~3;
754 if (pitches) {
755 pitches[1] = pitches[2] = tmp;
756 }
757 tmp *= (*height >> 1);
758 size += tmp;
759 if (offsets) {
760 offsets[2] = size;
761 }
762 size += tmp;
763 break;
764 case FOURCC_UYVY:
765 case FOURCC_YUY2:
766 size = *width * 2;
767 if (pitches) {
768 pitches[0] = size;
769 }
770 size *= *height;
771 break;
772 default:
773 debug_printf("Query for invalid video format %d\n", format);
774 return -1;
775 }
776 return size;
777}
778
779
780/*
781 *-----------------------------------------------------------------------------
782 *
783 * vmw_xv_set_port_attribute --
784 *
785 * From the spec: A port may have particular attributes such as colorKey, hue,
786 * saturation, brightness or contrast. Xv clients set these
787 * attribute values by sending attribute strings (Atoms) to the server.
788 *
789 * Results:
790 * Success if the attribute exists and XvBadAlloc otherwise.
791 *
792 * Side effects:
793 * The respective attribute gets the new value.
794 *
795 *-----------------------------------------------------------------------------
796 */
797
798static int
799vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute,
800 INT32 value, pointer data)
801{
802 struct vmwgfx_overlay_port *port = data;
803 Atom xvColorKey = MAKE_ATOM("XV_COLORKEY");
804 Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
805
806 if (attribute == xvColorKey) {
807 debug_printf("%s: Set colorkey:0x%x\n", __func__, (unsigned)value);
808 port->colorKey = value;
809 } else if (attribute == xvAutoPaint) {
810 debug_printf("%s: Set autoPaint: %s\n", __func__, value? "TRUE": "FALSE");
811 port->isAutoPaintColorkey = value;
812 } else {
813 return XvBadAlloc;
814 }
815
816 return Success;
817}
818
819
820/*
821 *-----------------------------------------------------------------------------
822 *
823 * vmw_xv_get_port_attribute --
824 *
825 * From the spec: A port may have particular attributes such as hue,
826 * saturation, brightness or contrast. Xv clients get these
827 * attribute values by sending attribute strings (Atoms) to the server
828 *
829 * Results:
830 * Success if the attribute exists and XvBadAlloc otherwise.
831 *
832 * Side effects:
833 * "value" contains the requested attribute on success.
834 *
835 *-----------------------------------------------------------------------------
836 */
837
838static int
839vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute,
840 INT32 *value, pointer data)
841{
842 struct vmwgfx_overlay_port *port = data;
843 Atom xvColorKey = MAKE_ATOM("XV_COLORKEY");
844 Atom xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
845
846 if (attribute == xvColorKey) {
847 *value = port->colorKey;
848 } else if (attribute == xvAutoPaint) {
849 *value = port->isAutoPaintColorkey;
850 } else {
851 return XvBadAlloc;
852 }
853
854 return Success;
855}
856
857
858/*
859 *-----------------------------------------------------------------------------
860 *
861 * vmw_xv_query_best_size --
862 *
863 * From the spec: QueryBestSize provides the client with a way to query what
864 * the destination dimensions would end up being if they were to request
865 * that an area vid_w by vid_h from the video stream be scaled to rectangle
866 * of drw_w by drw_h on the screen. Since it is not expected that all
867 * hardware will be able to get the target dimensions exactly, it is
868 * important that the driver provide this function.
869 *
870 * This function seems to never be called, but to be on the safe side
871 * we apply the same logic that QueryImageAttributes has for width
872 * and height.
873 *
874 * Results:
875 * None.
876 *
877 * Side effects:
878 * None.
879 *
880 *-----------------------------------------------------------------------------
881 */
882
883static void
884vmw_xv_query_best_size(ScrnInfoPtr pScrn, Bool motion,
885 short vid_w, short vid_h, short drw_w,
886 short drw_h, unsigned int *p_w,
887 unsigned int *p_h, pointer data)
888{
889 *p_w = (drw_w + 1) & ~1;
890 *p_h = drw_h;
891
892 return;
893}
diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c
new file mode 100644
index 0000000..0a6b98f
--- /dev/null
+++ b/vmwgfx/vmwgfx_saa.c
@@ -0,0 +1,1514 @@
1/*
2 * Copyright 2011 VMWare, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Thomas Hellstrom <thellstrom@vmware.com>
26 */
27
28#include <xorg-server.h>
29#include <mi.h>
30#include <fb.h>
31#include <xf86drmMode.h>
32#include <xa_context.h>
33#include "vmwgfx_saa.h"
34#include "vmwgfx_drmi.h"
35#include "vmwgfx_saa_priv.h"
36
37/*
38 * Damage to be added as soon as we attach storage to the pixmap.
39 */
40static Bool
41vmwgfx_pixmap_add_damage(PixmapPtr pixmap)
42{
43 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
44 struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
45 DrawablePtr draw = &pixmap->drawable;
46 BoxRec box;
47
48 if (spix->damage)
49 return TRUE;
50
51 if (!saa_add_damage(pixmap))
52 return FALSE;
53
54 box.x1 = 0;
55 box.x2 = draw->width;
56 box.y1 = 0;
57 box.y2 = draw->height;
58
59 if (vpix->hw) {
60 REGION_RESET(draw->pScreen, &spix->dirty_hw, &box);
61 REGION_EMPTY(draw->pScreen, &spix->dirty_shadow);
62 } else {
63 REGION_RESET(draw->pScreen, &spix->dirty_shadow, &box);
64 REGION_EMPTY(draw->pScreen, &spix->dirty_hw);
65 }
66
67 return TRUE;
68}
69
70static void
71vmwgfx_pixmap_remove_damage(PixmapPtr pixmap)
72{
73 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
74 struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
75
76 if (!spix->damage || vpix->hw || vpix->gmr || vpix->malloc)
77 return;
78
79 DamageUnregister(&pixmap->drawable, spix->damage);
80 DamageDestroy(spix->damage);
81 spix->damage = NULL;
82}
83
84static void
85vmwgfx_pixmap_remove_present(struct vmwgfx_saa_pixmap *vpix)
86{
87 if (vpix->dirty_present)
88 REGION_DESTROY(pixmap->drawable.pScreen, vpix->dirty_present);
89 if (vpix->present_damage)
90 REGION_DESTROY(pixmap->drawable.pScreen, vpix->present_damage);
91 if (vpix->pending_update)
92 REGION_DESTROY(pixmap->drawable.pScreen, vpix->pending_update);
93 if (vpix->pending_present)
94 REGION_DESTROY(pixmap->drawable.pScreen, vpix->pending_present);
95 vpix->dirty_present = NULL;
96 vpix->present_damage = NULL;
97 vpix->pending_update = NULL;
98 vpix->pending_present = NULL;
99}
100
101static Bool
102vmwgfx_pixmap_add_present(PixmapPtr pixmap, Bool present_opt)
103{
104 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
105 ScreenPtr pScreen = pixmap->drawable.pScreen;
106 (void) pScreen;
107
108 if (present_opt) {
109 vpix->dirty_present = REGION_CREATE(pScreen, NULL, 0);
110 if (!vpix->dirty_present)
111 return FALSE;
112 vpix->present_damage = REGION_CREATE(pScreen, NULL, 0);
113 if (!vpix->present_damage)
114 goto out_no_present_damage;
115 }
116 vpix->pending_update = REGION_CREATE(pScreen, NULL, 0);
117 if (!vpix->pending_update)
118 goto out_no_pending_update;
119 vpix->pending_present = REGION_CREATE(pScreen, NULL, 0);
120 if (!vpix->pending_present)
121 goto out_no_pending_present;
122
123 return TRUE;
124 out_no_pending_present:
125 REGION_DESTROY(pScreen, vpix->pending_update);
126 out_no_pending_update:
127 if (vpix->present_damage)
128 REGION_DESTROY(pScreen, vpix->present_damage);
129 out_no_present_damage:
130 if (vpix->dirty_present)
131 REGION_DESTROY(pScreen, vpix->dirty_present);
132 return FALSE;
133}
134
135static void
136vmwgfx_pixmap_free_storage(struct vmwgfx_saa_pixmap *vpix)
137{
138 if (!(vpix->backing & VMWGFX_PIX_MALLOC) && vpix->malloc) {
139 free(vpix->malloc);
140 vpix->malloc = NULL;
141 }
142 if (!(vpix->backing & VMWGFX_PIX_SURFACE) && vpix->hw) {
143 xa_surface_destroy(vpix->hw);
144 vpix->hw = NULL;
145 }
146 if (!(vpix->backing & VMWGFX_PIX_GMR) && vpix->gmr) {
147 vmwgfx_dmabuf_destroy(vpix->gmr);
148 vpix->gmr = NULL;
149 }
150}
151
152static Bool
153vmwgfx_pixmap_create_gmr(struct vmwgfx_saa *vsaa, PixmapPtr pixmap)
154{
155 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
156 size_t size;
157 struct vmwgfx_dmabuf *gmr;
158 void *addr;
159
160 if (vpix->gmr)
161 return TRUE;
162
163 size = pixmap->devKind * pixmap->drawable.height;
164 gmr = vmwgfx_dmabuf_alloc(vsaa->drm_fd, size);
165 if (!gmr)
166 return FALSE;
167
168 if (vpix->malloc) {
169
170 addr = vmwgfx_dmabuf_map(gmr);
171 if (!addr)
172 goto out_no_transfer;
173 memcpy(addr, vpix->malloc, size);
174 vmwgfx_dmabuf_unmap(gmr);
175
176 } else if (!vmwgfx_pixmap_add_damage(pixmap))
177 goto out_no_transfer;
178
179 vpix->backing |= VMWGFX_PIX_GMR;
180 vpix->backing &= ~VMWGFX_PIX_MALLOC;
181 vpix->gmr = gmr;
182
183 vmwgfx_pixmap_free_storage(vpix);
184
185 return TRUE;
186
187 out_no_transfer:
188 vmwgfx_dmabuf_destroy(gmr);
189 return FALSE;
190}
191
192static Bool
193vmwgfx_pixmap_create_sw(struct vmwgfx_saa *vsaa, PixmapPtr pixmap)
194{
195 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
196
197 if (!(vpix->backing & (VMWGFX_PIX_MALLOC | VMWGFX_PIX_GMR)))
198 return FALSE;
199
200 if (!vpix->malloc && (vpix->backing & VMWGFX_PIX_MALLOC)) {
201 vpix->malloc = malloc(pixmap->devKind * pixmap->drawable.height);
202 if (!vpix->malloc)
203 goto out_no_malloc;
204 if (!vmwgfx_pixmap_add_damage(pixmap))
205 goto out_no_damage;
206 } else if (vpix->backing & VMWGFX_PIX_GMR)
207 return vmwgfx_pixmap_create_gmr(vsaa, pixmap);
208
209 return TRUE;
210
211 out_no_damage:
212 free(vpix->malloc);
213 vpix->malloc = NULL;
214 out_no_malloc:
215 return FALSE;
216}
217
218
219/**
220 *
221 * Makes sure all presented contents covered by @region are read
222 * back and are present in a valid GMR.
223 */
224
225static Bool
226vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa,
227 PixmapPtr pixmap,
228 RegionPtr region)
229{
230 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
231 struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
232 RegionRec intersection;
233
234 if (!spix->damage || !REGION_NOTEMPTY(vsaa->pScreen, &spix->dirty_hw) ||
235 !vpix->dirty_present)
236 return TRUE;
237
238 /*
239 * Intersect dirty region with region to be read back, if any.
240 */
241
242 REGION_NULL(vsaa->pScreen, &intersection);
243 REGION_COPY(vsaa->pScreen, &intersection, &spix->dirty_hw);
244 REGION_INTERSECT(vsaa->pScreen, &intersection, &intersection,
245 vpix->dirty_present);
246
247 if (region)
248 REGION_INTERSECT(vsaa->pScreen, &intersection, &intersection, region);
249
250 if (!REGION_NOTEMPTY(vsaa->pScreen, &intersection))
251 goto out;
252
253 /*
254 * Make really sure there is a GMR to read back to.
255 */
256
257 if (!vmwgfx_pixmap_create_gmr(vsaa, pixmap))
258 goto out_err;
259
260 if (vmwgfx_present_readback(vsaa->drm_fd, vpix->fb_id,
261 &intersection) != 0)
262 goto out_err;
263
264 REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_hw,
265 &spix->dirty_hw, &intersection);
266 out:
267 REGION_UNINIT(vsaa->pScreen, &intersection);
268 return TRUE;
269
270 out_err:
271 REGION_UNINIT(vsaa->pScreen, &intersection);
272 return FALSE;
273}
274
275static Bool
276vmwgfx_saa_dma(struct vmwgfx_saa *vsaa,
277 PixmapPtr pixmap,
278 RegionPtr reg,
279 Bool to_hw)
280{
281 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
282
283 if (!vpix->hw || (!vpix->gmr && !vpix->malloc))
284 return TRUE;
285
286 if (vpix->gmr && vsaa->can_optimize_dma) {
287 uint32_t handle, dummy;
288
289 if (xa_surface_handle(vpix->hw, &handle, &dummy) != 0)
290 goto out_err;
291 if (vmwgfx_dma(0, 0, reg, vpix->gmr, pixmap->devKind, handle,
292 to_hw) != 0)
293 goto out_err;
294 } else {
295 void *data = vpix->malloc;
296 int ret;
297
298 if (vpix->gmr) {
299 data = vmwgfx_dmabuf_map(vpix->gmr);
300 if (!data)
301 goto out_err;
302 }
303
304 ret = xa_surface_dma(vsaa->xa_ctx, vpix->hw, data, pixmap->devKind,
305 (int) to_hw,
306 (struct xa_box *) REGION_RECTS(reg),
307 REGION_NUM_RECTS(reg));
308 if (vpix->gmr)
309 vmwgfx_dmabuf_unmap(vpix->gmr);
310 if (ret)
311 goto out_err;
312 }
313 return TRUE;
314 out_err:
315 LogMessage(X_ERROR, "DMA %s surface failed.\n",
316 to_hw ? "to" : "from");
317 return FALSE;
318}
319
320
321static Bool
322vmwgfx_download_from_hw(struct saa_driver *driver, PixmapPtr pixmap,
323 RegionPtr readback)
324{
325 struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
326 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
327 struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
328
329 RegionRec intersection;
330
331 if (!vmwgfx_pixmap_present_readback(vsaa, pixmap, readback))
332 return FALSE;
333
334 if (!REGION_NOTEMPTY(vsaa->pScreen, &spix->dirty_hw))
335 return TRUE;
336
337 if (!vpix->hw)
338 return TRUE;
339
340 REGION_NULL(vsaa->pScreen, &intersection);
341 REGION_INTERSECT(vsaa->pScreen, &intersection, readback,
342 &spix->dirty_hw);
343 readback = &intersection;
344
345 if (!vmwgfx_pixmap_create_sw(vsaa, pixmap))
346 goto out_err;
347
348 if (!vmwgfx_saa_dma(vsaa, pixmap, readback, FALSE))
349 goto out_err;
350 REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_hw, &spix->dirty_hw, readback);
351 REGION_UNINIT(vsaa->pScreen, &intersection);
352 return TRUE;
353 out_err:
354 REGION_UNINIT(vsaa->pScreen, &intersection);
355 return FALSE;
356}
357
358
359static Bool
360vmwgfx_upload_to_hw(struct saa_driver *driver, PixmapPtr pixmap,
361 RegionPtr upload)
362{
363 return vmwgfx_saa_dma(to_vmwgfx_saa(driver), pixmap, upload, TRUE);
364}
365
366static void
367vmwgfx_release_from_cpu(struct saa_driver *driver, PixmapPtr pixmap, saa_access_t access)
368{
369 // LogMessage(X_INFO, "Release 0x%08lx access 0x%08x\n",
370 // (unsigned long) pixmap, (unsigned) access);
371}
372
373static void *
374vmwgfx_sync_for_cpu(struct saa_driver *driver, PixmapPtr pixmap, saa_access_t access)
375{
376 /*
377 * Errors in this functions will turn up in subsequent map
378 * calls.
379 */
380
381 (void) vmwgfx_pixmap_create_sw(to_vmwgfx_saa(driver), pixmap);
382
383 return NULL;
384}
385
386static void *
387vmwgfx_map(struct saa_driver *driver, PixmapPtr pixmap, saa_access_t access)
388{
389 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
390
391 if (vpix->malloc)
392 return vpix->malloc;
393 else if (vpix->gmr)
394 return vmwgfx_dmabuf_map(vpix->gmr);
395 else
396 return NULL;
397}
398
399static void
400vmwgfx_unmap(struct saa_driver *driver, PixmapPtr pixmap, saa_access_t access)
401{
402 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
403
404 if (vpix->gmr)
405 return vmwgfx_dmabuf_unmap(vpix->gmr);
406
407// LogMessage(X_INFO, "Unmap 0x%08lx access 0x%08x\n",
408 // (unsigned long) pixmap, (unsigned) access);
409 ;
410}
411
412static Bool
413vmwgfx_create_pixmap(struct saa_driver *driver, struct saa_pixmap *spix,
414 int w, int h, int depth,
415 unsigned int usage_hint, int bpp, int *new_pitch)
416{
417 struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
418
419 *new_pitch = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
420
421 WSBMINITLISTHEAD(&vpix->sync_x_head);
422 WSBMINITLISTHEAD(&vpix->scanout_list);
423
424 return TRUE;
425}
426
427Bool
428vmwgfx_hw_kill(struct vmwgfx_saa *vsaa,
429 struct saa_pixmap *spix)
430{
431 struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
432
433 if (!vpix->hw)
434 return TRUE;
435
436 /*
437 * Read back any dirty regions from hardware.
438 */
439
440 if (!vmwgfx_download_from_hw(&vsaa->driver, spix->pixmap,
441 &spix->dirty_hw))
442 return FALSE;
443
444 xa_surface_destroy(vpix->hw);
445 vpix->hw = NULL;
446
447 /*
448 * Remove damage tracking if this is not a scanout pixmap.
449 */
450
451 if (WSBMLISTEMPTY(&vpix->scanout_list))
452 vmwgfx_pixmap_remove_damage(spix->pixmap);
453
454 return TRUE;
455}
456
457void
458vmwgfx_flush_dri2(ScreenPtr pScreen)
459{
460 struct vmwgfx_saa *vsaa =
461 to_vmwgfx_saa(saa_get_driver(pScreen));
462 struct _WsbmListHead *list, *next;
463 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
464
465 if (!pScrn->vtSema)
466 return;
467
468 WSBMLISTFOREACHSAFE(list, next, &vsaa->sync_x_list) {
469 struct vmwgfx_saa_pixmap *vpix =
470 WSBMLISTENTRY(list, struct vmwgfx_saa_pixmap, sync_x_head);
471 struct saa_pixmap *spix = &vpix->base;
472 PixmapPtr pixmap = spix->pixmap;
473
474 if (vmwgfx_upload_to_hw(&vsaa->driver, pixmap, &spix->dirty_shadow)) {
475 REGION_EMPTY(vsaa->pScreen, &spix->dirty_shadow);
476 WSBMLISTDELINIT(list);
477 }
478 }
479}
480
481
482static void
483vmwgfx_destroy_pixmap(struct saa_driver *driver, PixmapPtr pixmap)
484{
485 ScreenPtr pScreen = to_vmwgfx_saa(driver)->pScreen;
486 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
487 (void) pScreen;
488
489 vpix->backing = 0;
490 vmwgfx_pixmap_free_storage(vpix);
491
492 /*
493 * Any damage we've registered has already been removed by the server
494 * at this point. Any attempt to unregister / destroy it will result
495 * in a double free.
496 */
497
498 vmwgfx_pixmap_remove_present(vpix);
499 WSBMLISTDELINIT(&vpix->sync_x_head);
500
501 if (vpix->hw_is_dri2_fronts)
502 LogMessage(X_ERROR, "Incorrect dri2 front count.\n");
503}
504
505
506
507/**
508 *
509 * Makes sure we have a surface with valid contents.
510 */
511
512static void
513vmwgfx_copy_stride(uint8_t *dst, uint8_t *src, unsigned int dst_pitch,
514 unsigned int src_pitch, unsigned int dst_height,
515 unsigned int src_height)
516{
517 unsigned int i;
518 unsigned int height = (dst_height < src_height) ? dst_height : src_height;
519 unsigned int pitch = (dst_pitch < src_pitch) ? dst_pitch : src_pitch;
520
521 for(i=0; i<height; ++i) {
522 memcpy(dst, src, pitch);
523 dst += dst_pitch;
524 src += src_pitch;
525 }
526}
527
528
529static Bool
530vmwgfx_pix_resize(PixmapPtr pixmap, unsigned int old_pitch,
531 unsigned int old_height, unsigned int old_width)
532{
533 ScreenPtr pScreen = pixmap->drawable.pScreen;
534 struct vmwgfx_saa *vsaa = to_vmwgfx_saa(saa_get_driver(pScreen));
535 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
536 struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
537 DrawablePtr draw = &pixmap->drawable;
538 unsigned int size = pixmap->devKind * draw->height;
539 BoxRec b_box;
540 RegionRec b_reg;
541
542 /*
543 * Ignore copying errors. At worst they will show up as rendering
544 * artefacts.
545 */
546
547 if (vpix->malloc) {
548
549 void *new_malloc = malloc(size);
550 if (!new_malloc)
551 return FALSE;
552
553 vmwgfx_copy_stride(new_malloc, vpix->malloc, pixmap->devKind,
554 old_pitch, draw->height,
555 old_height);
556 free(vpix->malloc);
557 vpix->malloc = new_malloc;
558 }
559
560 if (vpix->gmr) {
561 struct vmwgfx_dmabuf *gmr;
562 void *new_addr;
563 void *old_addr;
564
565 gmr = vmwgfx_dmabuf_alloc(vsaa->drm_fd, size);
566 if (!gmr)
567 return FALSE;
568
569 new_addr = vmwgfx_dmabuf_map(gmr);
570 old_addr = vmwgfx_dmabuf_map(vpix->gmr);
571
572 if (new_addr && old_addr)
573 vmwgfx_copy_stride(new_addr, old_addr, pixmap->devKind,
574 old_pitch, draw->height,
575 old_height);
576 else
577 LogMessage(X_ERROR, "Failed pixmap resize copy.\n");
578
579 if (old_addr)
580 vmwgfx_dmabuf_unmap(vpix->gmr);
581 if (new_addr)
582 vmwgfx_dmabuf_unmap(gmr);
583 vmwgfx_dmabuf_destroy(vpix->gmr);
584 vpix->gmr = gmr;
585 }
586
587 if (vpix->hw) {
588 if (xa_surface_redefine(vpix->hw, draw->width, draw->height,
589 draw->depth, xa_type_argb,
590 xa_format_unknown, vpix->xa_flags, 1) != 0)
591 return FALSE;
592 }
593
594 b_box.x1 = 0;
595 b_box.x2 = draw->width;
596 b_box.y1 = 0;
597 b_box.y2 = draw->height;
598
599 REGION_INIT(pScreen, &b_reg, &b_box, 1);
600 REGION_INTERSECT(pScreen, &spix->dirty_shadow, &spix->dirty_shadow,
601 &b_reg);
602 REGION_INTERSECT(pScreen, &spix->dirty_hw, &spix->dirty_hw, &b_reg);
603 if (vpix->dirty_present)
604 REGION_INTERSECT(pScreen, vpix->dirty_present, vpix->dirty_present,
605 &b_reg);
606 if (vpix->pending_update)
607 REGION_INTERSECT(pScreen, vpix->pending_update, vpix->pending_update,
608 &b_reg);
609 if (vpix->pending_present)
610 REGION_INTERSECT(pScreen, vpix->pending_present,
611 vpix->pending_present, &b_reg);
612 if (vpix->present_damage)
613 REGION_INTERSECT(pScreen, vpix->present_damage, vpix->present_damage,
614 &b_reg);
615
616 REGION_UNINIT(pScreen, &b_reg);
617
618 return TRUE;
619}
620
621
622static Bool
623vmwgfx_modify_pixmap_header (PixmapPtr pixmap, int w, int h, int depth,
624 int bpp, int devkind, void *pixdata)
625{
626 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
627 unsigned int old_height;
628 unsigned int old_width;
629 unsigned int old_pitch;
630
631 if (!vpix) {
632 LogMessage(X_ERROR, "Not an SAA pixmap.\n");
633 return FALSE;
634 }
635
636 if (pixdata) {
637 vpix->backing = 0;
638 vmwgfx_pixmap_free_storage(vpix);
639 return FALSE;
640 }
641
642 if (depth <= 0)
643 depth = pixmap->drawable.depth;
644
645 if (bpp <= 0)
646 bpp = pixmap->drawable.bitsPerPixel;
647
648 if (w <= 0)
649 w = pixmap->drawable.width;
650
651 if (h <= 0)
652 h = pixmap->drawable.height;
653
654 if (w <= 0 || h <= 0 || depth <= 0)
655 return FALSE;
656
657 old_height = pixmap->drawable.height;
658 old_width = pixmap->drawable.width;
659 old_pitch = pixmap->devKind;
660
661 if (!miModifyPixmapHeader(pixmap, w, h, depth,
662 bpp, devkind, NULL))
663 goto out_no_modify;
664
665 if (!vpix->backing)
666 vpix->backing = VMWGFX_PIX_MALLOC;
667
668 vmwgfx_pix_resize(pixmap, old_pitch, old_height, old_width);
669 vmwgfx_pixmap_free_storage(vpix);
670 return TRUE;
671
672 out_no_modify:
673 return FALSE;
674}
675
676static Bool
677vmwgfx_present_prepare(struct vmwgfx_saa *vsaa,
678 struct vmwgfx_saa_pixmap *src_vpix,
679 struct vmwgfx_saa_pixmap *dst_vpix)
680{
681 ScreenPtr pScreen = vsaa->pScreen;
682 unsigned int dummy;
683
684 (void) pScreen;
685 if (src_vpix == dst_vpix || !src_vpix->hw ||
686 xa_surface_handle(src_vpix->hw, &vsaa->src_handle, &dummy) != 0)
687 return FALSE;
688
689 REGION_NULL(pScreen, &vsaa->present_region);
690 vsaa->diff_valid = FALSE;
691 vsaa->dst_vpix = dst_vpix;
692 vsaa->present_flush(pScreen);
693
694 return TRUE;
695}
696
697/**
698 * Determine whether we should try present copies on this pixmap.
699 */
700
701static Bool
702vmwgfx_is_present_hw(PixmapPtr pixmap)
703{
704 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
705 return (vpix->dirty_present != NULL);
706}
707
708static void
709vmwgfx_check_hw_contents(struct vmwgfx_saa *vsaa,
710 struct vmwgfx_saa_pixmap *vpix,
711 RegionPtr region,
712 Bool *has_dirty_hw,
713 Bool *has_valid_hw)
714{
715 RegionRec intersection;
716
717
718 if (!vpix->hw) {
719 *has_dirty_hw = FALSE;
720 *has_valid_hw = FALSE;
721 return;
722 }
723
724 if (!region) {
725 *has_dirty_hw = REGION_NOTEMPTY(vsaa->pScreen,
726 &vpix->base.dirty_hw);
727 *has_valid_hw = !REGION_NOTEMPTY(vsaa->pScreen,
728 &vpix->base.dirty_shadow);
729 return;
730 }
731
732 REGION_NULL(vsaa->pScreen, &intersection);
733 REGION_INTERSECT(vsaa->pScreen, &intersection, &vpix->base.dirty_hw,
734 region);
735 *has_dirty_hw = REGION_NOTEMPTY(vsaa->pScreen, &intersection);
736 REGION_INTERSECT(vsaa->pScreen, &intersection, &vpix->base.dirty_shadow,
737 region);
738 *has_valid_hw = !REGION_NOTEMPTY(vsaa->pScreen, &intersection);
739 REGION_UNINIT(vsaa->pScreen, &intersection);
740}
741
742
743Bool
744vmwgfx_create_hw(struct vmwgfx_saa *vsaa,
745 PixmapPtr pixmap)
746{
747 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
748 struct xa_surface *hw;
749 uint32_t new_flags;
750
751 if (!vsaa->xat)
752 return FALSE;
753
754 if (vpix->hw)
755 return TRUE;
756
757 new_flags = (vpix->xa_flags & ~vpix->staging_remove_flags) |
758 vpix->staging_add_flags;
759
760 hw = xa_surface_create(vsaa->xat,
761 pixmap->drawable.width,
762 pixmap->drawable.height,
763 0,
764 xa_type_other,
765 vpix->staging_format,
766 new_flags);
767 if (hw == NULL)
768 return FALSE;
769
770 vpix->xa_flags = new_flags;
771
772 if (!vmwgfx_pixmap_add_damage(pixmap))
773 goto out_no_damage;
774
775 /*
776 * Even if we don't have a GMR yet, indicate that when needed it
777 * should be created.
778 */
779
780 vpix->hw = hw;
781 vpix->backing |= VMWGFX_PIX_SURFACE;
782 vmwgfx_pixmap_free_storage(vpix);
783
784 return TRUE;
785
786out_no_damage:
787 xa_surface_destroy(hw);
788 return FALSE;
789}
790
791
792Bool
793vmwgfx_hw_validate(PixmapPtr pixmap, RegionPtr region)
794{
795 struct vmwgfx_saa *vsaa =
796 to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
797 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
798 struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
799 RegionRec intersection;
800
801 if (!vmwgfx_pixmap_present_readback(vsaa, pixmap, region))
802 return FALSE;
803
804 REGION_NULL(vsaa->pScreen, &intersection);
805 REGION_COPY(vsaa->pScreen, &intersection, &spix->dirty_shadow);
806
807 if (vpix->dirty_present)
808 REGION_UNION(vsaa->pScreen, &intersection, vpix->dirty_present,
809 &spix->dirty_shadow);
810
811 if (spix->damage && REGION_NOTEMPTY(vsaa->pScreen, &intersection)) {
812 RegionPtr upload = &intersection;
813
814 /*
815 * Check whether we need to upload from GMR.
816 */
817
818 if (region) {
819 REGION_INTERSECT(vsaa->pScreen, &intersection, region,
820 &intersection);
821 upload = &intersection;
822 }
823
824 if (REGION_NOTEMPTY(vsaa->pScreen, upload)) {
825 Bool ret = vmwgfx_upload_to_hw(&vsaa->driver, pixmap, upload);
826 if (ret) {
827 REGION_SUBTRACT(vsaa->pScreen, &spix->dirty_shadow,
828 &spix->dirty_shadow, upload);
829 if (vpix->dirty_present)
830 REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present,
831 vpix->dirty_present, upload);
832 } else {
833 REGION_UNINIT(vsaa->pScreen, &intersection);
834 return FALSE;
835 }
836 }
837 }
838 REGION_UNINIT(vsaa->pScreen, &intersection);
839 return TRUE;
840}
841
842static Bool
843vmwgfx_copy_prepare(struct saa_driver *driver,
844 PixmapPtr src_pixmap,
845 PixmapPtr dst_pixmap,
846 int dx,
847 int dy,
848 int alu,
849 RegionPtr src_reg,
850 uint32_t plane_mask)
851{
852 struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
853 struct vmwgfx_saa_pixmap *src_vpix;
854 struct vmwgfx_saa_pixmap *dst_vpix;
855 Bool has_dirty_hw;
856 Bool has_valid_hw;
857
858 if (!vsaa->xat || !SAA_PM_IS_SOLID(&dst_pixmap->drawable, plane_mask) ||
859 alu != GXcopy)
860 return FALSE;
861
862 src_vpix = vmwgfx_saa_pixmap(src_pixmap);
863 dst_vpix = vmwgfx_saa_pixmap(dst_pixmap);
864
865 vmwgfx_check_hw_contents(vsaa, src_vpix, src_reg,
866 &has_dirty_hw, &has_valid_hw);
867
868 if (vmwgfx_is_present_hw(dst_pixmap) &&
869 src_vpix->backing & VMWGFX_PIX_SURFACE) {
870
871 if (!has_dirty_hw && !has_valid_hw)
872 return FALSE;
873
874 if (!vmwgfx_hw_accel_validate(src_pixmap, 0, 0, 0, src_reg))
875 return FALSE;
876 if (vmwgfx_present_prepare(vsaa, src_vpix, dst_vpix)) {
877 vsaa->present_copy = TRUE;
878 return TRUE;
879 }
880 return FALSE;
881 }
882
883 vsaa->present_copy = FALSE;
884 if (src_vpix != dst_vpix) {
885
886 /*
887 * Use hardware acceleration either if source is partially only
888 * in hardware, or if source is entirely in hardware and destination
889 * has a hardware surface.
890 */
891
892 if (!has_dirty_hw && !(has_valid_hw && (dst_vpix->hw != NULL)))
893 return FALSE;
894
895 /*
896 * Determine surface formats.
897 */
898
899 if (src_vpix->base.src_format == 0) {
900 if (!vmwgfx_hw_accel_stage(src_pixmap, 0, XA_FLAG_RENDER_TARGET, 0))
901 return FALSE;
902 } else {
903 if (PICT_FORMAT_TYPE(src_vpix->base.src_format) != PICT_TYPE_ARGB ||
904 !vmwgfx_hw_composite_src_stage(src_pixmap, src_vpix->base.src_format))
905 return FALSE;
906 }
907
908 if (dst_vpix->base.dst_format == 0) {
909 if (!vmwgfx_hw_accel_stage(dst_pixmap, 0, XA_FLAG_RENDER_TARGET, 0))
910 return FALSE;
911 } else {
912 if (PICT_FORMAT_TYPE(dst_vpix->base.dst_format) != PICT_TYPE_ARGB ||
913 !vmwgfx_hw_composite_dst_stage(dst_pixmap, dst_vpix->base.dst_format))
914 return FALSE;
915 }
916
917 /*
918 * Create hardware surfaces.
919 */
920
921 if (!vmwgfx_hw_commit(src_pixmap))
922 return FALSE;
923 if (!vmwgfx_hw_commit(dst_pixmap))
924 return FALSE;
925
926 /*
927 * Migrate data.
928 */
929
930 if (!vmwgfx_hw_validate(src_pixmap, src_reg)) {
931 xa_copy_done(vsaa->xa_ctx);
932 return FALSE;
933 }
934
935 /*
936 * Setup copy state.
937 */
938
939 if (xa_copy_prepare(vsaa->xa_ctx, dst_vpix->hw, src_vpix->hw) !=
940 XA_ERR_NONE)
941 return FALSE;
942
943 return TRUE;
944 }
945
946 return FALSE;
947}
948
949
950static void
951vmwgfx_present_done(struct vmwgfx_saa *vsaa)
952{
953 ScreenPtr pScreen = vsaa->pScreen;
954 struct vmwgfx_saa_pixmap *dst_vpix = vsaa->dst_vpix;
955
956 (void) pScreen;
957 if (!vsaa->diff_valid)
958 return;
959
960 (void) vmwgfx_present(vsaa->drm_fd, dst_vpix->fb_id,
961 vsaa->xdiff, vsaa->ydiff,
962 &vsaa->present_region, vsaa->src_handle);
963
964 REGION_TRANSLATE(pScreen, &vsaa->present_region, vsaa->xdiff, vsaa->ydiff);
965 REGION_UNION(pScreen, dst_vpix->present_damage, dst_vpix->present_damage,
966 &vsaa->present_region);
967 vsaa->diff_valid = FALSE;
968 REGION_UNINIT(pScreen, &vsaa->present_region);
969}
970
971static void
972vmwgfx_present_copy(struct vmwgfx_saa *vsaa,
973 int src_x,
974 int src_y,
975 int dst_x,
976 int dst_y,
977 int w,
978 int h)
979{
980 int xdiff = dst_x - src_x;
981 int ydiff = dst_y - src_y;
982 BoxRec box;
983 RegionRec reg;
984
985 if (vsaa->diff_valid && ((xdiff != vsaa->xdiff) || (ydiff != vsaa->ydiff)))
986 (void) vmwgfx_present_done(vsaa);
987
988 if (!vsaa->diff_valid) {
989 vsaa->xdiff = xdiff;
990 vsaa->ydiff = ydiff;
991 vsaa->diff_valid = TRUE;
992 }
993
994 box.x1 = src_x;
995 box.x2 = src_x + w;
996 box.y1 = src_y;
997 box.y2 = src_y + h;
998
999 REGION_INIT(pScreen, &reg, &box, 1);
1000 REGION_UNION(pScreen, &vsaa->present_region, &vsaa->present_region, &reg);
1001 REGION_UNINIT(pScreen, &reg);
1002}
1003
1004static void
1005vmwgfx_copy(struct saa_driver *driver,
1006 int src_x,
1007 int src_y,
1008 int dst_x,
1009 int dst_y,
1010 int w,
1011 int h)
1012{
1013 struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
1014
1015 if (vsaa->present_copy) {
1016 vmwgfx_present_copy(vsaa, src_x, src_y, dst_x, dst_y, w, h);
1017 return;
1018 }
1019 xa_copy(vsaa->xa_ctx, dst_x, dst_y, src_x, src_y, w, h);
1020}
1021
1022static void
1023vmwgfx_copy_done(struct saa_driver *driver)
1024{
1025 struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
1026
1027 if (vsaa->present_copy) {
1028 vmwgfx_present_done(vsaa);
1029 return;
1030 }
1031 xa_copy_done(vsaa->xa_ctx);
1032}
1033
1034static Bool
1035vmwgfx_composite_prepare(struct saa_driver *driver, CARD8 op,
1036 PicturePtr src_pict, PicturePtr mask_pict,
1037 PicturePtr dst_pict,
1038 PixmapPtr src_pix, PixmapPtr mask_pix,
1039 PixmapPtr dst_pix,
1040 RegionPtr src_region,
1041 RegionPtr mask_region,
1042 RegionPtr dst_region)
1043{
1044 struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
1045 struct vmwgfx_saa_pixmap *src_vpix;
1046 struct vmwgfx_saa_pixmap *dst_vpix;
1047 struct vmwgfx_saa_pixmap *mask_vpix;
1048 Bool tmp_valid_hw;
1049 Bool dirty_hw;
1050 Bool valid_hw;
1051 RegionRec empty;
1052 struct xa_composite *xa_comp;
1053
1054 REGION_NULL(pScreen, &empty);
1055
1056 /*
1057 * First we define our migration policy. We accelerate only if there
1058 * are dirty hw regions to be read or if all source data is
1059 * available in hw, and the destination has a hardware surface.
1060 */
1061 dst_vpix = vmwgfx_saa_pixmap(dst_pix);
1062 valid_hw = (dst_vpix->hw != NULL);
1063 if (saa_op_reads_destination(op)) {
1064 vmwgfx_check_hw_contents(vsaa, dst_vpix, dst_region,
1065 &dirty_hw, &tmp_valid_hw);
1066 valid_hw = (valid_hw && tmp_valid_hw);
1067 } else {
1068 dirty_hw = FALSE;
1069 dst_region = &empty;
1070 }
1071
1072 if (src_pix && !dirty_hw) {
1073 src_vpix = vmwgfx_saa_pixmap(src_pix);
1074 vmwgfx_check_hw_contents(vsaa, src_vpix, src_region,
1075 &dirty_hw, &tmp_valid_hw);
1076 valid_hw = (valid_hw && tmp_valid_hw);
1077 }
1078
1079 if (mask_pict && mask_pix && !dirty_hw) {
1080 mask_vpix = vmwgfx_saa_pixmap(mask_pix);
1081 vmwgfx_check_hw_contents(vsaa, mask_vpix, mask_region,
1082 &dirty_hw, &tmp_valid_hw);
1083 valid_hw = (valid_hw && tmp_valid_hw);
1084 }
1085
1086 /*
1087 * In rendercheck mode we try to accelerate all supported
1088 * composite operations.
1089 */
1090
1091 if (!valid_hw && !dirty_hw && !vsaa->rendercheck)
1092 goto out_err;
1093
1094 /*
1095 * Then, setup most of the XA composite state (except hardware surfaces)
1096 * and check whether XA can accelerate.
1097 */
1098
1099 xa_comp = vmwgfx_xa_setup_comp(vsaa->vcomp, op,
1100 src_pict, mask_pict, dst_pict);
1101 if (!xa_comp)
1102 goto out_err;
1103
1104 if (xa_composite_check_accelerated(xa_comp) != XA_ERR_NONE)
1105 goto out_err;
1106
1107 /*
1108 * Check that we can create the needed hardware surfaces.
1109 */
1110 if (src_pix && !vmwgfx_hw_composite_src_stage(src_pix, src_pict->format))
1111 goto out_err;
1112 if (mask_pict && mask_pix &&
1113 !vmwgfx_hw_composite_src_stage(mask_pix, mask_pict->format))
1114 goto out_err;
1115 if (!vmwgfx_hw_composite_dst_stage(dst_pix, dst_pict->format))
1116 goto out_err;
1117
1118 /*
1119 * Seems OK. Commit the changes, creating hardware surfaces.
1120 */
1121 if (src_pix && !vmwgfx_hw_commit(src_pix))
1122 goto out_err;
1123 if (mask_pict && mask_pix && !vmwgfx_hw_commit(mask_pix))
1124 goto out_err;
1125 if (!vmwgfx_hw_commit(dst_pix))
1126 goto out_err;
1127
1128 /*
1129 * Update the XA state with our hardware surfaces and
1130 * surface formats
1131 */
1132 if (!vmwgfx_xa_update_comp(xa_comp, src_pix, mask_pix, dst_pix))
1133 goto out_err;
1134
1135 /*
1136 * Migrate data to surfaces.
1137 */
1138 if (src_pix && src_region && !vmwgfx_hw_validate(src_pix, NULL))
1139 goto out_err;
1140 if (mask_pict && mask_pix && mask_region &&
1141 !vmwgfx_hw_validate(mask_pix, NULL))
1142 goto out_err;
1143 if (dst_region && !vmwgfx_hw_validate(dst_pix, NULL))
1144 goto out_err;
1145
1146
1147 /*
1148 * Bind the XA state. This must be done after data migration, since
1149 * migration may change the hardware surfaces.
1150 */
1151 if (xa_composite_prepare(vsaa->xa_ctx, xa_comp))
1152 goto out_err;
1153
1154 REGION_UNINIT(pScreen, &empty);
1155 return TRUE;
1156
1157 out_err:
1158 REGION_UNINIT(pScreen, &empty);
1159 return FALSE;
1160}
1161
1162static void
1163vmwgfx_composite(struct saa_driver *driver,
1164 int src_x, int src_y, int mask_x, int mask_y,
1165 int dst_x, int dst_y,
1166 int width, int height)
1167{
1168 struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
1169
1170 xa_composite_rect(vsaa->xa_ctx, src_x, src_y, mask_x, mask_y,
1171 dst_x, dst_y, width, height);
1172}
1173
1174static void
1175vmwgfx_composite_done(struct saa_driver *driver)
1176{
1177 struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
1178
1179 xa_composite_done(vsaa->xa_ctx);
1180}
1181
1182static void
1183vmwgfx_takedown(struct saa_driver *driver)
1184{
1185 struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
1186
1187 if (vsaa->vcomp)
1188 vmwgfx_free_composite(vsaa->vcomp);
1189 free(vsaa);
1190}
1191
1192/*
1193 * This function call originates from the damage layer (outside SAA)
1194 * to indicate that an operation is complete, and that damage is being
1195 * processed.
1196 */
1197static void
1198vmwgfx_operation_complete(struct saa_driver *driver,
1199 PixmapPtr pixmap)
1200{
1201 struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
1202 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
1203 struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
1204 ScrnInfoPtr pScrn = xf86Screens[vsaa->pScreen->myNum];
1205
1206 /*
1207 * Make dri2 drawables up to date, or add them to the flush list
1208 * executed at glxWaitX(). Currently glxWaitX() is broken, so
1209 * we flush immediately, unless we're VT-switched away, in which
1210 * case a flush would deadlock in the kernel.
1211 */
1212
1213 if (vpix->hw && vpix->hw_is_dri2_fronts) {
1214 if (1 && pScrn->vtSema &&
1215 vmwgfx_upload_to_hw(driver, pixmap, &spix->dirty_shadow)) {
1216
1217 REGION_EMPTY(vsaa->pScreen, &spix->dirty_shadow);
1218 return;
1219 }
1220
1221 if (WSBMLISTEMPTY(&vpix->sync_x_head))
1222 WSBMLISTADDTAIL(&vpix->sync_x_head, &vsaa->sync_x_list);
1223 }
1224}
1225
1226/*
1227 * This function is called by SAA to indicate that SAA has
1228 * dirtied a region of a pixmap, either as hw (accelerated) or as
1229 * !hw (not accelerated).
1230 */
1231static Bool
1232vmwgfx_dirty(struct saa_driver *driver, PixmapPtr pixmap,
1233 Bool hw, RegionPtr damage)
1234{
1235 struct vmwgfx_saa *vsaa = to_vmwgfx_saa(driver);
1236 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
1237 struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
1238
1239 /*
1240 * Return if this is not a scanout pixmap.
1241 */
1242 if (WSBMLISTEMPTY(&vpix->scanout_list))
1243 return TRUE;
1244
1245#if 0
1246 /*
1247 * This code can be enabled to immediately upload scanout sw
1248 * contents to the hw surface. Otherwise this is done
1249 * just before we call the kms update function for the hw
1250 * surface.
1251 */
1252 if (vsaa->only_hw_presents) {
1253 if (!hw && !vmwgfx_upload_to_hw(&vsaa->driver, pixmap, damage))
1254 return FALSE;
1255
1256 REGION_SUBTRACT(&vsaa->pScreen, &spix->dirty_shadow,
1257 &spix->dirty_shadow, damage);
1258 hw = TRUE;
1259 }
1260#endif
1261
1262 /*
1263 * Is the new scanout damage hw or sw?
1264 */
1265 if (hw) {
1266 /*
1267 * Dump pending present into present tracking region.
1268 */
1269 if (vpix->dirty_present &&
1270 REGION_NOTEMPTY(vsaa->pScreen, vpix->present_damage)) {
1271 REGION_UNION(vsaa->pScreen, vpix->dirty_present,
1272 vpix->dirty_present, damage);
1273 REGION_EMPTY(vsaa->pScreen, vpix->present_damage);
1274 } else {
1275 if (REGION_NOTEMPTY(vsaa->pScreen, vpix->pending_update)) {
1276 RegionRec reg;
1277
1278 REGION_NULL(vsaa->pScreen, &reg);
1279 REGION_INTERSECT(vsaa->pScreen, &reg, vpix->pending_update,
1280 damage);
1281 if (REGION_NOTEMPTY(vsaa->pScreen, &reg))
1282 vsaa->present_flush(vsaa->pScreen);
1283 REGION_UNINIT(pScreen, &reg);
1284 }
1285 REGION_UNION(vsaa->pScreen, vpix->pending_present,
1286 vpix->pending_present, damage);
1287 if (vpix->dirty_present)
1288 REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present,
1289 vpix->dirty_present, damage);
1290 }
1291 } else {
1292 if (REGION_NOTEMPTY(vsaa->pScreen, vpix->pending_present)) {
1293 RegionRec reg;
1294
1295 REGION_NULL(vsaa->pScreen, &reg);
1296 REGION_INTERSECT(vsaa->pScreen, &reg, vpix->pending_present,
1297 damage);
1298 if (REGION_NOTEMPTY(vsaa->pScreen, &reg))
1299 vsaa->present_flush(vsaa->pScreen);
1300 REGION_UNINIT(pScreen, &reg);
1301 }
1302 REGION_UNION(vsaa->pScreen, vpix->pending_update,
1303 vpix->pending_update, damage);
1304 if (vpix->dirty_present)
1305 REGION_SUBTRACT(vsaa->pScreen, vpix->dirty_present,
1306 vpix->dirty_present, damage);
1307 }
1308
1309 return TRUE;
1310}
1311
1312
1313static const struct saa_driver vmwgfx_saa_driver = {
1314 .saa_major = SAA_VERSION_MAJOR,
1315 .saa_minor = SAA_VERSION_MINOR,
1316 .pixmap_size = sizeof(struct vmwgfx_saa_pixmap),
1317 .damage = vmwgfx_dirty,
1318 .operation_complete = vmwgfx_operation_complete,
1319 .download_from_hw = vmwgfx_download_from_hw,
1320 .release_from_cpu = vmwgfx_release_from_cpu,
1321 .sync_for_cpu = vmwgfx_sync_for_cpu,
1322 .map = vmwgfx_map,
1323 .unmap = vmwgfx_unmap,
1324 .create_pixmap = vmwgfx_create_pixmap,
1325 .destroy_pixmap = vmwgfx_destroy_pixmap,
1326 .modify_pixmap_header = vmwgfx_modify_pixmap_header,
1327 .copy_prepare = vmwgfx_copy_prepare,
1328 .copy = vmwgfx_copy,
1329 .copy_done = vmwgfx_copy_done,
1330 .composite_prepare = vmwgfx_composite_prepare,
1331 .composite = vmwgfx_composite,
1332 .composite_done = vmwgfx_composite_done,
1333 .takedown = vmwgfx_takedown,
1334};
1335
1336
1337Bool
1338vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
1339 void (*present_flush)(ScreenPtr pScreen),
1340 Bool direct_presents,
1341 Bool only_hw_presents,
1342 Bool rendercheck)
1343{
1344 struct vmwgfx_saa *vsaa;
1345
1346 vsaa = calloc(1, sizeof(*vsaa));
1347 if (!vsaa)
1348 return FALSE;
1349
1350 if (xat == NULL) {
1351 direct_presents = FALSE;
1352 only_hw_presents = FALSE;
1353 }
1354
1355 vsaa->pScreen = pScreen;
1356 vsaa->xat = xat;
1357 if (xat)
1358 vsaa->xa_ctx = xa_context_default(xat);
1359 vsaa->drm_fd = drm_fd;
1360 vsaa->present_flush = present_flush;
1361 vsaa->can_optimize_dma = FALSE;
1362 vsaa->use_present_opt = direct_presents;
1363 vsaa->only_hw_presents = only_hw_presents;
1364 vsaa->rendercheck = rendercheck;
1365 WSBMINITLISTHEAD(&vsaa->sync_x_list);
1366
1367 vsaa->driver = vmwgfx_saa_driver;
1368 vsaa->vcomp = vmwgfx_alloc_composite();
1369
1370 if (!vsaa->vcomp)
1371 vsaa->driver.composite_prepare = NULL;
1372
1373 if (!saa_driver_init(pScreen, &vsaa->driver))
1374 goto out_no_saa;
1375
1376 return TRUE;
1377 out_no_saa:
1378 free(vsaa);
1379 return FALSE;
1380}
1381
1382/*
1383 * *************************************************************************
1384 * Scanout functions.
1385 * These do not strictly belong here, but we choose to hide the scanout
1386 * pixmap private data in the saa pixmaps. Might want to revisit this.
1387 */
1388
1389/*
1390 * Make sure we flush / update this scanout on next update run.
1391 */
1392
1393void
1394vmwgfx_scanout_refresh(PixmapPtr pixmap)
1395{
1396 ScreenPtr pScreen = pixmap->drawable.pScreen;
1397 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
1398 BoxRec box;
1399
1400 (void) pScreen;
1401 box.x1 = 0;
1402 box.y1 = 0;
1403 box.x2 = pixmap->drawable.width;
1404 box.y2 = pixmap->drawable.height;
1405
1406 REGION_RESET(vsaa->pScreen, vpix->pending_present, &box);
1407 if (vpix->dirty_present)
1408 REGION_SUBTRACT(vsaa->pScreen, vpix->pending_present,
1409 vpix->pending_present, vpix->dirty_present);
1410 REGION_SUBTRACT(vsaa->pScreen, vpix->pending_present,
1411 vpix->pending_present, &vpix->base.dirty_shadow);
1412 REGION_COPY(vsaa->pScreen, vpix->pending_update,
1413 &vpix->base.dirty_shadow);
1414}
1415
1416/*
1417 * Take a "scanout reference" on a pixmap. If this is the first scanout
1418 * reference, allocate resources needed for scanout, like proper
1419 * damage tracking and kms fbs.
1420 */
1421
1422uint32_t
1423vmwgfx_scanout_ref(struct vmwgfx_screen_entry *entry)
1424{
1425 PixmapPtr pixmap = entry->pixmap;
1426 struct vmwgfx_saa *vsaa =
1427 to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
1428 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
1429
1430 if (WSBMLISTEMPTY(&vpix->scanout_list)) {
1431 uint32_t handle, dummy;
1432 unsigned int depth;
1433
1434 if (vsaa->only_hw_presents) {
1435 /*
1436 * The KMS fb will be a HW surface. Create it, add damage
1437 * and get the handle.
1438 */
1439 if (!vmwgfx_hw_accel_validate(pixmap, 0, XA_FLAG_SCANOUT, 0, NULL))
1440 goto out_err;
1441 if (xa_surface_handle(vpix->hw, &handle, &dummy) != 0)
1442 goto out_err;
1443 depth = xa_format_depth(xa_surface_format(vpix->hw));
1444
1445 } else {
1446 /*
1447 * The KMS fb will be a Guest Memory Region. Create it,
1448 * add damage and get the handle.
1449 */
1450 if (!vmwgfx_pixmap_create_gmr(vsaa, pixmap))
1451 goto out_err;
1452
1453 handle = vpix->gmr->handle;
1454 depth = pixmap->drawable.depth;
1455
1456 }
1457
1458 if (!vmwgfx_pixmap_add_present(pixmap, vsaa->use_present_opt))
1459 goto out_no_present;
1460
1461 if (drmModeAddFB(vsaa->drm_fd,
1462 pixmap->drawable.width,
1463 pixmap->drawable.height,
1464 depth,
1465 pixmap->drawable.bitsPerPixel,
1466 pixmap->devKind,
1467 handle,
1468 &vpix->fb_id) != 0)
1469 goto out_no_fb;;
1470 }
1471 pixmap->refcnt += 1;
1472 WSBMLISTADDTAIL(&entry->scanout_head, &vpix->scanout_list);
1473 return vpix->fb_id;
1474
1475 out_no_fb:
1476 vmwgfx_pixmap_remove_present(vpix);
1477 out_no_present:
1478 vmwgfx_pixmap_remove_damage(pixmap);
1479 out_err:
1480 vpix->fb_id = -1;
1481 return -1;
1482}
1483
1484/*
1485 * Free a "scanout reference" on a pixmap. If this was the last scanout
1486 * reference, free pixmap resources needed for scanout, like
1487 * damage tracking and kms fbs.
1488 */
1489void
1490vmwgfx_scanout_unref(struct vmwgfx_screen_entry *entry)
1491{
1492 struct vmwgfx_saa *vsaa;
1493 struct vmwgfx_saa_pixmap *vpix;
1494 PixmapPtr pixmap = entry->pixmap;
1495
1496 if (!pixmap)
1497 return;
1498
1499 vsaa = to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
1500 vpix = vmwgfx_saa_pixmap(pixmap);
1501 WSBMLISTDELINIT(&entry->scanout_head);
1502
1503 if (WSBMLISTEMPTY(&vpix->scanout_list)) {
1504 REGION_EMPTY(vsaa->pScreen, vpix->pending_update);
1505 drmModeRmFB(vsaa->drm_fd, vpix->fb_id);
1506 vpix->fb_id = -1;
1507 vmwgfx_pixmap_present_readback(vsaa, pixmap, NULL);
1508 vmwgfx_pixmap_remove_present(vpix);
1509 vmwgfx_pixmap_remove_damage(pixmap);
1510 }
1511
1512 entry->pixmap = NULL;
1513 pixmap->drawable.pScreen->DestroyPixmap(pixmap);
1514}
diff --git a/vmwgfx/vmwgfx_saa.h b/vmwgfx/vmwgfx_saa.h
new file mode 100644
index 0000000..bb8ec96
--- /dev/null
+++ b/vmwgfx/vmwgfx_saa.h
@@ -0,0 +1,110 @@
1/*
2 * Copyright 2011 VMWare, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Thomas Hellstrom <thellstrom@vmware.com>
26 */
27
28#ifndef _VMWGFX_SAA_H_
29#define _VMWGFX_SAA_H_
30
31#include "saa.h"
32#include <xa_composite.h>
33#include "vmwgfx_drmi.h"
34#include "wsbm_util.h"
35
36
37#define VMWGFX_FLAG_FORCE_GMR (1 << 0) /* Create with GMR as backing store */
38#define VMWGFX_FLAG_FORCE_SURFACE (1 << 1) /* Create with surface as backing store */
39#define VMWGFX_FLAG_AVOID_HWACCEL (1 << 2) /* Avoid Hardware acceleration on this pixmap */
40#define VMWGFX_FLAG_USE_PRESENT (1 << 3) /* Use presents when copying to this pixmap */
41
42struct vmwgfx_saa_pixmap {
43 struct saa_pixmap base;
44 RegionPtr dirty_present;
45 RegionPtr present_damage;
46 RegionPtr pending_update;
47 RegionPtr pending_present;
48 uint32_t usage_flags;
49 uint32_t backing;
50 void *malloc;
51 struct vmwgfx_dmabuf *gmr;
52 struct xa_surface *hw;
53 uint32_t fb_id;
54 int hw_is_dri2_fronts;
55 struct _WsbmListHead sync_x_head;
56 struct _WsbmListHead scanout_list;
57
58 uint32_t xa_flags;
59 uint32_t staging_add_flags;
60 uint32_t staging_remove_flags;
61 enum xa_formats staging_format;
62};
63
64struct vmwgfx_screen_entry {
65 struct _WsbmListHead scanout_head;
66 PixmapPtr pixmap;
67};
68
69static inline struct vmwgfx_saa_pixmap *
70to_vmwgfx_saa_pixmap(struct saa_pixmap *spix)
71{
72 return (struct vmwgfx_saa_pixmap *) spix;
73}
74
75static inline struct vmwgfx_saa_pixmap*
76vmwgfx_saa_pixmap(PixmapPtr pix)
77{
78 return to_vmwgfx_saa_pixmap(saa_get_saa_pixmap(pix));
79}
80
81extern Bool
82vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
83 void (*present_flush)(ScreenPtr pScreen),
84 Bool direct_presents,
85 Bool only_hw_presents,
86 Bool rendercheck);
87
88extern uint32_t
89vmwgfx_scanout_ref(struct vmwgfx_screen_entry *box);
90
91extern void
92vmwgfx_scanout_unref(struct vmwgfx_screen_entry *box);
93
94extern void
95vmwgfx_scanout_refresh(PixmapPtr pixmap);
96
97extern void
98vmwgfx_remove_dri2_list(struct vmwgfx_saa_pixmap *vpix);
99
100extern void
101vmwgfx_flush_dri2(ScreenPtr pScreen);
102
103extern Bool
104vmwgfx_hw_dri2_validate(PixmapPtr pixmap, unsigned int depth);
105
106Bool
107vmwgfx_hw_accel_validate(PixmapPtr pixmap, unsigned int depth,
108 uint32_t add_flags, uint32_t remove_flags,
109 RegionPtr region);
110#endif
diff --git a/vmwgfx/vmwgfx_saa_priv.h b/vmwgfx/vmwgfx_saa_priv.h
new file mode 100644
index 0000000..5f46dee
--- /dev/null
+++ b/vmwgfx/vmwgfx_saa_priv.h
@@ -0,0 +1,125 @@
1/*
2 * Copyright 2011 VMWare, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Thomas Hellstrom <thellstrom@vmware.com>
26 */
27#ifndef _VMWGFX_SAA_PRIV_H_
28#define _VMWGFX_SAA_PRIV_H_
29
30#define VMWGFX_PIX_MALLOC (1 << 0)
31#define VMWGFX_PIX_GMR (1 << 1)
32#define VMWGFX_PIX_SURFACE (1 << 2)
33
34#include <xorg-server.h>
35#include <picturestr.h>
36#include "vmwgfx_saa.h"
37
38struct vmwgfx_saa {
39 struct saa_driver driver;
40 struct vmwgfx_dma_ctx *ctx;
41 struct xa_tracker *xat;
42 struct xa_context *xa_ctx;
43 ScreenPtr pScreen;
44 int drm_fd;
45 struct vmwgfx_saa_pixmap *src_vpix;
46 struct vmwgfx_saa_pixmap *dst_vpix;
47 Bool present_copy;
48 Bool diff_valid;
49 int xdiff;
50 int ydiff;
51 RegionRec present_region;
52 uint32_t src_handle;
53 Bool can_optimize_dma;
54 Bool use_present_opt;
55 Bool only_hw_presents;
56 Bool rendercheck;
57 void (*present_flush) (ScreenPtr pScreen);
58 struct _WsbmListHead sync_x_list;
59 struct vmwgfx_composite *vcomp;
60};
61
62static inline struct vmwgfx_saa *
63to_vmwgfx_saa(struct saa_driver *driver) {
64 return (struct vmwgfx_saa *) driver;
65}
66
67/*
68 * In vmwgfx_saa.c
69 */
70
71Bool
72vmwgfx_hw_kill(struct vmwgfx_saa *vsaa,
73 struct saa_pixmap *spix);
74Bool
75vmwgfx_create_hw(struct vmwgfx_saa *vsaa,
76 PixmapPtr pixmap);
77
78
79/*
80 * vmwgfx_xa_surface.c
81 */
82
83enum xa_formats
84vmwgfx_xa_format(enum _PictFormatShort format);
85Bool
86vmwgfx_hw_validate(PixmapPtr pixmap, RegionPtr region);
87
88Bool
89vmwgfx_hw_accel_stage(PixmapPtr pixmap, unsigned int depth,
90 uint32_t add_flags, uint32_t remove_flags);
91Bool
92vmwgfx_hw_composite_src_stage(PixmapPtr pixmap,
93 enum _PictFormatShort pict_format);
94Bool
95vmwgfx_hw_composite_dst_stage(PixmapPtr pixmap,
96 enum _PictFormatShort pict_format);
97Bool
98vmwgfx_hw_commit(PixmapPtr pixmap);
99
100/*
101 * vmwgfx_xa_composite.c
102 */
103
104struct vmwgfx_composite;
105
106void
107vmwgfx_free_composite(struct vmwgfx_composite *vcomp);
108struct vmwgfx_composite *
109vmwgfx_alloc_composite(void);
110
111Bool
112vmwgfx_xa_update_comp(struct xa_composite *comp,
113 PixmapPtr src_pix,
114 PixmapPtr mask_pix,
115 PixmapPtr dst_pix);
116
117struct xa_composite *
118vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp,
119 int op,
120 PicturePtr src_pict,
121 PicturePtr mask_pict,
122 PicturePtr dst_pict);
123
124
125#endif
diff --git a/vmwgfx/vmwgfx_tex_video.c b/vmwgfx/vmwgfx_tex_video.c
new file mode 100644
index 0000000..cc94c20
--- /dev/null
+++ b/vmwgfx/vmwgfx_tex_video.c
@@ -0,0 +1,855 @@
1/*
2 * Copyright 2009-2011 VMWare, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Thomas Hellstrom <thellstrom@vmware.com>
26 * Author: Zack Rusin <zackr@vmware.com>
27 */
28
29#include "vmwgfx_driver.h"
30#include "vmwgfx_drmi.h"
31#include "vmwgfx_saa.h"
32
33#include <xf86xv.h>
34#include <X11/extensions/Xv.h>
35#include <fourcc.h>
36#include <xa_tracker.h>
37#include <xa_context.h>
38#include <math.h>
39
40/*XXX get these from pipe's texture limits */
41#define IMAGE_MAX_WIDTH 2048
42#define IMAGE_MAX_HEIGHT 2048
43
44#define RES_720P_X 1280
45#define RES_720P_Y 720
46
47
48#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
49
50/*
51 * ITU-R BT.601, BT.709 transfer matrices.
52 * [R', G', B'] values are in the range [0, 1], Y' is in the range [0,1]
53 * and [Pb, Pr] components are in the range [-0.5, 0.5].
54 *
55 * The matrices are transposed to fit the xa conversion matrix format.
56 */
57
58static const float bt_601[] = {
59 1.f, 1.f, 1.f, 0.f,
60 0.f, -0.344136f, 1.772f, 0.f,
61 1.402f, -0.714136f, 0.f, 0.f
62};
63
64static const float bt_709[] = {
65 1.f, 1.f, 1.f, 0.f,
66 0.f, -0.187324f, 1.8556f, 0.f,
67 1.5748f, -0.468124f, 0.f, 0.f
68};
69
70static Atom xvBrightness, xvContrast, xvSaturation, xvHue;
71
72#define NUM_TEXTURED_ATTRIBUTES 4
73static XF86AttributeRec TexturedAttributes[NUM_TEXTURED_ATTRIBUTES] = {
74 {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
75 {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
76 {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
77 {XvSettable | XvGettable, -1000, 1000, "XV_HUE"}
78};
79
80#define NUM_FORMATS 3
81static XF86VideoFormatRec Formats[NUM_FORMATS] = {
82 {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
83};
84
85static XF86VideoEncodingRec DummyEncoding[1] = {
86 {
87 0,
88 "XV_IMAGE",
89 IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
90 {1, 1}
91 }
92};
93
94#define NUM_IMAGES 3
95static XF86ImageRec Images[NUM_IMAGES] = {
96 XVIMAGE_UYVY,
97 XVIMAGE_YUY2,
98 XVIMAGE_YV12,
99};
100
101struct xorg_xv_port_priv {
102 struct xa_tracker *xat;
103 struct xa_context *r;
104 struct xa_fence *fence;
105
106 RegionRec clip;
107
108 int brightness;
109 int contrast;
110 int saturation;
111 int hue;
112
113 int current_set;
114 struct vmwgfx_dmabuf *bounce[2][3];
115 struct xa_surface *yuv[3];
116
117 int drm_fd;
118
119 Bool hdtv;
120 float uv_offset;
121 float uv_scale;
122 float y_offset;
123 float y_scale;
124 float rgb_offset;
125 float rgb_scale;
126 float sinhue;
127 float coshue;
128 float cm[16];
129};
130
131/*
132 * vmwgfx_update_conversion_matrix - Compute the effective color conversion
133 * matrix.
134 *
135 * Applies yuv- and resulting rgb scales and offsets to compute the correct
136 * color conversion matrix. These scales and offsets are properties of the
137 * video stream and can be adjusted using XV properties as well.
138 */
139static void
140vmwgfx_update_conversion_matrix(struct xorg_xv_port_priv *priv)
141{
142 int i;
143 float *cm = priv->cm;
144 static const float *bt;
145
146 bt = (priv->hdtv) ? bt_709 : bt_601;
147
148 memcpy(cm, bt, sizeof(bt_601));
149
150 /*
151 * Apply hue rotation
152 */
153 cm[4] = priv->coshue * bt[4] - priv->sinhue * bt[8];
154 cm[8] = priv->sinhue * bt[4] + priv->coshue * bt[8];
155 cm[5] = priv->coshue * bt[5] - priv->sinhue * bt[9];
156 cm[9] = priv->sinhue * bt[5] + priv->coshue * bt[9];
157 cm[6] = priv->coshue * bt[6] - priv->sinhue * bt[10];
158 cm[10] = priv->sinhue * bt[6] + priv->coshue * bt[10];
159
160 /*
161 * Adjust for yuv scales in input and rgb scale in the converted output.
162 */
163 for(i = 0; i < 3; ++i) {
164 cm[i] *= (priv->y_scale*priv->rgb_scale);
165 cm[i+4] *= (priv->uv_scale*priv->rgb_scale);
166 cm[i+8] *= (priv->uv_scale*priv->rgb_scale);
167 }
168
169 /*
170 * Adjust for yuv offsets in input and rgb offset in the converted output.
171 */
172 for (i = 0; i < 3; ++i)
173 cm[i+12] = -cm[i]*priv->y_offset - (cm[i+4] + cm[i+8])*priv->uv_offset
174 - priv->rgb_offset*priv->rgb_scale;
175
176 /*
177 * Alpha is 1, unconditionally.
178 */
179 cm[15] = 1.f;
180}
181
182
183static void
184stop_video(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
185{
186 struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
187 int i, j;
188
189 REGION_EMPTY(pScrn->pScreen, &priv->clip);
190 if (shutdown) {
191
192 /*
193 * No need to destroy the xa context or xa tracker since
194 * they are copied from the screen resources.
195 */
196
197 xa_fence_destroy(priv->fence);
198 priv->fence = NULL;
199
200 for (i=0; i<3; ++i) {
201 if (priv->yuv[i]) {
202 xa_surface_destroy(priv->yuv[i]);
203 priv->yuv[i] = NULL;
204 }
205 for (j=0; j<2; ++j) {
206 if (priv->bounce[j][i]) {
207 vmwgfx_dmabuf_destroy(priv->bounce[j][i]);
208 priv->bounce[0][i] = NULL;
209 }
210 }
211 }
212 }
213}
214
215static int
216set_port_attribute(ScrnInfoPtr pScrn,
217 Atom attribute, INT32 value, pointer data)
218{
219 struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
220
221 if (attribute == xvBrightness) {
222 if ((value < -1000) || (value > 1000))
223 return BadValue;
224
225 priv->brightness = value;
226 priv->y_offset = -((float) value)/1000.f;
227
228 } else if (attribute == xvContrast) {
229 if ((value < -1000) || (value > 1000))
230 return BadValue;
231
232 priv->contrast = value;
233 priv->rgb_scale = ((float) value + 1000.f)/1000.f;
234
235 } else if (attribute == xvSaturation) {
236 if ((value < -1000) || (value > 1000))
237 return BadValue;
238
239 priv->saturation = value;
240 priv->uv_scale = ((float) value + 1000.f)/1000.f;
241
242 } else if (attribute == xvHue) {
243 double hue_angle;
244
245 if ((value < -1000) || (value > 1000))
246 return BadValue;
247
248 priv->hue = value;
249 hue_angle = (double) value * M_PI / 1000.;
250 priv->sinhue = sin(hue_angle);
251 priv->coshue = cos(hue_angle);
252
253 } else
254 return BadMatch;
255
256 vmwgfx_update_conversion_matrix(priv);
257 return Success;
258}
259
260static int
261get_port_attribute(ScrnInfoPtr pScrn,
262 Atom attribute, INT32 * value, pointer data)
263{
264 struct xorg_xv_port_priv *priv = (struct xorg_xv_port_priv *)data;
265
266 if (attribute == xvBrightness)
267 *value = priv->brightness;
268 else if (attribute == xvContrast)
269 *value = priv->contrast;
270 else if (attribute == xvSaturation)
271 *value = priv->saturation;
272 else if (attribute == xvHue)
273 *value = priv->hue;
274 else
275 return BadMatch;
276
277 return Success;
278}
279
280static void
281query_best_size(ScrnInfoPtr pScrn,
282 Bool motion,
283 short vid_w, short vid_h,
284 short drw_w, short drw_h,
285 unsigned int *p_w, unsigned int *p_h, pointer data)
286{
287 if (vid_w > (drw_w << 1))
288 drw_w = vid_w >> 1;
289 if (vid_h > (drw_h << 1))
290 drw_h = vid_h >> 1;
291
292 *p_w = drw_w;
293 *p_h = drw_h;
294}
295
296static int
297check_yuv_surfaces(struct xorg_xv_port_priv *priv, int id,
298 int width, int height)
299{
300 struct xa_surface **yuv = priv->yuv;
301 struct vmwgfx_dmabuf **bounce = priv->bounce[priv->current_set];
302 int ret = 0;
303 int i;
304 size_t size;
305
306 for (i=0; i<3; ++i) {
307
308 /*
309 * Adjust u,v texture size and DMA buffer to what's required by
310 * the format.
311 */
312 if (i == 1) {
313 switch(id) {
314 case FOURCC_YV12:
315 height /= 2;
316 /* Fall through */
317 case FOURCC_YUY2:
318 case FOURCC_UYVY:
319 width /= 2;
320 break;
321 default:
322 break;
323 }
324 }
325
326 if (!yuv[i])
327 yuv[i] = xa_surface_create(priv->xat, width, height, 8,
328 xa_type_yuv_component,
329 xa_format_unknown, 0);
330 else
331 ret = xa_surface_redefine(yuv[i], width, height, 8,
332 xa_type_yuv_component,
333 xa_format_unknown, 0, 0);
334 if (ret || !yuv[i])
335 return BadAlloc;
336
337 size = width * height;
338
339 if (bounce[i] && (bounce[i]->size < size ||
340 bounce[i]->size > 2*size)) {
341 vmwgfx_dmabuf_destroy(bounce[i]);
342 bounce[i] = NULL;
343 }
344
345 if (!bounce[i]) {
346 bounce[i] = vmwgfx_dmabuf_alloc(priv->drm_fd, size);
347 if (!bounce[i])
348 return BadAlloc;
349 }
350 }
351 return Success;
352}
353
354static int
355query_image_attributes(ScrnInfoPtr pScrn,
356 int id,
357 unsigned short *w, unsigned short *h,
358 int *pitches, int *offsets)
359{
360 int size, tmp;
361
362 if (*w > IMAGE_MAX_WIDTH)
363 *w = IMAGE_MAX_WIDTH;
364 if (*h > IMAGE_MAX_HEIGHT)
365 *h = IMAGE_MAX_HEIGHT;
366
367 *w = (*w + 1) & ~1;
368 if (offsets)
369 offsets[0] = 0;
370
371 switch (id) {
372 case FOURCC_YV12:
373 *h = (*h + 1) & ~1;
374 size = (*w + 3) & ~3;
375 if (pitches) {
376 pitches[0] = size;
377 }
378 size *= *h;
379 if (offsets) {
380 offsets[1] = size;
381 }
382 tmp = ((*w >> 1) + 3) & ~3;
383 if (pitches) {
384 pitches[1] = pitches[2] = tmp;
385 }
386 tmp *= (*h >> 1);
387 size += tmp;
388 if (offsets) {
389 offsets[2] = size;
390 }
391 size += tmp;
392 break;
393 case FOURCC_UYVY:
394 case FOURCC_YUY2:
395 default:
396 size = *w << 1;
397 if (pitches)
398 pitches[0] = size;
399 size *= *h;
400 break;
401 }
402
403 return size;
404}
405
406static int
407copy_packed_data(ScrnInfoPtr pScrn,
408 struct xorg_xv_port_priv *port,
409 int id,
410 unsigned char *buf,
411 int left,
412 int top,
413 unsigned short w, unsigned short h)
414{
415 int i;
416 struct vmwgfx_dmabuf **bounce = port->bounce[port->current_set];
417 char *ymap, *vmap, *umap;
418 unsigned char y1, y2, u, v;
419 int yidx, uidx, vidx;
420 int y_array_size = w * h;
421 int ret = BadAlloc;
422
423 /*
424 * Here, we could use xa_surface_[map|unmap], but given the size of
425 * the yuv textures, that could stress the xa tracker dma buffer pool,
426 * particularaly with multiple videos rendering simultaneously.
427 *
428 * Instead, cheat and allocate vmwgfx dma buffers directly.
429 */
430
431 ymap = (char *)vmwgfx_dmabuf_map(bounce[0]);
432 if (!ymap)
433 return BadAlloc;
434 umap = (char *)vmwgfx_dmabuf_map(bounce[1]);
435 if (!umap)
436 goto out_no_umap;
437 vmap = (char *)vmwgfx_dmabuf_map(bounce[2]);
438 if (!vmap)
439 goto out_no_vmap;
440
441
442 yidx = uidx = vidx = 0;
443
444 switch (id) {
445 case FOURCC_YV12: {
446 int pitches[3], offsets[3];
447 unsigned char *y, *u, *v;
448 query_image_attributes(pScrn, FOURCC_YV12,
449 &w, &h, pitches, offsets);
450
451 y = buf + offsets[0];
452 v = buf + offsets[1];
453 u = buf + offsets[2];
454 memcpy(ymap, y, w*h);
455 memcpy(vmap, v, w*h/4);
456 memcpy(umap, u, w*h/4);
457 break;
458 }
459 case FOURCC_UYVY:
460 for (i = 0; i < y_array_size; i +=2 ) {
461 /* extracting two pixels */
462 u = buf[0];
463 y1 = buf[1];
464 v = buf[2];
465 y2 = buf[3];
466 buf += 4;
467
468 ymap[yidx++] = y1;
469 ymap[yidx++] = y2;
470 umap[uidx++] = u;
471 vmap[vidx++] = v;
472 }
473 break;
474 case FOURCC_YUY2:
475 for (i = 0; i < y_array_size; i +=2 ) {
476 /* extracting two pixels */
477 y1 = buf[0];
478 u = buf[1];
479 y2 = buf[2];
480 v = buf[3];
481
482 buf += 4;
483
484 ymap[yidx++] = y1;
485 ymap[yidx++] = y2;
486 umap[uidx++] = u;
487 vmap[vidx++] = v;
488 }
489 break;
490 default:
491 ret = BadAlloc;
492 break;
493 }
494
495 ret = Success;
496 vmwgfx_dmabuf_unmap(bounce[2]);
497 out_no_vmap:
498 vmwgfx_dmabuf_unmap(bounce[1]);
499 out_no_umap:
500 vmwgfx_dmabuf_unmap(bounce[0]);
501
502 if (ret == Success) {
503 struct xa_surface *srf;
504 struct vmwgfx_dmabuf *buf;
505 uint32_t handle;
506 unsigned int stride;
507 BoxRec box;
508 RegionRec reg;
509
510 box.x1 = 0;
511 box.x2 = w;
512 box.y1 = 0;
513 box.y2 = h;
514
515 REGION_INIT(pScrn->pScreen, &reg, &box, 1);
516
517 for (i=0; i<3; ++i) {
518 srf = port->yuv[i];
519 buf = bounce[i];
520
521 if (i == 1) {
522 switch(id) {
523 case FOURCC_YV12:
524 h /= 2;
525 /* Fall through */
526 case FOURCC_YUY2:
527 case FOURCC_UYVY:
528 w /= 2;
529 break;
530 default:
531 break;
532 }
533
534 box.x1 = 0;
535 box.x2 = w;
536 box.y1 = 0;
537 box.y2 = h;
538
539 REGION_RESET(pScrn->pScreen, &reg, &box);
540 }
541
542 if (xa_surface_handle(srf, &handle, &stride) != 0) {
543 ret = BadAlloc;
544 break;
545 }
546
547 if (vmwgfx_dma(0, 0, &reg, buf, w, handle, 1) != 0) {
548 ret = BadAlloc;
549 break;
550 }
551 }
552 REGION_UNINIT(pScrn->pScreen, &reg);
553 }
554
555 return ret;
556}
557
558
559static int
560display_video(ScreenPtr pScreen, struct xorg_xv_port_priv *pPriv, int id,
561 RegionPtr dstRegion,
562 int src_x, int src_y, int src_w, int src_h,
563 int dst_x, int dst_y, int dst_w, int dst_h,
564 PixmapPtr pPixmap)
565{
566 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pPixmap);
567 Bool hdtv;
568 RegionRec reg;
569 int ret = BadAlloc;
570 int blit_ret;
571
572 REGION_NULL(pScreen, &reg);
573
574 if (!vmwgfx_hw_accel_validate(pPixmap, 0, XA_FLAG_RENDER_TARGET, 0, &reg))
575 goto out_no_dst;
576
577 hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y));
578 if (hdtv != pPriv->hdtv) {
579 pPriv->hdtv = hdtv;
580 vmwgfx_update_conversion_matrix(pPriv);
581 }
582
583#ifdef COMPOSITE
584
585 /*
586 * For redirected windows, we need to fix up the destination coordinates.
587 */
588
589 REGION_TRANSLATE(pScreen, dstRegion, -pPixmap->screen_x,
590 -pPixmap->screen_y);
591 dst_x -= pPixmap->screen_x;
592 dst_y -= pPixmap->screen_y;
593#endif
594
595 /*
596 * Throttle on previous blit.
597 */
598
599 if (pPriv->fence) {
600 (void) xa_fence_wait(pPriv->fence, 1000000000ULL);
601 xa_fence_destroy(pPriv->fence);
602 pPriv->fence = NULL;
603 }
604
605 DamageRegionAppend(&pPixmap->drawable, dstRegion);
606
607 blit_ret = xa_yuv_planar_blit(pPriv->r, src_x, src_y, src_w, src_h,
608 dst_x, dst_y, dst_w, dst_h,
609 (struct xa_box *)REGION_RECTS(dstRegion),
610 REGION_NUM_RECTS(dstRegion),
611 pPriv->cm,
612 vpix->hw, pPriv->yuv);
613
614 saa_pixmap_dirty(pPixmap, TRUE, dstRegion);
615 DamageRegionProcessPending(&pPixmap->drawable);
616 ret = Success;
617
618 if (!blit_ret) {
619 ret = Success;
620 pPriv->fence = xa_fence_get(pPriv->r);
621 } else
622 ret = BadAlloc;
623
624 out_no_dst:
625 REGION_UNINIT(pScreen, &reg);
626 return ret;
627}
628
629static int
630put_image(ScrnInfoPtr pScrn,
631 short src_x, short src_y,
632 short drw_x, short drw_y,
633 short src_w, short src_h,
634 short drw_w, short drw_h,
635 int id, unsigned char *buf,
636 short width, short height,
637 Bool sync, RegionPtr clipBoxes, pointer data,
638 DrawablePtr pDraw)
639{
640 struct xorg_xv_port_priv *pPriv = (struct xorg_xv_port_priv *) data;
641 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
642 PixmapPtr pPixmap;
643 INT32 x1, x2, y1, y2;
644 BoxRec dstBox;
645 int ret;
646
647 /* Clip */
648 x1 = src_x;
649 x2 = src_x + src_w;
650 y1 = src_y;
651 y2 = src_y + src_h;
652
653 dstBox.x1 = drw_x;
654 dstBox.x2 = drw_x + drw_w;
655 dstBox.y1 = drw_y;
656 dstBox.y2 = drw_y + drw_h;
657
658 if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
659 width, height))
660 return Success;
661
662 ret = check_yuv_surfaces(pPriv, id, width, height);
663 if (ret)
664 return ret;
665
666 ret = copy_packed_data(pScrn, pPriv, id, buf,
667 src_x, src_y, width, height);
668 if (ret)
669 return ret;
670
671 if (pDraw->type == DRAWABLE_WINDOW) {
672 pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
673 } else {
674 pPixmap = (PixmapPtr)pDraw;
675 }
676
677 display_video(pScrn->pScreen, pPriv, id, clipBoxes,
678 src_x, src_y, src_w, src_h,
679 drw_x, drw_y,
680 drw_w, drw_h, pPixmap);
681
682 pPriv->current_set = (pPriv->current_set + 1) & 1;
683 return Success;
684}
685
686static struct xorg_xv_port_priv *
687port_priv_create(struct xa_tracker *xat, struct xa_context *r,
688 int drm_fd)
689{
690 struct xorg_xv_port_priv *priv = NULL;
691
692 priv = calloc(1, sizeof(struct xorg_xv_port_priv));
693
694 if (!priv)
695 return NULL;
696
697 priv->r = r;
698 priv->xat = xat;
699 priv->drm_fd = drm_fd;
700 REGION_NULL(pScreen, &priv->clip);
701 priv->hdtv = FALSE;
702 priv->uv_offset = 0.5f;
703 priv->uv_scale = 1.f;
704 priv->y_offset = 0.f;
705 priv->y_scale = 1.f;
706 priv->rgb_offset = 0.f;
707 priv->rgb_scale = 1.f;
708 priv->sinhue = 0.f;
709 priv->coshue = 1.f;
710
711 vmwgfx_update_conversion_matrix(priv);
712
713 return priv;
714}
715
716static void
717vmwgfx_free_textured_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports)
718{
719 if (free_ports) {
720 int i;
721
722 for(i=0; i<adaptor->nPorts; ++i) {
723 free(adaptor->pPortPrivates[i].ptr);
724 }
725 }
726
727 free(adaptor->pAttributes);
728 free(adaptor->pPortPrivates);
729 xf86XVFreeVideoAdaptorRec(adaptor);
730}
731
732static XF86VideoAdaptorPtr
733xorg_setup_textured_adapter(ScreenPtr pScreen)
734{
735 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
736 modesettingPtr ms = modesettingPTR(pScrn);
737 XF86VideoAdaptorPtr adapt;
738 XF86AttributePtr attrs;
739 DevUnion *dev_unions;
740 int nports = 16, i;
741 int nattributes;
742 struct xa_context *xar;
743
744 /*
745 * Use the XA default context since we don't expect the X server
746 * to render from multiple threads.
747 */
748
749 xar = xa_context_default(ms->xat);
750 nattributes = NUM_TEXTURED_ATTRIBUTES;
751
752 adapt = calloc(1, sizeof(XF86VideoAdaptorRec));
753 dev_unions = calloc(nports, sizeof(DevUnion));
754 attrs = calloc(nattributes, sizeof(XF86AttributeRec));
755 if (adapt == NULL || dev_unions == NULL || attrs == NULL) {
756 free(adapt);
757 free(dev_unions);
758 free(attrs);
759 return NULL;
760 }
761
762 adapt->type = XvWindowMask | XvInputMask | XvImageMask;
763 adapt->flags = 0;
764 adapt->name = "XA G3D Textured Video";
765 adapt->nEncodings = 1;
766 adapt->pEncodings = DummyEncoding;
767 adapt->nFormats = NUM_FORMATS;
768 adapt->pFormats = Formats;
769 adapt->nPorts = 0;
770 adapt->pPortPrivates = dev_unions;
771 adapt->nAttributes = nattributes;
772 adapt->pAttributes = attrs;
773 memcpy(attrs, TexturedAttributes, nattributes * sizeof(XF86AttributeRec));
774 adapt->nImages = NUM_IMAGES;
775 adapt->pImages = Images;
776 adapt->PutVideo = NULL;
777 adapt->PutStill = NULL;
778 adapt->GetVideo = NULL;
779 adapt->GetStill = NULL;
780 adapt->StopVideo = stop_video;
781 adapt->SetPortAttribute = set_port_attribute;
782 adapt->GetPortAttribute = get_port_attribute;
783 adapt->QueryBestSize = query_best_size;
784 adapt->PutImage = put_image;
785 adapt->QueryImageAttributes = query_image_attributes;
786
787
788 for (i = 0; i < nports; i++) {
789 struct xorg_xv_port_priv *priv =
790 port_priv_create(ms->xat, xar, ms->fd);
791
792 adapt->pPortPrivates[i].ptr = (pointer) (priv);
793 adapt->nPorts++;
794 }
795
796 return adapt;
797}
798
799void
800xorg_xv_init(ScreenPtr pScreen)
801{
802 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
803 modesettingPtr ms = modesettingPTR(pScrn);
804 XF86VideoAdaptorPtr *adaptors, *new_adaptors = NULL;
805 XF86VideoAdaptorPtr textured_adapter = NULL, overlay_adaptor = NULL;
806 int num_adaptors;
807
808 num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
809 new_adaptors = malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
810 if (new_adaptors == NULL)
811 return;
812
813 memcpy(new_adaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr));
814 adaptors = new_adaptors;
815
816 /* Add the adaptors supported by our hardware. First, set up the atoms
817 * that will be used by both output adaptors.
818 */
819 xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
820 xvContrast = MAKE_ATOM("XV_CONTRAST");
821 xvSaturation = MAKE_ATOM("XV_SATURATION");
822 xvHue = MAKE_ATOM("XV_HUE");
823
824 if (ms->xat) {
825 textured_adapter = xorg_setup_textured_adapter(pScreen);
826 if (textured_adapter)
827 adaptors[num_adaptors++] = textured_adapter;
828 } else {
829 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
830 "No 3D acceleration. Not setting up textured video.\n");
831 }
832
833 overlay_adaptor = vmw_video_init_adaptor(pScrn);
834 if (overlay_adaptor)
835 adaptors[num_adaptors++] = overlay_adaptor;
836
837 if (num_adaptors) {
838 Bool ret;
839 ret = xf86XVScreenInit(pScreen, adaptors, num_adaptors);
840 if (textured_adapter)
841 vmwgfx_free_textured_adaptor(textured_adapter, !ret);
842 if (overlay_adaptor)
843 vmw_video_free_adaptor(overlay_adaptor, !ret);
844 if (!ret)
845 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
846 "Failed to initialize Xv.\n");
847 } else {
848 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
849 "Disabling Xv because no adaptors could be initialized.\n");
850 }
851
852
853 out_err_mem:
854 free(adaptors);
855}
diff --git a/vmwgfx/vmwgfx_xa_composite.c b/vmwgfx/vmwgfx_xa_composite.c
new file mode 100644
index 0000000..a2e3970
--- /dev/null
+++ b/vmwgfx/vmwgfx_xa_composite.c
@@ -0,0 +1,277 @@
1/*
2 * Copyright 2009-2011 VMWare, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Thomas Hellstrom <thellstrom@vmware.com>
26 * Author: Zack Ruzin <zackr@vmware.com>
27 *
28 * The code in this file translates XRender PICT composite stuff
29 * to fit the libxatracker API.
30 */
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#include <picturestr.h>
37#include <X11/extensions/Xrender.h>
38#include "xa_composite.h"
39#include "vmwgfx_saa.h"
40#include "vmwgfx_saa_priv.h"
41
42
43struct vmwgfx_composite {
44 union xa_source_pict *src_spict;
45 union xa_source_pict *mask_spict;
46 union xa_source_pict *dst_spict;
47 struct xa_picture *src_pict;
48 struct xa_picture *mask_pict;
49 struct xa_picture *dst_pict;
50 struct xa_composite *comp;
51};
52
53static const enum xa_composite_op vmwgfx_op_map[] = {
54 [PictOpClear] = xa_op_clear,
55 [PictOpSrc] = xa_op_src,
56 [PictOpDst] = xa_op_dst,
57 [PictOpOver] = xa_op_over,
58 [PictOpOverReverse] = xa_op_over_reverse,
59 [PictOpIn] = xa_op_in,
60 [PictOpInReverse] = xa_op_in_reverse,
61 [PictOpOut] = xa_op_out,
62 [PictOpOutReverse] = xa_op_out_reverse,
63 [PictOpAtop] = xa_op_atop,
64 [PictOpAtopReverse] = xa_op_atop_reverse,
65 [PictOpXor] = xa_op_xor,
66 [PictOpAdd] = xa_op_add
67};
68
69static const unsigned int vmwgfx_op_map_size =
70 sizeof(vmwgfx_op_map) / sizeof(enum xa_composite_op);
71
72static Bool
73vmwgfx_matrix_from_pict_transform(PictTransform *trans, float *matrix)
74{
75 if (!trans)
76 return FALSE;
77
78 matrix[0] = XFixedToDouble(trans->matrix[0][0]);
79 matrix[3] = XFixedToDouble(trans->matrix[0][1]);
80 matrix[6] = XFixedToDouble(trans->matrix[0][2]);
81
82 matrix[1] = XFixedToDouble(trans->matrix[1][0]);
83 matrix[4] = XFixedToDouble(trans->matrix[1][1]);
84 matrix[7] = XFixedToDouble(trans->matrix[1][2]);
85
86 matrix[2] = XFixedToDouble(trans->matrix[2][0]);
87 matrix[5] = XFixedToDouble(trans->matrix[2][1]);
88 matrix[8] = XFixedToDouble(trans->matrix[2][2]);
89
90 return TRUE;
91}
92
93static enum xa_composite_wrap
94vmwgfx_xa_setup_wrap(Bool pict_has_repeat, int pict_repeat)
95{
96 enum xa_composite_wrap wrap = xa_wrap_clamp_to_border;
97
98 if (!pict_has_repeat)
99 return wrap;
100
101 switch(pict_repeat) {
102 case RepeatNormal:
103 wrap = xa_wrap_repeat;
104 break;
105 case RepeatReflect:
106 wrap = xa_wrap_mirror_repeat;
107 break;
108 case RepeatPad:
109 wrap = xa_wrap_clamp_to_edge;
110 break;
111 default:
112 break;
113 }
114 return wrap;
115}
116
117static Bool
118vmwgfx_render_filter_to_xa(int xrender_filter,
119 enum xa_composite_filter *out_filter)
120{
121 switch (xrender_filter) {
122 case PictFilterConvolution:
123 case PictFilterNearest:
124 case PictFilterFast:
125 *out_filter = xa_filter_nearest;
126 break;
127 case PictFilterBest:
128 case PictFilterGood:
129 case PictFilterBilinear:
130 *out_filter = xa_filter_linear;
131 break;
132 default:
133 *out_filter = xa_filter_nearest;
134 return FALSE;
135 }
136 return TRUE;
137}
138
139static Bool
140vmwgfx_xa_setup_pict(PicturePtr pict,
141 struct xa_picture *xa_pict,
142 union xa_source_pict *src_pict)
143{
144 if (!pict)
145 return FALSE;
146
147 memset(xa_pict, 0, sizeof(*xa_pict));
148
149 xa_pict->pict_format = vmwgfx_xa_format(pict->format);
150 if (xa_pict->pict_format == xa_format_unknown)
151 return FALSE;
152
153 /*
154 * Saa doesn't let drivers accelerate alpha maps.
155 */
156 xa_pict->alpha_map = NULL;
157 xa_pict->component_alpha = pict->componentAlpha;
158
159 xa_pict->has_transform =
160 vmwgfx_matrix_from_pict_transform(pict->transform,
161 xa_pict->transform);
162
163 xa_pict->wrap = vmwgfx_xa_setup_wrap(pict->repeat,
164 pict->repeatType);
165
166 (void) vmwgfx_render_filter_to_xa(pict->filter, &xa_pict->filter);
167
168 if (pict->pSourcePict) {
169 if (pict->pSourcePict->type != SourcePictTypeSolidFill)
170 return FALSE;
171
172 src_pict->type = xa_src_pict_solid_fill;
173 src_pict->solid_fill.color = pict->pSourcePict->solidFill.color;
174 xa_pict->src_pict = src_pict;
175 }
176
177 return TRUE;
178}
179
180struct xa_composite *
181vmwgfx_xa_setup_comp(struct vmwgfx_composite *vcomp,
182 int op,
183 PicturePtr src_pict,
184 PicturePtr mask_pict,
185 PicturePtr dst_pict)
186{
187 struct xa_composite *comp = vcomp->comp;
188
189 if (op >= vmwgfx_op_map_size)
190 return NULL;
191
192 comp->op = vmwgfx_op_map[op];
193 if (comp->op == xa_op_clear && op != PictOpClear)
194 return NULL;
195
196 if (!vmwgfx_xa_setup_pict(dst_pict, vcomp->dst_pict,
197 vcomp->dst_spict))
198 return NULL;
199 if (!vmwgfx_xa_setup_pict(src_pict, vcomp->src_pict,
200 vcomp->src_spict))
201 return NULL;
202 if (mask_pict && !vmwgfx_xa_setup_pict(mask_pict,
203 vcomp->mask_pict,
204 vcomp->mask_spict))
205 return NULL;
206
207 comp->dst = vcomp->dst_pict;
208 comp->src = vcomp->src_pict;
209 comp->mask = (mask_pict) ? vcomp->mask_pict : NULL;
210
211 return comp;
212}
213
214Bool
215vmwgfx_xa_update_comp(struct xa_composite *comp,
216 PixmapPtr src_pix,
217 PixmapPtr mask_pix,
218 PixmapPtr dst_pix)
219{
220 comp->dst->srf = vmwgfx_saa_pixmap(dst_pix)->hw;
221 if (src_pix)
222 comp->src->srf = vmwgfx_saa_pixmap(src_pix)->hw;
223 if (mask_pix && comp->mask)
224 comp->mask->srf = vmwgfx_saa_pixmap(mask_pix)->hw;
225 return TRUE;
226}
227
228
229void
230vmwgfx_free_composite(struct vmwgfx_composite *vcomp)
231{
232 if (!vcomp)
233 return;
234
235 if (vcomp->src_spict)
236 free(vcomp->src_spict);
237 if (vcomp->mask_spict)
238 free(vcomp->mask_spict);
239 if (vcomp->dst_spict)
240 free(vcomp->dst_spict);
241 if (vcomp->src_pict)
242 free(vcomp->src_pict);
243 if (vcomp->mask_pict)
244 free(vcomp->mask_pict);
245 if (vcomp->dst_pict)
246 free(vcomp->dst_pict);
247 if (vcomp->comp)
248 free(vcomp->comp);
249 free(vcomp);
250}
251
252struct vmwgfx_composite *
253vmwgfx_alloc_composite(void)
254{
255 const struct xa_composite_allocation *a = xa_composite_allocation();
256 struct vmwgfx_composite *vcomp = calloc(1, sizeof(*vcomp));
257
258 if (!vcomp)
259 return NULL;
260
261 vcomp->src_spict = calloc(1, a->xa_source_pict_size);
262 vcomp->mask_spict = calloc(1, a->xa_source_pict_size);
263 vcomp->dst_spict = calloc(1, a->xa_source_pict_size);
264 vcomp->src_pict = calloc(1, a->xa_picture_size);
265 vcomp->mask_pict = calloc(1, a->xa_picture_size);
266 vcomp->dst_pict = calloc(1, a->xa_picture_size);
267 vcomp->comp = calloc(1, a->xa_composite_size);
268
269 if (!vcomp->src_spict || !vcomp->mask_spict || !vcomp->dst_spict ||
270 !vcomp->src_pict || !vcomp->mask_pict || !vcomp->dst_pict ||
271 !vcomp->comp) {
272 vmwgfx_free_composite(vcomp);
273 return NULL;
274 }
275
276 return vcomp;
277}
diff --git a/vmwgfx/vmwgfx_xa_surface.c b/vmwgfx/vmwgfx_xa_surface.c
new file mode 100644
index 0000000..2a18762
--- /dev/null
+++ b/vmwgfx/vmwgfx_xa_surface.c
@@ -0,0 +1,368 @@
1/*
2 * Copyright 2011 VMWare, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Thomas Hellstrom <thellstrom@vmware.com>
26 */
27#ifdef _HAVE_CONFIG_H_
28#include "config.h"
29#endif
30
31#include <xorg-server.h>
32#include "vmwgfx_saa_priv.h"
33
34
35static const enum xa_surface_type vmwgfx_stype_map[] = {
36 [PICT_TYPE_OTHER] = xa_type_other,
37 [PICT_TYPE_A] = xa_type_a,
38 [PICT_TYPE_ARGB] = xa_type_argb,
39 [PICT_TYPE_ABGR] = xa_type_abgr,
40 [PICT_TYPE_BGRA] = xa_type_bgra
41};
42
43static const unsigned int vmwgfx_stype_map_size =
44 sizeof(vmwgfx_stype_map) / sizeof(enum xa_surface_type);
45
46
47/*
48 * Create an xa format from a PICT format.
49 */
50enum xa_formats
51vmwgfx_xa_format(enum _PictFormatShort format)
52{
53 uint32_t ptype = PICT_FORMAT_TYPE(format);
54
55 if (ptype >= vmwgfx_stype_map_size ||
56 vmwgfx_stype_map[ptype] == 0 ||
57 vmwgfx_stype_map[ptype] == xa_type_other)
58 return xa_format_unknown;
59
60 return xa_format(PICT_FORMAT_BPP(format),
61 vmwgfx_stype_map[ptype],
62 PICT_FORMAT_A(format),
63 PICT_FORMAT_R(format),
64 PICT_FORMAT_G(format),
65 PICT_FORMAT_B(format));
66}
67
68/*
69 * Choose formats and flags for a dri2 surface.
70 */
71static Bool
72vmwgfx_hw_dri2_stage(PixmapPtr pixmap, unsigned int depth)
73{
74 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
75 enum xa_formats format;
76
77 if (depth == 0)
78 depth = pixmap->drawable.depth;
79
80 switch(depth) {
81 case 32:
82 format = xa_format_a8r8g8b8;
83 break;
84 case 24:
85 format = xa_format_x8r8g8b8;
86 break;
87 case 16:
88 format = xa_format_r5g6b5;
89 break;
90 case 15:
91 format = xa_format_x1r5g5b5;
92 break;
93 default:
94 return FALSE;
95 }
96
97 vpix->staging_format = format;
98 vpix->staging_remove_flags = 0;
99 vpix->staging_add_flags = XA_FLAG_RENDER_TARGET | XA_FLAG_SHARED;
100
101 return TRUE;
102}
103
104/*
105 * Is composite old format compatible? Only difference is that old format
106 * has more alpha bits?
107 */
108static inline Bool
109vmwgfx_old_format_compatible(enum xa_formats format,
110 enum xa_formats old_format)
111{
112 return (format == old_format ||
113 (xa_format_type(format) == xa_format_type(old_format) &&
114 xa_format_a(format) <= xa_format_a(old_format) &&
115 xa_format_r(format) == xa_format_r(old_format) &&
116 xa_format_g(format) == xa_format_g(old_format) &&
117 xa_format_b(format) == xa_format_b(old_format)));
118}
119
120
121/*
122 * Choose format and flags for a composite dst surface.
123 */
124Bool
125vmwgfx_hw_composite_dst_stage(PixmapPtr pixmap,
126 enum _PictFormatShort pict_format)
127{
128 struct vmwgfx_saa *vsaa =
129 to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
130 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
131 enum xa_formats format = vmwgfx_xa_format(pict_format);
132
133 /*
134 * Check if we can reuse old hardware format.
135 */
136 if (vpix->hw) {
137 enum xa_formats old_format = xa_surface_format(vpix->hw);
138
139 if (vmwgfx_old_format_compatible(format, old_format))
140 format = old_format;
141 }
142
143 if (xa_format_check_supported(vsaa->xat, format,
144 vpix->xa_flags | XA_FLAG_RENDER_TARGET) !=
145 XA_ERR_NONE) {
146 return FALSE;
147 }
148
149 vpix->staging_format = format;
150 vpix->staging_remove_flags = 0;
151 vpix->staging_add_flags = XA_FLAG_RENDER_TARGET;
152
153 return TRUE;
154}
155
156/*
157 * Choose format and flags for a composite src surface.
158 */
159Bool
160vmwgfx_hw_composite_src_stage(PixmapPtr pixmap,
161 enum _PictFormatShort pict_format)
162{
163 struct vmwgfx_saa *vsaa =
164 to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
165 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
166 enum xa_formats format = vmwgfx_xa_format(pict_format);
167 enum xa_formats swizzle_format = xa_format_unknown;
168 enum xa_surface_type ftype;
169
170 if (format == xa_format_unknown)
171 return FALSE;
172
173 ftype = xa_format_type(format);
174 if (ftype == xa_type_abgr) {
175
176 swizzle_format = xa_format(xa_format_bpp(format),
177 xa_type_argb,
178 xa_format_a(format),
179 xa_format_r(format),
180 xa_format_g(format),
181 xa_format_b(format));
182 }
183
184 /*
185 * Check if we can reuse old format.
186 */
187
188 if (vpix->hw) {
189 enum xa_formats old_format = xa_surface_format(vpix->hw);
190
191 if (vmwgfx_old_format_compatible(format, old_format) ||
192 (swizzle_format != xa_format_unknown &&
193 vmwgfx_old_format_compatible(swizzle_format, old_format))) {
194 format = old_format;
195 goto have_format;
196 }
197 }
198
199 if (swizzle_format != xa_format_unknown &&
200 xa_format_check_supported(vsaa->xat, swizzle_format, vpix->xa_flags) ==
201 XA_ERR_NONE) {
202 format = swizzle_format;
203 goto have_format;
204 }
205
206 if (xa_format_check_supported(vsaa->xat, format, vpix->xa_flags) ==
207 XA_ERR_NONE) {
208 goto have_format;
209 }
210
211 return FALSE;
212 have_format:
213 vpix->staging_format = format;
214 vpix->staging_remove_flags = 0;
215 vpix->staging_add_flags = 0;
216
217 return TRUE;
218}
219
220/*
221 * Choose accel format given depth.
222 */
223static enum xa_formats
224vmwgfx_choose_accel_format(unsigned int depth)
225{
226 switch(depth) {
227 case 32:
228 return xa_format_a8r8g8b8;
229 case 24:
230 return xa_format_x8r8g8b8;
231 case 16:
232 return xa_format_r5g6b5;
233 case 15:
234 return xa_format_x1r5g5b5;
235 case 8:
236 return xa_format_a8;
237 default:
238 break;
239 }
240 return xa_format_unknown;
241}
242
243
244/*
245 * Determine xa format and flags for an ordinary accel surface.
246 */
247Bool
248vmwgfx_hw_accel_stage(PixmapPtr pixmap, unsigned int depth,
249 uint32_t add_flags, uint32_t remove_flags)
250{
251 struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
252 enum xa_formats format = xa_format_unknown;
253
254 if (depth == 0)
255 depth = pixmap->drawable.depth;
256
257 if (vpix->hw) {
258 enum xa_formats old_format = xa_surface_format(vpix->hw);
259 enum xa_surface_type ftype = xa_format_type(old_format);
260
261 if (ftype != xa_type_argb &&
262 ftype != xa_type_a) {
263 LogMessage(X_ERROR,
264 "Acceleration fallback due to strange hw format.\n");
265 return FALSE;
266 }
267
268 if (xa_format_depth(old_format) == depth ||
269 (xa_format_depth(old_format) == 32 &&
270 depth == 24))
271 format = old_format;
272 }
273
274 if (format == xa_format_unknown)
275 format = vmwgfx_choose_accel_format(depth);
276
277 if (format == xa_format_unknown)
278 return FALSE;
279
280 vpix->staging_add_flags = add_flags;
281 vpix->staging_remove_flags = remove_flags;
282 vpix->staging_format = format;
283
284 return TRUE;
285}
286
287/*
288 * Create a surface with a format and flags determined by one of
289 * the staging functions.
290 */
291Bool
292vmwgfx_hw_commit(PixmapPtr pixmap)
293{
294 struct vmwgfx_saa *vsaa =
295 to_vmwgfx_saa(saa_get_driver(pixmap->drawable.pScreen));
296 struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap);
297 struct vmwgfx_saa_pixmap *vpix = to_vmwgfx_saa_pixmap(spix);
298 enum xa_formats format = vpix->staging_format;
299
300 if (vpix->hw) {
301 enum xa_formats old_format = xa_surface_format(vpix->hw);
302
303 if (vpix->staging_format != old_format) {
304 if (xa_format_type(format) != xa_format_type(old_format) ||
305 xa_format_r(format) != xa_format_r(old_format) ||
306 xa_format_g(format) != xa_format_g(old_format) ||
307 xa_format_b(format) != xa_format_b(old_format)) {
308
309 LogMessage(X_INFO, "Killing old hw surface.\n");
310
311 if (!vmwgfx_hw_kill(vsaa, spix))
312 return FALSE;
313 }
314 }
315 }
316
317 if (vpix->hw) {
318 uint32_t new_flags;
319
320 new_flags = (vpix->xa_flags & ~vpix->staging_remove_flags) |
321 vpix->staging_add_flags;
322
323 if (vpix->staging_format != xa_surface_format(vpix->hw))
324 LogMessage(X_INFO, "Changing hardware format.\n");
325
326 if (xa_surface_redefine(vpix->hw,
327 pixmap->drawable.width,
328 pixmap->drawable.height,
329 0,
330 xa_type_other,
331 vpix->staging_format,
332 new_flags, 1) != XA_ERR_NONE)
333 return FALSE;
334 vpix->xa_flags = new_flags;
335 } else if (!vmwgfx_create_hw(vsaa, pixmap))
336 return FALSE;
337
338 return TRUE;
339}
340
341/*
342 * Create an accel surface if there is none, and make sure the region
343 * given by @region is valid. If @region is NULL, the whole surface
344 * will be valid. This is a utility convenience function only.
345 */
346Bool
347vmwgfx_hw_accel_validate(PixmapPtr pixmap, unsigned int depth,
348 uint32_t add_flags, uint32_t remove_flags,
349 RegionPtr region)
350{
351 return (vmwgfx_hw_accel_stage(pixmap, depth, add_flags, remove_flags) &&
352 vmwgfx_hw_commit(pixmap) &&
353 vmwgfx_hw_validate(pixmap, region));
354}
355
356
357/*
358 * Create a dri2 surface if there is none,
359 * and make sure the whole surfade is valid.
360 * This is a utility convenience function only.
361 */
362Bool
363vmwgfx_hw_dri2_validate(PixmapPtr pixmap, unsigned int depth)
364{
365 return (vmwgfx_hw_dri2_stage(pixmap, depth) &&
366 vmwgfx_hw_commit(pixmap) &&
367 vmwgfx_hw_validate(pixmap, NULL));
368}
diff --git a/vmwgfx/wsbm_util.h b/vmwgfx/wsbm_util.h
new file mode 100644
index 0000000..2a2613b
--- /dev/null
+++ b/vmwgfx/wsbm_util.h
@@ -0,0 +1,79 @@
1/*
2 * This file is not copyrighted.
3 */
4
5#ifndef _WSBM_UTIL_H_
6#define _WSBM_UTIL_H_
7
8#include <stddef.h>
9
10#ifndef containerOf
11#define containerOf(__item, __type, __field) \
12 ((__type *)(((char *) (__item)) - offsetof(__type, __field)))
13#endif
14
15struct _WsbmListHead
16{
17 struct _WsbmListHead *prev;
18 struct _WsbmListHead *next;
19};
20
21#define WSBMINITLISTHEAD(__item) \
22 do{ \
23 (__item)->prev = (__item); \
24 (__item)->next = (__item); \
25 } while (0)
26
27#define WSBMLISTADD(__item, __list) \
28 do { \
29 (__item)->prev = (__list); \
30 (__item)->next = (__list)->next; \
31 (__list)->next->prev = (__item); \
32 (__list)->next = (__item); \
33 } while (0)
34
35#define WSBMLISTADDTAIL(__item, __list) \
36 do { \
37 (__item)->next = (__list); \
38 (__item)->prev = (__list)->prev; \
39 (__list)->prev->next = (__item); \
40 (__list)->prev = (__item); \
41 } while(0)
42
43#define WSBMLISTDEL(__item) \
44 do { \
45 (__item)->prev->next = (__item)->next; \
46 (__item)->next->prev = (__item)->prev; \
47 } while(0)
48
49#define WSBMLISTDELINIT(__item) \
50 do { \
51 (__item)->prev->next = (__item)->next; \
52 (__item)->next->prev = (__item)->prev; \
53 (__item)->next = (__item); \
54 (__item)->prev = (__item); \
55 } while(0)
56
57#define WSBMLISTFOREACH(__item, __list) \
58 for((__item) = (__list)->next; (__item) != (__list); (__item) = (__item)->next)
59
60#define WSBMLISTFOREACHPREV(__item, __list) \
61 for((__item) = (__list)->prev; (__item) != (__list); (__item) = (__item)->prev)
62
63#define WSBMLISTFOREACHSAFE(__item, __next, __list) \
64 for((__item) = (__list)->next, (__next) = (__item)->next; \
65 (__item) != (__list); \
66 (__item) = (__next), (__next) = (__item)->next)
67
68#define WSBMLISTFOREACHPREVSAFE(__item, __prev, __list) \
69 for((__item) = (__list)->prev, (__prev) = (__item->prev); \
70 (__item) != (__list); \
71 (__item) = (__prev), (__prev) = (__item)->prev)
72
73#define WSBMLISTENTRY(__item, __type, __field) \
74 containerOf(__item, __type, __field)
75
76#define WSBMLISTEMPTY(__item) \
77 ((__item)->next == (__item))
78
79#endif