diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2011-12-19 20:25:43 +0100 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2011-12-19 20:25:43 +0100 |
commit | b5546fb1de3f3859151a91e98ab0bd24b6789e2e (patch) | |
tree | 8e5283d6610e87d796e0d64b0a06c42469422b0d | |
parent | abf9cb75630cb27bb4741d194cb23014fe3d09b1 (diff) | |
parent | 5748c33535bc7d3009b9758653885e6ae0e73002 (diff) |
Merge branch 'vmwgfx_branch'
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 | ||
21 | SUBDIRS = src man vmwarectrl | 21 | SUBDIRS = @VMWGFX_DIRS@ src man vmwarectrl |
22 | MAINTAINERCLEANFILES = ChangeLog INSTALL | 22 | MAINTAINERCLEANFILES = 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 |
74 | PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.1 xproto fontsproto $REQUIRED_MODULES]) | 74 | PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.1 xproto fontsproto $REQUIRED_MODULES]) |
75 | PKG_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 | |||
80 | PKG_CHECK_EXISTS([xorg-server >= 1.1.0], | 75 | PKG_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 | ||
92 | PKG_CHECK_EXISTS([xorg-server >= 1.7.0], | 87 | PKG_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 |
97 | PKG_CHECK_MODULES(X11, x11 xext) | 93 | PKG_CHECK_MODULES(X11, x11 xext) |
@@ -113,13 +109,40 @@ AM_CONDITIONAL(XSERVER_LIBPCIACCESS, test "x$XSERVER_LIBPCIACCESS" = xyes) | |||
113 | 109 | ||
114 | AC_SUBST([moduledir]) | 110 | AC_SUBST([moduledir]) |
115 | 111 | ||
112 | if test x$BUILD_VMWGFX = xyes; then | ||
113 | PKG_CHECK_MODULES([LIBDRM], [libdrm],[],[BUILD_VMWGFX=no]) | ||
114 | fi | ||
115 | if test x$BUILD_VMWGFX = xyes; then | ||
116 | PKG_CHECK_MODULES([XATRACKER], [xatracker >= 0.4.0],[],[BUILD_VMWGFX=no]) | ||
117 | fi | ||
118 | |||
116 | DRIVER_NAME=vmware | 119 | DRIVER_NAME=vmware |
117 | AC_SUBST([DRIVER_NAME]) | 120 | AC_SUBST([DRIVER_NAME]) |
118 | 121 | ||
122 | AC_MSG_CHECKING([whether to build Kernel Mode Setting and 3D]) | ||
123 | VMWGFX_DIRS= | ||
124 | if 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]) | ||
135 | else | ||
136 | AC_MSG_RESULT([no]) | ||
137 | fi | ||
138 | |||
139 | AC_SUBST([VMWGFX_DIRS]) | ||
140 | AC_SUBST([VMWGFX_LIBADD]) | ||
119 | AC_CONFIG_FILES([ | 141 | AC_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 | |||
125 | AC_OUTPUT | 148 | AC_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 @@ | |||
1 | noinst_LTLIBRARIES = libsaa.la | ||
2 | |||
3 | libsaa_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) | ||
4 | libsaa_la_LDFLAGS = -static | ||
5 | libsaa_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 | ||
44 | DevPrivateKeyRec saa_screen_index; | ||
45 | DevPrivateKeyRec saa_pixmap_index; | ||
46 | DevPrivateKeyRec saa_gc_index; | ||
47 | #else | ||
48 | int saa_screen_index = -1; | ||
49 | int saa_pixmap_index = -1; | ||
50 | int 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 | */ | ||
64 | PixmapPtr | ||
65 | saa_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 | */ | ||
78 | void | ||
79 | saa_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 | */ | ||
98 | PixmapPtr | ||
99 | saa_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 | |||
108 | static Bool | ||
109 | saa_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 | |||
131 | Bool | ||
132 | saa_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 | |||
168 | void | ||
169 | saa_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 | |||
205 | static void | ||
206 | saa_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 | |||
219 | Bool | ||
220 | saa_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 | |||
239 | static inline RegionPtr | ||
240 | saa_pix_damage_region(struct saa_pixmap *spix) | ||
241 | { | ||
242 | return (spix->damage ? DamageRegion(spix->damage) : NULL); | ||
243 | } | ||
244 | |||
245 | Bool | ||
246 | saa_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 | |||
270 | Bool | ||
271 | saa_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 | |||
301 | Bool | ||
302 | saa_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 | |||
330 | void | ||
331 | saa_fad_read(DrawablePtr draw) | ||
332 | { | ||
333 | saa_finish_access_pixmap(saa_get_drawable_pixmap(draw), SAA_ACCESS_R); | ||
334 | } | ||
335 | |||
336 | void | ||
337 | saa_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 | |||
347 | Bool | ||
348 | saa_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 | |||
356 | Bool | ||
357 | saa_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 | |||
373 | static void | ||
374 | saa_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 | |||
439 | static void | ||
440 | saa_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 | |||
449 | static void | ||
450 | saa_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 | |||
459 | static void | ||
460 | saa_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 | |||
469 | static void | ||
470 | saa_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 | |||
479 | static void | ||
480 | saa_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 | |||
489 | static void | ||
490 | saa_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 | |||
499 | static 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 | */ | ||
513 | int | ||
514 | saa_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 | |||
532 | static Bool | ||
533 | saa_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 | |||
550 | static void | ||
551 | saa_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 | |||
560 | static Bool | ||
561 | saa_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 | |||
572 | RegionPtr | ||
573 | saa_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 | |||
584 | void | ||
585 | saa_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 | */ | ||
596 | Bool | ||
597 | saa_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 | |||
630 | struct saa_driver * | ||
631 | saa_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 | */ | ||
646 | Bool | ||
647 | saa_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 | |||
741 | Bool | ||
742 | saa_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 | |||
57 | typedef unsigned int saa_access_t; | ||
58 | |||
59 | enum saa_pixmap_loc { | ||
60 | saa_loc_driver, | ||
61 | saa_loc_override, | ||
62 | }; | ||
63 | |||
64 | struct 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 | |||
82 | struct 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 | |||
130 | extern _X_EXPORT PixmapPtr | ||
131 | saa_get_drawable_pixmap(DrawablePtr pDrawable); | ||
132 | |||
133 | extern _X_EXPORT void | ||
134 | saa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap, | ||
135 | int *xp, int *yp); | ||
136 | |||
137 | extern _X_EXPORT PixmapPtr | ||
138 | saa_get_pixmap(DrawablePtr drawable, int *xp, int *yp); | ||
139 | |||
140 | extern _X_EXPORT Bool | ||
141 | saa_prepare_access_pixmap(PixmapPtr pix, saa_access_t access, | ||
142 | RegionPtr read_reg); | ||
143 | |||
144 | extern _X_EXPORT Bool | ||
145 | saa_pad_read(DrawablePtr draw); | ||
146 | |||
147 | Bool | ||
148 | saa_pad_read_box(DrawablePtr draw, int x, int y, int w, int h); | ||
149 | |||
150 | extern _X_EXPORT Bool | ||
151 | saa_pad_write(DrawablePtr draw, GCPtr pGC, Bool check_read, | ||
152 | saa_access_t * access); | ||
153 | |||
154 | extern _X_EXPORT void | ||
155 | saa_finish_access_pixmap(PixmapPtr pix, saa_access_t access); | ||
156 | |||
157 | extern _X_EXPORT void | ||
158 | saa_fad_read(DrawablePtr draw); | ||
159 | |||
160 | extern _X_EXPORT void | ||
161 | saa_fad_write(DrawablePtr draw, saa_access_t access); | ||
162 | |||
163 | extern _X_EXPORT Bool | ||
164 | saa_resources_init(ScreenPtr screen); | ||
165 | |||
166 | extern _X_EXPORT void | ||
167 | saa_driver_fini(ScreenPtr pScreen); | ||
168 | |||
169 | extern _X_EXPORT int | ||
170 | saa_create_gc(GCPtr pGC); | ||
171 | |||
172 | extern _X_EXPORT RegionPtr | ||
173 | saa_bitmap_to_region(PixmapPtr pPix); | ||
174 | |||
175 | extern _X_EXPORT Bool | ||
176 | saa_close_screen(int i, ScreenPtr pScreen); | ||
177 | |||
178 | extern _X_EXPORT Bool | ||
179 | saa_gc_reads_destination(DrawablePtr pDrawable, GCPtr pGC); | ||
180 | |||
181 | extern _X_EXPORT Bool | ||
182 | saa_op_reads_destination(CARD8 op); | ||
183 | |||
184 | extern _X_EXPORT void | ||
185 | saa_set_fallback_debug(ScreenPtr screen, Bool enable); | ||
186 | |||
187 | extern _X_EXPORT | ||
188 | struct saa_pixmap *saa_get_saa_pixmap(PixmapPtr pPixmap); | ||
189 | |||
190 | extern _X_EXPORT Bool | ||
191 | saa_add_damage(PixmapPtr pixmap); | ||
192 | |||
193 | extern _X_EXPORT struct saa_driver * | ||
194 | saa_get_driver(ScreenPtr pScreen); | ||
195 | |||
196 | extern _X_EXPORT Bool | ||
197 | saa_driver_init(ScreenPtr screen, struct saa_driver *saa_driver); | ||
198 | |||
199 | extern _X_EXPORT void | ||
200 | saa_pixmap_dirty(PixmapPtr pixmap, Bool hw, RegionPtr reg); | ||
201 | |||
202 | extern _X_EXPORT void | ||
203 | saa_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 | |||
35 | Bool | ||
36 | saa_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 | |||
115 | static void | ||
116 | saa_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 | |||
133 | RegionPtr | ||
134 | saa_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 | |||
32 | PixmapPtr | ||
33 | saa_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 | |||
114 | Bool | ||
115 | saa_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 | |||
147 | Bool | ||
148 | saa_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 | |||
185 | struct saa_pixmap * | ||
186 | saa_get_saa_pixmap(PixmapPtr pPixmap) | ||
187 | { | ||
188 | return saa_pixmap(pPixmap); | ||
189 | } | ||
190 | |||
191 | void | ||
192 | saa_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 | |||
212 | void | ||
213 | saa_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 | |||
67 | struct saa_gc_priv { | ||
68 | /* GC values from the layer below. */ | ||
69 | GCOps *saved_ops; | ||
70 | GCFuncs *saved_funcs; | ||
71 | }; | ||
72 | |||
73 | struct 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 | |||
104 | extern GCOps saa_gc_ops; | ||
105 | |||
106 | #if DEBUG_TRACE_FALL | ||
107 | #define SAA_FALLBACK(x) \ | ||
108 | do { \ | ||
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 | |||
139 | extern DevPrivateKeyRec saa_screen_index; | ||
140 | extern DevPrivateKeyRec saa_pixmap_index; | ||
141 | extern DevPrivateKeyRec saa_gc_index; | ||
142 | |||
143 | static inline struct saa_screen_priv * | ||
144 | saa_screen(ScreenPtr screen) | ||
145 | { | ||
146 | return (struct saa_screen_priv *)dixGetPrivate(&screen->devPrivates, | ||
147 | &saa_screen_index); | ||
148 | } | ||
149 | |||
150 | static inline struct saa_gc_priv * | ||
151 | saa_gc(GCPtr gc) | ||
152 | { | ||
153 | return (struct saa_gc_priv *)dixGetPrivateAddr(&gc->devPrivates, | ||
154 | &saa_gc_index); | ||
155 | } | ||
156 | |||
157 | static inline struct saa_pixmap * | ||
158 | saa_pixmap(PixmapPtr pix) | ||
159 | { | ||
160 | return (struct saa_pixmap *)dixGetPrivateAddr(&pix->devPrivates, | ||
161 | &saa_pixmap_index); | ||
162 | } | ||
163 | #else | ||
164 | #undef SAA_DEVPRIVATEKEYREC | ||
165 | extern int saa_screen_index; | ||
166 | extern int saa_pixmap_index; | ||
167 | extern int saa_gc_index; | ||
168 | |||
169 | static inline struct saa_screen_priv * | ||
170 | saa_screen(ScreenPtr screen) | ||
171 | { | ||
172 | return (struct saa_screen_priv *)dixLookupPrivate(&screen->devPrivates, | ||
173 | &saa_screen_index); | ||
174 | } | ||
175 | |||
176 | static inline struct saa_gc_priv * | ||
177 | saa_gc(GCPtr gc) | ||
178 | { | ||
179 | return (struct saa_gc_priv *)dixLookupPrivateAddr(&gc->devPrivates, | ||
180 | &saa_gc_index); | ||
181 | } | ||
182 | |||
183 | static inline struct saa_pixmap * | ||
184 | saa_pixmap(PixmapPtr pix) | ||
185 | { | ||
186 | return (struct saa_pixmap *)dixLookupPrivateAddr(&pix->devPrivates, | ||
187 | &saa_pixmap_index); | ||
188 | } | ||
189 | |||
190 | #endif | ||
191 | |||
192 | extern void | ||
193 | saa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans, | ||
194 | DDXPointPtr ppt, int *pwidth, int fSorted); | ||
195 | extern void | ||
196 | saa_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC, | ||
197 | int nrect, xRectangle * prect); | ||
198 | extern RegionPtr | ||
199 | saa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, | ||
200 | int srcx, int srcy, int w, int h, int dstx, int dsty); | ||
201 | extern void | ||
202 | saa_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 | |||
206 | extern void | ||
207 | saa_unaccel_setup(ScreenPtr pScreen); | ||
208 | |||
209 | extern void | ||
210 | saa_unaccel_takedown(ScreenPtr pScreen); | ||
211 | |||
212 | extern RegionPtr | ||
213 | saa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, | ||
214 | int srcx, int srcy, int width, int height, int dstx, int dsty); | ||
215 | |||
216 | extern Bool | ||
217 | saa_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 | ||
224 | extern void | ||
225 | saa_render_setup(ScreenPtr pScreen); | ||
226 | |||
227 | extern void | ||
228 | saa_render_takedown(ScreenPtr pScreen); | ||
229 | |||
230 | |||
231 | extern void | ||
232 | saa_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 | |||
246 | extern Bool | ||
247 | saa_modify_pixmap_header(PixmapPtr pPixmap, int width, int height, int depth, | ||
248 | int bitsPerPixel, int devKind, pointer pPixData); | ||
249 | |||
250 | extern PixmapPtr | ||
251 | saa_create_pixmap(ScreenPtr pScreen, int w, int h, int depth, | ||
252 | unsigned usage_hint); | ||
253 | |||
254 | extern Bool | ||
255 | saa_destroy_pixmap(PixmapPtr pPixmap); | ||
256 | |||
257 | static inline RegionPtr | ||
258 | saa_pix_damage_pending(struct saa_pixmap *spix) | ||
259 | { | ||
260 | return (spix->damage ? DamagePendingRegion(spix->damage) : NULL); | ||
261 | } | ||
262 | |||
263 | extern RegionPtr | ||
264 | saa_boxes_to_region(ScreenPtr pScreen, int nbox, BoxPtr pbox, int ordering); | ||
265 | |||
266 | |||
267 | Bool | ||
268 | saa_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 | |||
41 | static PicturePtr | ||
42 | saa_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 | */ | ||
97 | static void | ||
98 | saa_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 | */ | ||
159 | static void | ||
160 | saa_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 | |||
210 | static Bool | ||
211 | saa_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 | |||
296 | static Bool | ||
297 | saa_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 | |||
357 | static void | ||
358 | saa_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 | |||
399 | void | ||
400 | saa_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 | |||
412 | void | ||
413 | saa_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 | */ | ||
41 | static Bool | ||
42 | saa_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 | */ | ||
59 | static void | ||
60 | saa_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 | |||
68 | void | ||
69 | saa_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 | |||
91 | static void | ||
92 | saa_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 | |||
110 | static void | ||
111 | saa_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 | |||
131 | RegionPtr | ||
132 | saa_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 | |||
153 | void | ||
154 | saa_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 | |||
221 | RegionPtr | ||
222 | saa_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 | |||
251 | static RegionPtr | ||
252 | saa_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 | |||
283 | static void | ||
284 | saa_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 | |||
304 | static void | ||
305 | saa_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 | |||
331 | static void | ||
332 | saa_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 | |||
357 | static void | ||
358 | saa_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 | |||
381 | void | ||
382 | saa_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 | |||
412 | static void | ||
413 | saa_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 | |||
438 | static void | ||
439 | saa_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 | |||
465 | static void | ||
466 | saa_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 | |||
496 | static void | ||
497 | saa_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) | ||
531 | static void | ||
532 | saa_src_validate(DrawablePtr pDrawable, | ||
533 | int x, | ||
534 | int y, int width, int height, unsigned int subWindowMode) | ||
535 | #else | ||
536 | static void | ||
537 | saa_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, ®, &box, 1); | ||
557 | REGION_UNION(pScreen, dst, dst, ®); | ||
558 | REGION_UNINIT(pScreen, ®); | ||
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 | |||
571 | static void | ||
572 | saa_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 | |||
591 | static void | ||
592 | saa_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 | |||
619 | Bool | ||
620 | saa_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 | |||
700 | static Bool | ||
701 | saa_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 | |||
795 | void | ||
796 | saa_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 | |||
852 | static void | ||
853 | saa_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 | |||
876 | void | ||
877 | saa_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 | |||
895 | void | ||
896 | saa_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 | |||
914 | GCOps 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 | ||
27 | vmwlegacy_drv_la_LTLIBRARIES = vmwlegacy_drv.la | 27 | vmware_drv_la_LTLIBRARIES = vmware_drv.la |
28 | vmwlegacy_drv_la_LDFLAGS = -module -avoid-version | 28 | vmware_drv_la_LDFLAGS = -module -avoid-version |
29 | vmwlegacy_drv_la_CFLAGS = @XORG_CFLAGS@ | 29 | vmware_drv_la_CFLAGS = @XORG_CFLAGS@ |
30 | vmwlegacy_drv_ladir = @moduledir@/drivers | 30 | vmware_drv_ladir = @moduledir@/drivers |
31 | vmware_drv_la_LIBADD = @VMWGFX_LIBADD@ | ||
32 | vmware_drv_la_DEPENDENCIES = @VMWGFX_LIBADD@ | ||
31 | 33 | ||
32 | vmwlegacy_drv_la_SOURCES = \ | 34 | vmware_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 \ | |
55 | vmware_drv_la_LTLIBRARIES = vmware_drv.la | 57 | vmware_bootstrap.c \ |
56 | vmware_drv_la_LDFLAGS = -module -avoid-version | 58 | vmware_common.c \ |
57 | vmware_drv_la_CFLAGS = @XORG_CFLAGS@ @LIBDRM_CFLAGS@ | 59 | vmware_common.h |
58 | vmware_drv_la_LIBADD = @LIBDRM_LIBS@ | ||
59 | vmware_drv_ladir = @moduledir@/drivers | ||
60 | |||
61 | vmware_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 | 292 | typedef |
177 | #define SVGA_CAP_OFFSCREEN_1 0x00001000 | 293 | struct 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 | 298 | typedef |
183 | #define SVGA_CAP_IRQMASK 0x00040000 | 299 | struct 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 */ | 325 | typedef |
192 | #define SVGA_ROP_AND 0x01 /* src AND dst */ | 326 | struct 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) | 338 | typedef |
339 | struct 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 | * | 368 | typedef |
224 | * BlendOp Fa Fb | 369 | struct 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: | 396 | typedef |
252 | * | 397 | struct 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 | 404 | typedef |
260 | #define SVGA_BLENDOP_OVER_REVERSE 4 | 405 | struct 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 | |||
978 | typedef | ||
979 | struct 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)) | 1018 | typedef 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 | |
1071 | typedef | ||
1072 | struct 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 | 1090 | typedef |
671 | /* FIFO layout: | 1091 | struct 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 | 1114 | typedef |
683 | /* FIFO layout: | 1115 | struct 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 | 1143 | typedef |
695 | /* FIFO layout: | 1144 | struct 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 | 1166 | typedef |
707 | /* FIFO layout: | 1167 | struct 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 | 1193 | typedef |
724 | /* FIFO layout: | 1194 | struct 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 | 1219 | typedef |
736 | /* FIFO layout: | 1220 | struct { |
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 | 1236 | typedef |
749 | /* FIFO layout: | 1237 | struct 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 | 1270 | typedef |
763 | /* FIFO layout: | 1271 | struct { |
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 | 1286 | typedef |
847 | * at under 2GB in the address space. This restricts VMs to have "only" | 1287 | struct { |
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 | |||
1339 | typedef | ||
1340 | struct { | ||
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 | |||
1376 | typedef | ||
1377 | struct { | ||
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 | |||
1424 | typedef | ||
1425 | struct { | ||
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 | |||
1459 | typedef | ||
1460 | struct { | ||
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 | |||
1491 | typedef | ||
1492 | struct { | ||
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 | |||
1507 | typedef | ||
1508 | struct { | ||
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 | |||
1542 | typedef 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 | |||
1549 | typedef | ||
1550 | struct { | ||
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 | |||
98 | static 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 | ||
110 | const char vmwlegacy_drv_modinfo[] | ||
111 | __attribute__((section(".modinfo"),unused)) = | ||
112 | "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH); | ||
113 | #else | ||
114 | const char vmwlegacy_drv_modinfo[] | ||
115 | __attribute__((section(".modinfo"),unused)) = | ||
116 | "version=" VMWARE_DRIVER_VERSION_STRING ".0"; | ||
117 | #endif /*VMW_SUBPATCH*/ | ||
118 | #endif | ||
119 | |||
120 | static SymTabRec VMWAREChipsets[] = { | ||
121 | { PCI_CHIP_VMWARE0405, "vmware0405" }, | ||
122 | { PCI_CHIP_VMWARE0710, "vmware0710" }, | ||
123 | { -1, NULL } | ||
124 | }; | ||
125 | |||
126 | #ifndef XSERVER_LIBPCIACCESS | ||
127 | static 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 | |||
141 | static 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 | |||
155 | static 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 | |||
168 | static 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 | |||
181 | static const char *fbSymbols[] = { | ||
182 | "fbCreateDefColormap", | ||
183 | "fbPictureInit", | ||
184 | "fbScreenInit", | ||
185 | NULL | ||
186 | }; | ||
187 | |||
188 | static const char *ramdacSymbols[] = { | ||
189 | "xf86CreateCursorInfoRec", | ||
190 | "xf86DestroyCursorInfoRec", | ||
191 | "xf86InitCursor", | ||
192 | NULL | ||
193 | }; | ||
194 | |||
195 | static const char *shadowfbSymbols[] = { | ||
196 | "ShadowFBInit2", | ||
197 | NULL | ||
198 | }; | ||
199 | |||
200 | #endif /* HAVE_XORG_SERVER_1_7_0 */ | ||
201 | |||
202 | #ifdef XFree86LOADER | ||
203 | static 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 | |||
217 | typedef enum { | ||
218 | OPTION_HW_CURSOR, | ||
219 | OPTION_XINERAMA, | ||
220 | OPTION_STATIC_XINERAMA, | ||
221 | OPTION_DEFAULT_MODE, | ||
222 | } VMWAREOpts; | ||
223 | |||
224 | static 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 | ||
469 | static void | ||
470 | VMWAREIdentify(int flags) | ||
471 | { | ||
472 | xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets); | ||
473 | } | ||
474 | |||
475 | static const OptionInfoRec * | ||
476 | VMWAREAvailableOptions(int chipid, int busid) | ||
477 | { | ||
478 | return VMWAREOptions; | ||
479 | } | ||
480 | |||
481 | static int | ||
482 | VMWAREParseTopologyElement(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 | |||
538 | static xXineramaScreenInfo * | ||
539 | VMWAREParseTopologyString(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 | |||
604 | static Bool | 291 | static Bool |
605 | VMWAREPreInit(ScrnInfoPtr pScrn, int flags) | 292 | VMWAREPreInit(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 | ||
1612 | static Bool | ||
1613 | VMWareDriverFunc(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 | |||
1651 | static Bool | 1294 | static Bool |
1652 | VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) | 1295 | VMWAREScreenInit(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 | 1645 | void |
1990 | static Bool | 1646 | vmwlegacy_hookup(ScrnInfoPtr pScrn) |
1991 | VMwarePciProbe (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 | |||
2028 | static Bool | ||
2029 | VMWAREProbe(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 | ||
2112 | static MODULESETUPPROTO(vmwlegacySetup); | ||
2113 | |||
2114 | _X_EXPORT XF86ModuleData vmwlegacyModuleData = { | ||
2115 | &vmwlegacyVersRec, | ||
2116 | vmwlegacySetup, | ||
2117 | NULL | ||
2118 | }; | ||
2119 | |||
2120 | static pointer | ||
2121 | vmwlegacySetup(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 | |||
92 | static 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 | ||
104 | const char vmware_drv_modinfo[] | ||
105 | __attribute__((section(".modinfo"),unused)) = | ||
106 | "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH); | ||
107 | #else | ||
108 | const 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 | ||
115 | static 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 | |||
143 | static 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 | |||
157 | static 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 | |||
163 | static SymTabRec VMWAREChipsets[] = { | ||
164 | { PCI_CHIP_VMWARE0405, "vmware0405" }, | ||
165 | { PCI_CHIP_VMWARE0710, "vmware0710" }, | ||
166 | { -1, NULL } | ||
167 | }; | ||
168 | |||
169 | #ifdef XFree86LOADER | ||
170 | static 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 | |||
184 | static 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 | |||
198 | OptionInfoPtr 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 | |||
208 | static Bool | ||
209 | VMwarePreinitStub(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 | ||
258 | static Bool | ||
259 | VMwarePciProbe (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 | |||
298 | static Bool | ||
299 | VMWAREProbe(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 | |||
361 | static void | ||
362 | VMWAREIdentify(int flags) | ||
363 | { | ||
364 | xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets); | ||
365 | } | ||
366 | |||
367 | static const OptionInfoRec * | ||
368 | VMWAREAvailableOptions(int chipid, int busid) | ||
369 | { | ||
370 | return VMWAREOptions; | ||
371 | } | ||
372 | |||
373 | #if VMWARE_DRIVER_FUNC | ||
374 | static Bool | ||
375 | VMWareDriverFunc(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 | |||
441 | const char *vgahwSymbols[] = { | ||
442 | "vgaHWGetHWRec", | ||
443 | "vgaHWGetIOBase", | ||
444 | "vgaHWGetIndex", | ||
445 | "vgaHWInit", | ||
446 | "vgaHWProtect", | ||
447 | "vgaHWRestore", | ||
448 | "vgaHWSave", | ||
449 | "vgaHWSaveScreen", | ||
450 | "vgaHWUnlock", | ||
451 | NULL | ||
452 | }; | ||
453 | |||
454 | static const char *fbSymbols[] = { | ||
455 | "fbCreateDefColormap", | ||
456 | "fbPictureInit", | ||
457 | "fbScreenInit", | ||
458 | NULL | ||
459 | }; | ||
460 | |||
461 | static const char *ramdacSymbols[] = { | ||
462 | "xf86CreateCursorInfoRec", | ||
463 | "xf86DestroyCursorInfoRec", | ||
464 | "xf86InitCursor", | ||
465 | NULL | ||
466 | }; | ||
467 | |||
468 | static const char *shadowfbSymbols[] = { | ||
469 | "ShadowFBInit2", | ||
470 | NULL | ||
471 | }; | ||
472 | #endif | ||
473 | |||
474 | #ifdef XFree86LOADER | ||
475 | static MODULESETUPPROTO(vmwareSetup); | ||
476 | |||
477 | _X_EXPORT XF86ModuleData vmwareModuleData = { | ||
478 | &vmwareVersRec, | ||
479 | vmwareSetup, | ||
480 | NULL | ||
481 | }; | ||
482 | |||
483 | static pointer | ||
484 | vmwareSetup(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 | |||
34 | typedef 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 | |||
47 | OptionInfoPtr VMWARECopyOptions(void); | ||
48 | const char **vgahwSymbols; | ||
49 | |||
50 | void | ||
51 | vmwlegacy_hookup(ScrnInfoPtr pScrn); | ||
52 | |||
53 | #ifdef BUILD_VMWGFX | ||
54 | void | ||
55 | vmwgfx_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 | |||
39 | static int | ||
40 | VMWAREParseTopologyElement(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 | |||
96 | xXineramaScreenInfo * | ||
97 | VMWAREParseTopologyString(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 | |||
35 | xXineramaScreenInfo * | ||
36 | VMWAREParseTopologyString(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 | ||
72 | const char vmware_drv_modinfo[] __attribute__((section(".modinfo"),unused)) = | ||
73 | "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH); | ||
74 | #else | ||
75 | const char vmware_drv_modinfo[] __attribute__((section(".modinfo"),unused)) = | ||
76 | "version=" VMWARE_DRIVER_VERSION_STRING ".0"; | ||
77 | #endif /*VMW_SUBPATCH*/ | ||
78 | #endif | ||
79 | |||
80 | static XF86ModuleVersionInfo vmware_version; | ||
81 | static MODULESETUPPROTO(vmware_setup); | ||
82 | |||
83 | _X_EXPORT XF86ModuleData vmwareModuleData = { | ||
84 | &vmware_version, | ||
85 | vmware_setup, | ||
86 | NULL | ||
87 | }; | ||
88 | |||
89 | extern XF86ModuleData *VMWGFX_MODULE_DATA; | ||
90 | |||
91 | /* | ||
92 | * Chain loading functions | ||
93 | */ | ||
94 | |||
95 | static Bool | ||
96 | vmware_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 | |||
120 | static Bool | ||
121 | vmware_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 | |||
161 | err: | ||
162 | /* XXX We should drop the reference on the module here */ | ||
163 | #endif /* HAVE_LIBDRM */ | ||
164 | return FALSE; | ||
165 | } | ||
166 | |||
167 | static Bool | ||
168 | vmware_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 | |||
221 | static 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 | |||
234 | static pointer | ||
235 | vmware_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 @@ | |||
1 | noinst_LTLIBRARIES = libvmwgfx.la | ||
2 | libvmwgfx_la_CFLAGS = $(CWARNFLAGS) $(XORG_CFLAGS) @LIBDRM_CFLAGS@ @XATRACKER_CFLAGS@ -I$(top_srcdir)/src -I$(top_srcdir)/saa | ||
3 | libvmwgfx_la_LIBADD = @LIBDRM_LIBS@ $(top_srcdir)/saa/libsaa.la\ | ||
4 | @XATRACKER_LIBS@ | ||
5 | libvmwgfx_la_DEPENDENCIES = $(top_srcdir)/saa/libsaa.la | ||
6 | |||
7 | libvmwgfx_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 | |||
53 | typedef 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 | |||
67 | typedef 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 | |||
81 | typedef 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 | |||
156 | typedef 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 | */ | ||
164 | typedef 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 | */ | ||
272 | typedef 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 | |||
308 | typedef 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 | |||
420 | typedef 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 | |||
426 | typedef 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 | |||
435 | typedef | ||
436 | union { | ||
437 | struct { | ||
438 | uint16 mode; /* SVGA3dFillModeType */ | ||
439 | uint16 face; /* SVGA3dFace */ | ||
440 | }; | ||
441 | uint32 uintValue; | ||
442 | } SVGA3dFillMode; | ||
443 | |||
444 | typedef 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 | |||
452 | typedef | ||
453 | union { | ||
454 | struct { | ||
455 | uint16 repeat; | ||
456 | uint16 pattern; | ||
457 | }; | ||
458 | uint32 uintValue; | ||
459 | } SVGA3dLinePattern; | ||
460 | |||
461 | typedef 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 | |||
479 | typedef 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 | |||
489 | typedef enum { | ||
490 | SVGA3D_FRONTWINDING_INVALID = 0, | ||
491 | SVGA3D_FRONTWINDING_CW = 1, | ||
492 | SVGA3D_FRONTWINDING_CCW = 2, | ||
493 | SVGA3D_FRONTWINDING_MAX | ||
494 | } SVGA3dFrontWinding; | ||
495 | |||
496 | typedef 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 | |||
509 | typedef 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 | */ | ||
527 | typedef 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 | */ | ||
539 | typedef 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 | */ | ||
551 | typedef enum { | ||
552 | SVGA3D_FOGBASE_INVALID = 0, | ||
553 | SVGA3D_FOGBASE_DEPTHBASED = 1, | ||
554 | SVGA3D_FOGBASE_RANGEBASED = 2, | ||
555 | SVGA3D_FOGBASE_MAX = 3 | ||
556 | } SVGA3dFogBase; | ||
557 | |||
558 | typedef 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 | |||
571 | typedef 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 | |||
580 | typedef enum { | ||
581 | SVGA3D_CLEAR_COLOR = 0x1, | ||
582 | SVGA3D_CLEAR_DEPTH = 0x2, | ||
583 | SVGA3D_CLEAR_STENCIL = 0x4 | ||
584 | } SVGA3dClearFlag; | ||
585 | |||
586 | typedef 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 | |||
603 | typedef | ||
604 | union { | ||
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 | |||
614 | typedef enum { | ||
615 | SVGA3D_VBLEND_DISABLE = 0, | ||
616 | SVGA3D_VBLEND_1WEIGHT = 1, | ||
617 | SVGA3D_VBLEND_2WEIGHT = 2, | ||
618 | SVGA3D_VBLEND_3WEIGHT = 3, | ||
619 | } SVGA3dVertexBlendFlags; | ||
620 | |||
621 | typedef 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 | |||
634 | typedef 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 | |||
678 | typedef 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 | |||
711 | typedef 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 | */ | ||
726 | typedef 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 | |||
738 | typedef 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 | |||
747 | typedef 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 | */ | ||
759 | typedef 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. */ | ||
772 | typedef 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 | |||
800 | typedef 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 | |||
818 | typedef 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 | |||
828 | typedef 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 | */ | ||
853 | typedef 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 | |||
877 | typedef 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 | |||
888 | typedef enum { | ||
889 | SVGA3D_COORDINATE_INVALID = 0, | ||
890 | SVGA3D_COORDINATE_LEFTHANDED = 1, | ||
891 | SVGA3D_COORDINATE_RIGHTHANDED = 2, | ||
892 | SVGA3D_COORDINATE_MAX | ||
893 | } SVGA3dCoordinateType; | ||
894 | |||
895 | typedef 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 | |||
914 | typedef 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 | |||
923 | typedef 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 | |||
932 | typedef enum { | ||
933 | SVGA3D_SHADERTYPE_COMPILED_DX8 = 0, | ||
934 | SVGA3D_SHADERTYPE_VS = 1, | ||
935 | SVGA3D_SHADERTYPE_PS = 2, | ||
936 | SVGA3D_SHADERTYPE_MAX | ||
937 | } SVGA3dShaderType; | ||
938 | |||
939 | typedef 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 | |||
947 | typedef enum { | ||
948 | SVGA3D_STRETCH_BLT_POINT = 0, | ||
949 | SVGA3D_STRETCH_BLT_LINEAR = 1, | ||
950 | SVGA3D_STRETCH_BLT_MAX | ||
951 | } SVGA3dStretchBltMode; | ||
952 | |||
953 | typedef enum { | ||
954 | SVGA3D_QUERYTYPE_OCCLUSION = 0, | ||
955 | SVGA3D_QUERYTYPE_MAX | ||
956 | } SVGA3dQueryType; | ||
957 | |||
958 | typedef 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 | |||
965 | typedef 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 | |||
1037 | typedef 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 | |||
1053 | typedef | ||
1054 | struct SVGA3dSurfaceImageId { | ||
1055 | uint32 sid; | ||
1056 | uint32 face; | ||
1057 | uint32 mipmap; | ||
1058 | } SVGA3dSurfaceImageId; | ||
1059 | |||
1060 | typedef | ||
1061 | struct 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 | */ | ||
1090 | typedef | ||
1091 | struct { | ||
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 | |||
1101 | typedef | ||
1102 | struct { | ||
1103 | uint32 width; | ||
1104 | uint32 height; | ||
1105 | uint32 depth; | ||
1106 | } SVGA3dSize; | ||
1107 | |||
1108 | typedef 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 | |||
1120 | typedef | ||
1121 | struct { | ||
1122 | uint32 numMipLevels; | ||
1123 | } SVGA3dSurfaceFace; | ||
1124 | |||
1125 | typedef | ||
1126 | struct { | ||
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 | |||
1142 | typedef | ||
1143 | struct { | ||
1144 | uint32 sid; | ||
1145 | } SVGA3dCmdDestroySurface; /* SVGA_3D_CMD_SURFACE_DESTROY */ | ||
1146 | |||
1147 | typedef | ||
1148 | struct { | ||
1149 | uint32 cid; | ||
1150 | } SVGA3dCmdDefineContext; /* SVGA_3D_CMD_CONTEXT_DEFINE */ | ||
1151 | |||
1152 | typedef | ||
1153 | struct { | ||
1154 | uint32 cid; | ||
1155 | } SVGA3dCmdDestroyContext; /* SVGA_3D_CMD_CONTEXT_DESTROY */ | ||
1156 | |||
1157 | typedef | ||
1158 | struct { | ||
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 | |||
1167 | typedef | ||
1168 | struct SVGA3dCopyRect { | ||
1169 | uint32 x; | ||
1170 | uint32 y; | ||
1171 | uint32 w; | ||
1172 | uint32 h; | ||
1173 | uint32 srcx; | ||
1174 | uint32 srcy; | ||
1175 | } SVGA3dCopyRect; | ||
1176 | |||
1177 | typedef | ||
1178 | struct 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 | |||
1190 | typedef | ||
1191 | struct { | ||
1192 | uint32 x; | ||
1193 | uint32 y; | ||
1194 | uint32 w; | ||
1195 | uint32 h; | ||
1196 | } SVGA3dRect; | ||
1197 | |||
1198 | typedef | ||
1199 | struct { | ||
1200 | uint32 x; | ||
1201 | uint32 y; | ||
1202 | uint32 z; | ||
1203 | uint32 w; | ||
1204 | uint32 h; | ||
1205 | uint32 d; | ||
1206 | } SVGA3dBox; | ||
1207 | |||
1208 | typedef | ||
1209 | struct { | ||
1210 | uint32 x; | ||
1211 | uint32 y; | ||
1212 | uint32 z; | ||
1213 | } SVGA3dPoint; | ||
1214 | |||
1215 | typedef | ||
1216 | struct { | ||
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 | |||
1233 | typedef | ||
1234 | struct { | ||
1235 | uint32 sid; | ||
1236 | /* Followed by variable number of SVGA3dCopyRect structures */ | ||
1237 | } SVGA3dCmdPresent; /* SVGA_3D_CMD_PRESENT */ | ||
1238 | |||
1239 | typedef | ||
1240 | struct { | ||
1241 | SVGA3dRenderStateName state; | ||
1242 | union { | ||
1243 | uint32 uintValue; | ||
1244 | float floatValue; | ||
1245 | }; | ||
1246 | } SVGA3dRenderState; | ||
1247 | |||
1248 | typedef | ||
1249 | struct { | ||
1250 | uint32 cid; | ||
1251 | /* Followed by variable number of SVGA3dRenderState structures */ | ||
1252 | } SVGA3dCmdSetRenderState; /* SVGA_3D_CMD_SETRENDERSTATE */ | ||
1253 | |||
1254 | typedef | ||
1255 | struct { | ||
1256 | uint32 cid; | ||
1257 | SVGA3dRenderTargetType type; | ||
1258 | SVGA3dSurfaceImageId target; | ||
1259 | } SVGA3dCmdSetRenderTarget; /* SVGA_3D_CMD_SETRENDERTARGET */ | ||
1260 | |||
1261 | typedef | ||
1262 | struct { | ||
1263 | SVGA3dSurfaceImageId src; | ||
1264 | SVGA3dSurfaceImageId dest; | ||
1265 | /* Followed by variable number of SVGA3dCopyBox structures */ | ||
1266 | } SVGA3dCmdSurfaceCopy; /* SVGA_3D_CMD_SURFACE_COPY */ | ||
1267 | |||
1268 | typedef | ||
1269 | struct { | ||
1270 | SVGA3dSurfaceImageId src; | ||
1271 | SVGA3dSurfaceImageId dest; | ||
1272 | SVGA3dBox boxSrc; | ||
1273 | SVGA3dBox boxDest; | ||
1274 | SVGA3dStretchBltMode mode; | ||
1275 | } SVGA3dCmdSurfaceStretchBlt; /* SVGA_3D_CMD_SURFACE_STRETCHBLT */ | ||
1276 | |||
1277 | typedef | ||
1278 | struct { | ||
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 | |||
1299 | typedef | ||
1300 | struct { | ||
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 | |||
1327 | typedef | ||
1328 | struct { | ||
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 | |||
1368 | typedef | ||
1369 | struct { | ||
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 | |||
1383 | typedef | ||
1384 | struct { | ||
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 | |||
1401 | typedef | ||
1402 | struct { | ||
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 | |||
1415 | typedef | ||
1416 | struct { | ||
1417 | SVGA3dVertexArrayIdentity identity; | ||
1418 | SVGA3dArray array; | ||
1419 | SVGA3dArrayRangeHint rangeHint; | ||
1420 | } SVGA3dVertexDecl; | ||
1421 | |||
1422 | typedef | ||
1423 | struct { | ||
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 | |||
1472 | typedef | ||
1473 | struct { | ||
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 | |||
1492 | typedef | ||
1493 | struct { | ||
1494 | uint32 stage; | ||
1495 | SVGA3dTextureStateName name; | ||
1496 | union { | ||
1497 | uint32 value; | ||
1498 | float floatValue; | ||
1499 | }; | ||
1500 | } SVGA3dTextureState; | ||
1501 | |||
1502 | typedef | ||
1503 | struct { | ||
1504 | uint32 cid; | ||
1505 | /* Followed by variable number of SVGA3dTextureState structures */ | ||
1506 | } SVGA3dCmdSetTextureState; /* SVGA_3D_CMD_SETTEXTURESTATE */ | ||
1507 | |||
1508 | typedef | ||
1509 | struct { | ||
1510 | uint32 cid; | ||
1511 | SVGA3dTransformType type; | ||
1512 | float matrix[16]; | ||
1513 | } SVGA3dCmdSetTransform; /* SVGA_3D_CMD_SETTRANSFORM */ | ||
1514 | |||
1515 | typedef | ||
1516 | struct { | ||
1517 | float min; | ||
1518 | float max; | ||
1519 | } SVGA3dZRange; | ||
1520 | |||
1521 | typedef | ||
1522 | struct { | ||
1523 | uint32 cid; | ||
1524 | SVGA3dZRange zRange; | ||
1525 | } SVGA3dCmdSetZRange; /* SVGA_3D_CMD_SETZRANGE */ | ||
1526 | |||
1527 | typedef | ||
1528 | struct { | ||
1529 | float diffuse[4]; | ||
1530 | float ambient[4]; | ||
1531 | float specular[4]; | ||
1532 | float emissive[4]; | ||
1533 | float shininess; | ||
1534 | } SVGA3dMaterial; | ||
1535 | |||
1536 | typedef | ||
1537 | struct { | ||
1538 | uint32 cid; | ||
1539 | SVGA3dFace face; | ||
1540 | SVGA3dMaterial material; | ||
1541 | } SVGA3dCmdSetMaterial; /* SVGA_3D_CMD_SETMATERIAL */ | ||
1542 | |||
1543 | typedef | ||
1544 | struct { | ||
1545 | uint32 cid; | ||
1546 | uint32 index; | ||
1547 | SVGA3dLightData data; | ||
1548 | } SVGA3dCmdSetLightData; /* SVGA_3D_CMD_SETLIGHTDATA */ | ||
1549 | |||
1550 | typedef | ||
1551 | struct { | ||
1552 | uint32 cid; | ||
1553 | uint32 index; | ||
1554 | uint32 enabled; | ||
1555 | } SVGA3dCmdSetLightEnabled; /* SVGA_3D_CMD_SETLIGHTENABLED */ | ||
1556 | |||
1557 | typedef | ||
1558 | struct { | ||
1559 | uint32 cid; | ||
1560 | SVGA3dRect rect; | ||
1561 | } SVGA3dCmdSetViewport; /* SVGA_3D_CMD_SETVIEWPORT */ | ||
1562 | |||
1563 | typedef | ||
1564 | struct { | ||
1565 | uint32 cid; | ||
1566 | SVGA3dRect rect; | ||
1567 | } SVGA3dCmdSetScissorRect; /* SVGA_3D_CMD_SETSCISSORRECT */ | ||
1568 | |||
1569 | typedef | ||
1570 | struct { | ||
1571 | uint32 cid; | ||
1572 | uint32 index; | ||
1573 | float plane[4]; | ||
1574 | } SVGA3dCmdSetClipPlane; /* SVGA_3D_CMD_SETCLIPPLANE */ | ||
1575 | |||
1576 | typedef | ||
1577 | struct { | ||
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 | |||
1584 | typedef | ||
1585 | struct { | ||
1586 | uint32 cid; | ||
1587 | uint32 shid; | ||
1588 | SVGA3dShaderType type; | ||
1589 | } SVGA3dCmdDestroyShader; /* SVGA_3D_CMD_SHADER_DESTROY */ | ||
1590 | |||
1591 | typedef | ||
1592 | struct { | ||
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 | |||
1600 | typedef | ||
1601 | struct { | ||
1602 | uint32 cid; | ||
1603 | SVGA3dShaderType type; | ||
1604 | uint32 shid; | ||
1605 | } SVGA3dCmdSetShader; /* SVGA_3D_CMD_SET_SHADER */ | ||
1606 | |||
1607 | typedef | ||
1608 | struct { | ||
1609 | uint32 cid; | ||
1610 | SVGA3dQueryType type; | ||
1611 | } SVGA3dCmdBeginQuery; /* SVGA_3D_CMD_BEGIN_QUERY */ | ||
1612 | |||
1613 | typedef | ||
1614 | struct { | ||
1615 | uint32 cid; | ||
1616 | SVGA3dQueryType type; | ||
1617 | SVGAGuestPtr guestResult; /* Points to an SVGA3dQueryResult structure */ | ||
1618 | } SVGA3dCmdEndQuery; /* SVGA_3D_CMD_END_QUERY */ | ||
1619 | |||
1620 | typedef | ||
1621 | struct { | ||
1622 | uint32 cid; /* Same parameters passed to END_QUERY */ | ||
1623 | SVGA3dQueryType type; | ||
1624 | SVGAGuestPtr guestResult; | ||
1625 | } SVGA3dCmdWaitForQuery; /* SVGA_3D_CMD_WAIT_FOR_QUERY */ | ||
1626 | |||
1627 | typedef | ||
1628 | struct { | ||
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 | |||
1673 | typedef | ||
1674 | struct { | ||
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 | |||
1709 | typedef 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 | |||
1794 | typedef 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 | |||
55 | struct 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 | |||
68 | static void | ||
69 | crtc_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 | |||
104 | void | ||
105 | vmwgfx_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 | |||
123 | static Bool | ||
124 | crtc_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 | |||
218 | static void | ||
219 | crtc_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 | |||
228 | static void * | ||
229 | crtc_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 | |||
244 | static PixmapPtr | ||
245 | crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) | ||
246 | { | ||
247 | return (PixmapPtr) data; | ||
248 | } | ||
249 | |||
250 | static void | ||
251 | crtc_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 | |||
263 | static void | ||
264 | crtc_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 | |||
269 | static void | ||
270 | crtc_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 | |||
278 | static void | ||
279 | crtc_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 | |||
313 | static void | ||
314 | crtc_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 | |||
333 | static void | ||
334 | crtc_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 | |||
344 | static void | ||
345 | crtc_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 | */ | ||
356 | void | ||
357 | xorg_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 | |||
371 | static void | ||
372 | crtc_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 | |||
387 | static 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 | |||
405 | void | ||
406 | xorg_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 | |||
448 | PixmapPtr | ||
449 | crtc_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 | |||
62 | static int | ||
63 | VMwareCtrlQueryVersion(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 | |||
107 | static Bool | ||
108 | VMwareCtrlDoSetRes(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 | |||
143 | static int | ||
144 | VMwareCtrlSetRes(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 | |||
205 | static Bool | ||
206 | VMwareCtrlDoSetTopology(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 | |||
250 | static int | ||
251 | VMwareCtrlSetTopology(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 | |||
308 | static int | ||
309 | VMwareCtrlDispatch(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 | |||
342 | static int | ||
343 | SVMwareCtrlQueryVersion(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 | |||
373 | static int | ||
374 | SVMwareCtrlSetRes(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 | |||
407 | static int | ||
408 | SVMwareCtrlSetTopology(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 | |||
441 | static int | ||
442 | SVMwareCtrlDispatch(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 | |||
474 | static void | ||
475 | VMwareCtrlResetProc(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 | |||
497 | void | ||
498 | vmw_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 | |||
49 | typedef 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 | |||
62 | static unsigned int | ||
63 | vmwgfx_color_format_to_depth(unsigned int format) | ||
64 | { | ||
65 | return format; | ||
66 | } | ||
67 | |||
68 | static unsigned int | ||
69 | vmwgfx_zs_format_to_depth(unsigned int format) | ||
70 | { | ||
71 | if (format == 24) | ||
72 | return 32; | ||
73 | return format; | ||
74 | } | ||
75 | |||
76 | static unsigned int | ||
77 | vmwgfx_z_format_to_depth(unsigned int format) | ||
78 | { | ||
79 | return format; | ||
80 | } | ||
81 | |||
82 | static Bool | ||
83 | dri2_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 | |||
216 | static void | ||
217 | dri2_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 | |||
243 | static DRI2Buffer2Ptr | ||
244 | dri2_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); | ||
265 | fail: | ||
266 | free(buffer); | ||
267 | return NULL; | ||
268 | } | ||
269 | |||
270 | static void | ||
271 | dri2_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 | |||
280 | static void | ||
281 | dri2_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 | |||
371 | Bool | ||
372 | xorg_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 | |||
420 | void | ||
421 | xorg_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 | */ | ||
68 | typedef int64_t int64; | ||
69 | typedef uint64_t uint64; | ||
70 | |||
71 | typedef int32_t int32; | ||
72 | typedef uint32_t uint32; | ||
73 | |||
74 | typedef int16_t int16; | ||
75 | typedef uint16_t uint16; | ||
76 | |||
77 | typedef int8_t int8; | ||
78 | typedef 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 | |||
107 | static Bool drv_pre_init(ScrnInfoPtr pScrn, int flags); | ||
108 | static Bool drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, | ||
109 | char **argv); | ||
110 | static Bool drv_switch_mode(int scrnIndex, DisplayModePtr mode, int flags); | ||
111 | static void drv_adjust_frame(int scrnIndex, int x, int y, int flags); | ||
112 | static Bool drv_enter_vt(int scrnIndex, int flags); | ||
113 | static void drv_leave_vt(int scrnIndex, int flags); | ||
114 | static void drv_free_screen(int scrnIndex, int flags); | ||
115 | static ModeStatus drv_valid_mode(int scrnIndex, DisplayModePtr mode, Bool verbose, | ||
116 | int flags); | ||
117 | |||
118 | extern void xorg_tracker_set_functions(ScrnInfoPtr scrn); | ||
119 | |||
120 | void | ||
121 | vmwgfx_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 | |||
134 | static Bool drv_close_screen(int scrnIndex, ScreenPtr pScreen); | ||
135 | |||
136 | /* | ||
137 | * Internal functions | ||
138 | */ | ||
139 | |||
140 | static Bool | ||
141 | drv_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 | |||
151 | static void | ||
152 | drv_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 | |||
165 | static void | ||
166 | drv_probe_ddc(ScrnInfoPtr pScrn, int index) | ||
167 | { | ||
168 | ConfiguredMonitor = NULL; | ||
169 | } | ||
170 | |||
171 | static Bool | ||
172 | drv_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 | |||
223 | error_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 | |||
234 | static const xf86CrtcConfigFuncsRec crtc_config_funcs = { | ||
235 | .resize = drv_crtc_resize | ||
236 | }; | ||
237 | |||
238 | static Bool | ||
239 | drv_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 | */ | ||
294 | static Bool | ||
295 | vmwgfx_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 | |||
335 | static Bool | ||
336 | drv_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 | |||
580 | static Bool | ||
581 | vmwgfx_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 | |||
605 | static Bool | ||
606 | vmwgfx_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 | |||
634 | void 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 | |||
711 | static 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 | |||
725 | static Bool | ||
726 | drv_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 | |||
741 | static Bool | ||
742 | drv_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 | */ | ||
771 | static Bool | ||
772 | vmwgfx_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 | */ | ||
802 | static Bool | ||
803 | vmwgfx_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 | */ | ||
832 | static 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 | |||
843 | static 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 | |||
902 | static Bool | ||
903 | drv_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 | |||
1098 | static void | ||
1099 | drv_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 | |||
1114 | static void | ||
1115 | drv_free_screen(int scrnIndex, int flags) | ||
1116 | { | ||
1117 | drv_free_rec(xf86Screens[scrnIndex]); | ||
1118 | } | ||
1119 | |||
1120 | static void | ||
1121 | drv_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 | */ | ||
1140 | static Bool | ||
1141 | drv_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 | |||
1154 | static Bool | ||
1155 | drv_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 | |||
1162 | static Bool | ||
1163 | drv_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 | |||
1194 | static ModeStatus | ||
1195 | drv_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 | |||
60 | typedef 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 | |||
70 | enum xorg_throttling_reason { | ||
71 | THROTTLE_RENDER, | ||
72 | THROTTLE_SWAP | ||
73 | }; | ||
74 | |||
75 | typedef 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 | |||
132 | void xorg_flush(ScreenPtr pScreen); | ||
133 | /*********************************************************************** | ||
134 | * xorg_dri2.c | ||
135 | */ | ||
136 | Bool | ||
137 | xorg_dri2_init(ScreenPtr pScreen); | ||
138 | |||
139 | void | ||
140 | xorg_dri2_close(ScreenPtr pScreen); | ||
141 | |||
142 | |||
143 | /*********************************************************************** | ||
144 | * xorg_crtc.c | ||
145 | */ | ||
146 | void | ||
147 | xorg_crtc_init(ScrnInfoPtr pScrn); | ||
148 | |||
149 | void | ||
150 | xorg_crtc_cursor_destroy(xf86CrtcPtr crtc); | ||
151 | |||
152 | void | ||
153 | vmwgfx_disable_scanout(ScrnInfoPtr pScrn); | ||
154 | |||
155 | PixmapPtr | ||
156 | crtc_get_scanout(xf86CrtcPtr crtc); | ||
157 | |||
158 | |||
159 | /*********************************************************************** | ||
160 | * xorg_output.c | ||
161 | */ | ||
162 | void | ||
163 | xorg_output_init(ScrnInfoPtr pScrn); | ||
164 | |||
165 | unsigned | ||
166 | xorg_output_get_id(xf86OutputPtr output); | ||
167 | |||
168 | Bool | ||
169 | vmwgfx_output_explicit_overlap(ScrnInfoPtr pScrn); | ||
170 | |||
171 | |||
172 | /*********************************************************************** | ||
173 | * xorg_xv.c | ||
174 | */ | ||
175 | void | ||
176 | xorg_xv_init(ScreenPtr pScreen); | ||
177 | |||
178 | XF86VideoAdaptorPtr | ||
179 | vmw_video_init_adaptor(ScrnInfoPtr pScrn); | ||
180 | void | ||
181 | vmw_video_free_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports); | ||
182 | |||
183 | void | ||
184 | vmw_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 | |||
89 | struct 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 | |||
112 | struct 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 | |||
155 | struct 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 | |||
174 | struct 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 | |||
190 | struct 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 | |||
206 | union 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 | |||
234 | union 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 | |||
279 | struct 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 | |||
313 | struct 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 | |||
348 | struct 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 | |||
366 | struct 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 | |||
383 | union 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 | |||
403 | struct 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 | |||
427 | struct 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 | |||
452 | struct 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 | |||
494 | struct 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 | |||
517 | struct 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 | |||
548 | struct 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 | |||
600 | struct 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 | |||
631 | struct 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 | |||
657 | struct 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 | |||
678 | struct 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 | */ | ||
700 | struct 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 | |||
732 | struct 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 | |||
762 | struct 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 | */ | ||
786 | struct 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 | |||
48 | static int | ||
49 | vmwgfx_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 | |||
66 | static void | ||
67 | vmwgfx_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 | |||
79 | int | ||
80 | vmwgfx_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 | |||
135 | int | ||
136 | vmwgfx_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 | |||
181 | struct 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 | |||
191 | static inline struct vmwgfx_int_dmabuf * | ||
192 | vmwgfx_int_dmabuf(struct vmwgfx_dmabuf *buf) | ||
193 | { | ||
194 | return (struct vmwgfx_int_dmabuf *) buf; | ||
195 | } | ||
196 | |||
197 | struct vmwgfx_dmabuf* | ||
198 | vmwgfx_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 | |||
232 | void * | ||
233 | vmwgfx_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 | |||
252 | void | ||
253 | vmwgfx_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 | |||
267 | void | ||
268 | vmwgfx_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 | |||
286 | int | ||
287 | vmwgfx_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 | |||
389 | int | ||
390 | vmwgfx_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 | |||
407 | int | ||
408 | vmwgfx_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 | |||
427 | int | ||
428 | vmwgfx_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 | |||
443 | int | ||
444 | vmwgfx_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 | |||
458 | int | ||
459 | vmwgfx_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 | |||
475 | int | ||
476 | vmwgfx_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 | |||
491 | int | ||
492 | vmwgfx_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 | |||
37 | struct vmwgfx_dma_ctx; | ||
38 | |||
39 | extern int | ||
40 | vmwgfx_present_readback(int drm_fd, uint32_t fb_id, RegionPtr region); | ||
41 | |||
42 | extern int | ||
43 | vmwgfx_present(int drm_fd, uint32_t fb_id, unsigned int dst_x, | ||
44 | unsigned int dst_y, RegionPtr region, uint32_t handle); | ||
45 | |||
46 | struct vmwgfx_dmabuf { | ||
47 | uint32_t handle; | ||
48 | uint32_t gmr_id; | ||
49 | uint32_t gmr_offset; | ||
50 | size_t size; | ||
51 | }; | ||
52 | |||
53 | extern struct vmwgfx_dmabuf* | ||
54 | vmwgfx_dmabuf_alloc(int drm_fd, size_t size); | ||
55 | extern void | ||
56 | vmwgfx_dmabuf_destroy(struct vmwgfx_dmabuf *buf); | ||
57 | extern void * | ||
58 | vmwgfx_dmabuf_map(struct vmwgfx_dmabuf *buf); | ||
59 | extern void | ||
60 | vmwgfx_dmabuf_unmap(struct vmwgfx_dmabuf *buf); | ||
61 | |||
62 | extern int | ||
63 | vmwgfx_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 | |||
67 | extern int | ||
68 | vmwgfx_num_streams(int drm_fd, uint32_t *ntot, uint32_t *nfree); | ||
69 | |||
70 | extern int | ||
71 | vmwgfx_claim_stream(int drm_fd, uint32_t *out); | ||
72 | |||
73 | extern int | ||
74 | vmwgfx_unref_stream(int drm_fd, uint32_t stream_id); | ||
75 | |||
76 | int | ||
77 | vmwgfx_cursor_bypass(int drm_fd, int xhot, int yhot); | ||
78 | |||
79 | int | ||
80 | vmwgfx_max_fb_size(int drm_fd, size_t *size); | ||
81 | |||
82 | int | ||
83 | vmwgfx_update_gui_layout(int drm_fd, unsigned int num_rects, | ||
84 | struct drm_vmw_rect *rects); | ||
85 | int | ||
86 | vmwgfx_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 | |||
54 | struct output_private | ||
55 | { | ||
56 | drmModeConnectorPtr drm_connector; | ||
57 | |||
58 | int c; | ||
59 | |||
60 | Bool is_implicit; | ||
61 | }; | ||
62 | |||
63 | static 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 | |||
82 | static void | ||
83 | output_create_resources(xf86OutputPtr output) | ||
84 | { | ||
85 | #ifdef RANDR_12_INTERFACE | ||
86 | #endif /* RANDR_12_INTERFACE */ | ||
87 | } | ||
88 | |||
89 | static void | ||
90 | output_dpms(xf86OutputPtr output, int mode) | ||
91 | { | ||
92 | } | ||
93 | |||
94 | static xf86OutputStatus | ||
95 | output_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 | |||
124 | static DisplayModePtr | ||
125 | output_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 | |||
167 | static int | ||
168 | output_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 | ||
184 | static Bool | ||
185 | output_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr value) | ||
186 | { | ||
187 | return TRUE; | ||
188 | } | ||
189 | #endif /* RANDR_12_INTERFACE */ | ||
190 | |||
191 | #ifdef RANDR_13_INTERFACE | ||
192 | static Bool | ||
193 | output_get_property(xf86OutputPtr output, Atom property) | ||
194 | { | ||
195 | return TRUE; | ||
196 | } | ||
197 | #endif /* RANDR_13_INTERFACE */ | ||
198 | |||
199 | static void | ||
200 | output_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 | |||
208 | static 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 | */ | ||
231 | Bool | ||
232 | vmwgfx_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 | |||
293 | void | ||
294 | xorg_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 | |||
386 | unsigned | ||
387 | xorg_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 | */ | ||
45 | typedef int64_t int64; | ||
46 | typedef uint64_t uint64; | ||
47 | |||
48 | typedef int32_t int32; | ||
49 | typedef uint32_t uint32; | ||
50 | |||
51 | typedef int16_t int16; | ||
52 | typedef uint16_t uint16; | ||
53 | |||
54 | typedef int8_t int8; | ||
55 | typedef 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 | ||
87 | static 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 | ||
98 | static XF86VideoFormatRec vmwareVideoFormats[] = | ||
99 | { | ||
100 | { 16, TrueColor}, | ||
101 | { 24, TrueColor} | ||
102 | }; | ||
103 | |||
104 | #define VMWARE_VID_NUM_IMAGES 3 | ||
105 | static XF86ImageRec vmwareVideoImages[] = | ||
106 | { | ||
107 | XVIMAGE_YV12, | ||
108 | XVIMAGE_YUY2, | ||
109 | XVIMAGE_UYVY | ||
110 | }; | ||
111 | |||
112 | #define VMWARE_VID_NUM_ATTRIBUTES 2 | ||
113 | static 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 | */ | ||
138 | struct 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 | */ | ||
152 | struct 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 | */ | ||
189 | static 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); | ||
195 | static void vmw_xv_stop_video(ScrnInfoPtr pScrn, pointer data, Bool Cleanup); | ||
196 | static int vmw_xv_query_image_attributes(ScrnInfoPtr pScrn, int format, | ||
197 | unsigned short *width, | ||
198 | unsigned short *height, int *pitches, | ||
199 | int *offsets); | ||
200 | static int vmw_xv_set_port_attribute(ScrnInfoPtr pScrn, Atom attribute, | ||
201 | INT32 value, pointer data); | ||
202 | static int vmw_xv_get_port_attribute(ScrnInfoPtr pScrn, Atom attribute, | ||
203 | INT32 *value, pointer data); | ||
204 | static 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 | */ | ||
213 | static 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); | ||
220 | static 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); | ||
226 | static void vmw_video_port_cleanup(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port); | ||
227 | |||
228 | static int vmw_video_buffer_alloc(int drm_fd, int size, | ||
229 | struct vmw_video_buffer *out); | ||
230 | static int vmw_video_buffer_free(struct vmw_video_buffer *out); | ||
231 | |||
232 | |||
233 | static struct vmwgfx_overlay_port * | ||
234 | vmwgfx_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 | |||
249 | void | ||
250 | vmw_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 | |||
281 | XF86VideoAdaptorPtr | ||
282 | vmw_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 | |||
373 | static int | ||
374 | vmw_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 | |||
441 | static int | ||
442 | vmw_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 | |||
535 | static void | ||
536 | vmw_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 | |||
572 | static int | ||
573 | vmw_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 | |||
610 | static int | ||
611 | vmw_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 | |||
650 | static int | ||
651 | vmw_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 | |||
689 | static void | ||
690 | vmw_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 | |||
723 | static int | ||
724 | vmw_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 | |||
798 | static int | ||
799 | vmw_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 | |||
838 | static int | ||
839 | vmw_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 | |||
883 | static void | ||
884 | vmw_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 | */ | ||
40 | static Bool | ||
41 | vmwgfx_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 | |||
70 | static void | ||
71 | vmwgfx_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 | |||
84 | static void | ||
85 | vmwgfx_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 | |||
101 | static Bool | ||
102 | vmwgfx_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 | |||
135 | static void | ||
136 | vmwgfx_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 | |||
152 | static Bool | ||
153 | vmwgfx_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 | |||
192 | static Bool | ||
193 | vmwgfx_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 | |||
225 | static Bool | ||
226 | vmwgfx_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 | |||
275 | static Bool | ||
276 | vmwgfx_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 | |||
321 | static Bool | ||
322 | vmwgfx_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 | |||
359 | static Bool | ||
360 | vmwgfx_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 | |||
366 | static void | ||
367 | vmwgfx_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 | |||
373 | static void * | ||
374 | vmwgfx_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 | |||
386 | static void * | ||
387 | vmwgfx_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 | |||
399 | static void | ||
400 | vmwgfx_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 | |||
412 | static Bool | ||
413 | vmwgfx_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 | |||
427 | Bool | ||
428 | vmwgfx_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 | |||
457 | void | ||
458 | vmwgfx_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 | |||
482 | static void | ||
483 | vmwgfx_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 | |||
512 | static void | ||
513 | vmwgfx_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 | |||
529 | static Bool | ||
530 | vmwgfx_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 | |||
622 | static Bool | ||
623 | vmwgfx_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 | |||
676 | static Bool | ||
677 | vmwgfx_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 | |||
701 | static Bool | ||
702 | vmwgfx_is_present_hw(PixmapPtr pixmap) | ||
703 | { | ||
704 | struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap); | ||
705 | return (vpix->dirty_present != NULL); | ||
706 | } | ||
707 | |||
708 | static void | ||
709 | vmwgfx_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 | |||
743 | Bool | ||
744 | vmwgfx_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 | |||
786 | out_no_damage: | ||
787 | xa_surface_destroy(hw); | ||
788 | return FALSE; | ||
789 | } | ||
790 | |||
791 | |||
792 | Bool | ||
793 | vmwgfx_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 | |||
842 | static Bool | ||
843 | vmwgfx_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 | |||
950 | static void | ||
951 | vmwgfx_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 | |||
971 | static void | ||
972 | vmwgfx_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, ®, &box, 1); | ||
1000 | REGION_UNION(pScreen, &vsaa->present_region, &vsaa->present_region, ®); | ||
1001 | REGION_UNINIT(pScreen, ®); | ||
1002 | } | ||
1003 | |||
1004 | static void | ||
1005 | vmwgfx_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 | |||
1022 | static void | ||
1023 | vmwgfx_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 | |||
1034 | static Bool | ||
1035 | vmwgfx_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 = ∅ | ||
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 | |||
1162 | static void | ||
1163 | vmwgfx_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 | |||
1174 | static void | ||
1175 | vmwgfx_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 | |||
1182 | static void | ||
1183 | vmwgfx_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 | */ | ||
1197 | static void | ||
1198 | vmwgfx_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 | */ | ||
1231 | static Bool | ||
1232 | vmwgfx_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, ®); | ||
1279 | REGION_INTERSECT(vsaa->pScreen, ®, vpix->pending_update, | ||
1280 | damage); | ||
1281 | if (REGION_NOTEMPTY(vsaa->pScreen, ®)) | ||
1282 | vsaa->present_flush(vsaa->pScreen); | ||
1283 | REGION_UNINIT(pScreen, ®); | ||
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, ®); | ||
1296 | REGION_INTERSECT(vsaa->pScreen, ®, vpix->pending_present, | ||
1297 | damage); | ||
1298 | if (REGION_NOTEMPTY(vsaa->pScreen, ®)) | ||
1299 | vsaa->present_flush(vsaa->pScreen); | ||
1300 | REGION_UNINIT(pScreen, ®); | ||
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 | |||
1313 | static 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 | |||
1337 | Bool | ||
1338 | vmwgfx_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 | |||
1393 | void | ||
1394 | vmwgfx_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 | |||
1422 | uint32_t | ||
1423 | vmwgfx_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 | */ | ||
1489 | void | ||
1490 | vmwgfx_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 | |||
42 | struct 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 | |||
64 | struct vmwgfx_screen_entry { | ||
65 | struct _WsbmListHead scanout_head; | ||
66 | PixmapPtr pixmap; | ||
67 | }; | ||
68 | |||
69 | static inline struct vmwgfx_saa_pixmap * | ||
70 | to_vmwgfx_saa_pixmap(struct saa_pixmap *spix) | ||
71 | { | ||
72 | return (struct vmwgfx_saa_pixmap *) spix; | ||
73 | } | ||
74 | |||
75 | static inline struct vmwgfx_saa_pixmap* | ||
76 | vmwgfx_saa_pixmap(PixmapPtr pix) | ||
77 | { | ||
78 | return to_vmwgfx_saa_pixmap(saa_get_saa_pixmap(pix)); | ||
79 | } | ||
80 | |||
81 | extern Bool | ||
82 | vmwgfx_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 | |||
88 | extern uint32_t | ||
89 | vmwgfx_scanout_ref(struct vmwgfx_screen_entry *box); | ||
90 | |||
91 | extern void | ||
92 | vmwgfx_scanout_unref(struct vmwgfx_screen_entry *box); | ||
93 | |||
94 | extern void | ||
95 | vmwgfx_scanout_refresh(PixmapPtr pixmap); | ||
96 | |||
97 | extern void | ||
98 | vmwgfx_remove_dri2_list(struct vmwgfx_saa_pixmap *vpix); | ||
99 | |||
100 | extern void | ||
101 | vmwgfx_flush_dri2(ScreenPtr pScreen); | ||
102 | |||
103 | extern Bool | ||
104 | vmwgfx_hw_dri2_validate(PixmapPtr pixmap, unsigned int depth); | ||
105 | |||
106 | Bool | ||
107 | vmwgfx_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 | |||
38 | struct 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 | |||
62 | static inline struct vmwgfx_saa * | ||
63 | to_vmwgfx_saa(struct saa_driver *driver) { | ||
64 | return (struct vmwgfx_saa *) driver; | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * In vmwgfx_saa.c | ||
69 | */ | ||
70 | |||
71 | Bool | ||
72 | vmwgfx_hw_kill(struct vmwgfx_saa *vsaa, | ||
73 | struct saa_pixmap *spix); | ||
74 | Bool | ||
75 | vmwgfx_create_hw(struct vmwgfx_saa *vsaa, | ||
76 | PixmapPtr pixmap); | ||
77 | |||
78 | |||
79 | /* | ||
80 | * vmwgfx_xa_surface.c | ||
81 | */ | ||
82 | |||
83 | enum xa_formats | ||
84 | vmwgfx_xa_format(enum _PictFormatShort format); | ||
85 | Bool | ||
86 | vmwgfx_hw_validate(PixmapPtr pixmap, RegionPtr region); | ||
87 | |||
88 | Bool | ||
89 | vmwgfx_hw_accel_stage(PixmapPtr pixmap, unsigned int depth, | ||
90 | uint32_t add_flags, uint32_t remove_flags); | ||
91 | Bool | ||
92 | vmwgfx_hw_composite_src_stage(PixmapPtr pixmap, | ||
93 | enum _PictFormatShort pict_format); | ||
94 | Bool | ||
95 | vmwgfx_hw_composite_dst_stage(PixmapPtr pixmap, | ||
96 | enum _PictFormatShort pict_format); | ||
97 | Bool | ||
98 | vmwgfx_hw_commit(PixmapPtr pixmap); | ||
99 | |||
100 | /* | ||
101 | * vmwgfx_xa_composite.c | ||
102 | */ | ||
103 | |||
104 | struct vmwgfx_composite; | ||
105 | |||
106 | void | ||
107 | vmwgfx_free_composite(struct vmwgfx_composite *vcomp); | ||
108 | struct vmwgfx_composite * | ||
109 | vmwgfx_alloc_composite(void); | ||
110 | |||
111 | Bool | ||
112 | vmwgfx_xa_update_comp(struct xa_composite *comp, | ||
113 | PixmapPtr src_pix, | ||
114 | PixmapPtr mask_pix, | ||
115 | PixmapPtr dst_pix); | ||
116 | |||
117 | struct xa_composite * | ||
118 | vmwgfx_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 | |||
58 | static 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 | |||
64 | static 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 | |||
70 | static Atom xvBrightness, xvContrast, xvSaturation, xvHue; | ||
71 | |||
72 | #define NUM_TEXTURED_ATTRIBUTES 4 | ||
73 | static 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 | ||
81 | static XF86VideoFormatRec Formats[NUM_FORMATS] = { | ||
82 | {15, TrueColor}, {16, TrueColor}, {24, TrueColor} | ||
83 | }; | ||
84 | |||
85 | static 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 | ||
95 | static XF86ImageRec Images[NUM_IMAGES] = { | ||
96 | XVIMAGE_UYVY, | ||
97 | XVIMAGE_YUY2, | ||
98 | XVIMAGE_YV12, | ||
99 | }; | ||
100 | |||
101 | struct 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 | */ | ||
139 | static void | ||
140 | vmwgfx_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 | |||
183 | static void | ||
184 | stop_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 | |||
215 | static int | ||
216 | set_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 | |||
260 | static int | ||
261 | get_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 | |||
280 | static void | ||
281 | query_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 | |||
296 | static int | ||
297 | check_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 | |||
354 | static int | ||
355 | query_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 | |||
406 | static int | ||
407 | copy_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, ®, &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, ®, &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, ®, buf, w, handle, 1) != 0) { | ||
548 | ret = BadAlloc; | ||
549 | break; | ||
550 | } | ||
551 | } | ||
552 | REGION_UNINIT(pScrn->pScreen, ®); | ||
553 | } | ||
554 | |||
555 | return ret; | ||
556 | } | ||
557 | |||
558 | |||
559 | static int | ||
560 | display_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, ®); | ||
573 | |||
574 | if (!vmwgfx_hw_accel_validate(pPixmap, 0, XA_FLAG_RENDER_TARGET, 0, ®)) | ||
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, ®); | ||
626 | return ret; | ||
627 | } | ||
628 | |||
629 | static int | ||
630 | put_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 | |||
686 | static struct xorg_xv_port_priv * | ||
687 | port_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 | |||
716 | static void | ||
717 | vmwgfx_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 | |||
732 | static XF86VideoAdaptorPtr | ||
733 | xorg_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 | |||
799 | void | ||
800 | xorg_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 | |||
43 | struct 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 | |||
53 | static 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 | |||
69 | static const unsigned int vmwgfx_op_map_size = | ||
70 | sizeof(vmwgfx_op_map) / sizeof(enum xa_composite_op); | ||
71 | |||
72 | static Bool | ||
73 | vmwgfx_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 | |||
93 | static enum xa_composite_wrap | ||
94 | vmwgfx_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 | |||
117 | static Bool | ||
118 | vmwgfx_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 | |||
139 | static Bool | ||
140 | vmwgfx_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 | |||
180 | struct xa_composite * | ||
181 | vmwgfx_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 | |||
214 | Bool | ||
215 | vmwgfx_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 | |||
229 | void | ||
230 | vmwgfx_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 | |||
252 | struct vmwgfx_composite * | ||
253 | vmwgfx_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 | |||
35 | static 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 | |||
43 | static 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 | */ | ||
50 | enum xa_formats | ||
51 | vmwgfx_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 | */ | ||
71 | static Bool | ||
72 | vmwgfx_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 | */ | ||
108 | static inline Bool | ||
109 | vmwgfx_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 | */ | ||
124 | Bool | ||
125 | vmwgfx_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 | */ | ||
159 | Bool | ||
160 | vmwgfx_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 | */ | ||
223 | static enum xa_formats | ||
224 | vmwgfx_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 | */ | ||
247 | Bool | ||
248 | vmwgfx_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 | */ | ||
291 | Bool | ||
292 | vmwgfx_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 | */ | ||
346 | Bool | ||
347 | vmwgfx_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 | */ | ||
362 | Bool | ||
363 | vmwgfx_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 | |||
15 | struct _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 | ||