Merge remote branch 'origin/master' into lp-setup-llvm
[mesa.git] / src / gallium / targets / xorg-vmwgfx / vmw_ctrl.c
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 * 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 "vmw_driver.h"
42 #include "vmwarectrlproto.h"
43
44 #include "xf86drm.h"
45
46
47 /*
48 *----------------------------------------------------------------------------
49 *
50 * VMwareCtrlQueryVersion --
51 *
52 * Implementation of QueryVersion command handler. Initialises and
53 * sends a reply.
54 *
55 * Results:
56 * Standard response codes.
57 *
58 * Side effects:
59 * Writes reply to client
60 *
61 *----------------------------------------------------------------------------
62 */
63
64 static int
65 VMwareCtrlQueryVersion(ClientPtr client)
66 {
67 xVMwareCtrlQueryVersionReply rep = { 0, };
68 register int n;
69
70 REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
71
72 rep.type = X_Reply;
73 rep.length = 0;
74 rep.sequenceNumber = client->sequence;
75 rep.majorVersion = VMWARE_CTRL_MAJOR_VERSION;
76 rep.minorVersion = VMWARE_CTRL_MINOR_VERSION;
77 if (client->swapped) {
78 swaps(&rep.sequenceNumber, n);
79 swapl(&rep.length, n);
80 swapl(&rep.majorVersion, n);
81 swapl(&rep.minorVersion, n);
82 }
83 WriteToClient(client, sizeof(xVMwareCtrlQueryVersionReply), (char *)&rep);
84
85 return client->noClientException;
86 }
87
88
89 /*
90 *----------------------------------------------------------------------------
91 *
92 * VMwareCtrlDoSetRes --
93 *
94 * Set the custom resolution into the mode list.
95 *
96 * This is done by alternately updating one of two dynamic modes. It is
97 * done this way because the server gets upset if you try to switch
98 * to a new resolution that has the same index as the current one.
99 *
100 * Results:
101 * TRUE on success, FALSE otherwise.
102 *
103 * Side effects:
104 * One dynamic mode will be updated if successful.
105 *
106 *----------------------------------------------------------------------------
107 */
108
109 static Bool
110 VMwareCtrlDoSetRes(ScrnInfoPtr pScrn,
111 CARD32 x,
112 CARD32 y)
113 {
114 struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn));
115 struct vmw_rect rect;
116 rect.x = 0;
117 rect.y = 0;
118 rect.w = x;
119 rect.h = y;
120
121 vmw_ioctl_update_layout(vmw, 1, &rect);
122
123 return TRUE;
124 }
125
126
127 /*
128 *----------------------------------------------------------------------------
129 *
130 * VMwareCtrlSetRes --
131 *
132 * Implementation of SetRes command handler. Initialises and sends a
133 * reply.
134 *
135 * Results:
136 * Standard response codes.
137 *
138 * Side effects:
139 * Writes reply to client
140 *
141 *----------------------------------------------------------------------------
142 */
143
144 static int
145 VMwareCtrlSetRes(ClientPtr client)
146 {
147 REQUEST(xVMwareCtrlSetResReq);
148 xVMwareCtrlSetResReply rep = { 0, };
149 ScrnInfoPtr pScrn;
150 ExtensionEntry *ext;
151 register int n;
152
153 REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq);
154
155 if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
156 return BadMatch;
157 }
158
159 pScrn = ext->extPrivate;
160 if (pScrn->scrnIndex != stuff->screen) {
161 return BadMatch;
162 }
163
164 if (!VMwareCtrlDoSetRes(pScrn, stuff->x, stuff->y)) {
165 return BadValue;
166 }
167
168 rep.type = X_Reply;
169 rep.length = (sizeof(xVMwareCtrlSetResReply) - sizeof(xGenericReply)) >> 2;
170 rep.sequenceNumber = client->sequence;
171 rep.screen = stuff->screen;
172 rep.x = stuff->x;
173 rep.y = stuff->y;
174 if (client->swapped) {
175 swaps(&rep.sequenceNumber, n);
176 swapl(&rep.length, n);
177 swapl(&rep.screen, n);
178 swapl(&rep.x, n);
179 swapl(&rep.y, n);
180 }
181 WriteToClient(client, sizeof(xVMwareCtrlSetResReply), (char *)&rep);
182
183 return client->noClientException;
184 }
185
186
187 /*
188 *----------------------------------------------------------------------------
189 *
190 * VMwareCtrlDoSetTopology --
191 *
192 * Set the custom topology and set a dynamic mode to the bounding box
193 * of the passed topology. If a topology is already pending, then do
194 * nothing but do not return failure.
195 *
196 * Results:
197 * TRUE on success, FALSE otherwise.
198 *
199 * Side effects:
200 * One dynamic mode and the pending xinerama state will be updated if
201 * successful.
202 *
203 *----------------------------------------------------------------------------
204 */
205
206 static Bool
207 VMwareCtrlDoSetTopology(ScrnInfoPtr pScrn,
208 xXineramaScreenInfo *extents,
209 unsigned long number)
210 {
211 struct vmw_rect *rects;
212 struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn));
213 int i;
214
215 rects = xcalloc(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 vmw_ioctl_update_layout(vmw, number, rects);
227
228 xfree(rects);
229 return TRUE;
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(struct vmw_customizer *vmw)
499 {
500 ExtensionEntry *myext;
501 ScrnInfoPtr pScrn = vmw->pScrn;
502
503 if (!(myext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
504 if (!(myext = AddExtension(VMWARE_CTRL_PROTOCOL_NAME, 0, 0,
505 VMwareCtrlDispatch,
506 SVMwareCtrlDispatch,
507 VMwareCtrlResetProc,
508 StandardMinorOpcode))) {
509 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
510 "Failed to add VMWARE_CTRL extension\n");
511 return;
512 }
513
514 /*
515 * For now, only support one screen as that's all the virtual
516 * hardware supports.
517 */
518 myext->extPrivate = pScrn;
519
520 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
521 "Initialized VMWARE_CTRL extension version %d.%d\n",
522 VMWARE_CTRL_MAJOR_VERSION, VMWARE_CTRL_MINOR_VERSION);
523 }
524 }