Merge remote branch 'origin/master' into glsl2
[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 "dixstruct.h"
36 #include "extnsionst.h"
37 #include <X11/X.h>
38 #include <X11/extensions/panoramiXproto.h>
39
40 #include "vmw_driver.h"
41 #include "vmwarectrlproto.h"
42
43 #include "xf86drm.h"
44
45
46 /*
47 *----------------------------------------------------------------------------
48 *
49 * VMwareCtrlQueryVersion --
50 *
51 * Implementation of QueryVersion command handler. Initialises and
52 * sends a reply.
53 *
54 * Results:
55 * Standard response codes.
56 *
57 * Side effects:
58 * Writes reply to client
59 *
60 *----------------------------------------------------------------------------
61 */
62
63 static int
64 VMwareCtrlQueryVersion(ClientPtr client)
65 {
66 xVMwareCtrlQueryVersionReply rep = { 0, };
67 register int n;
68
69 REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
70
71 rep.type = X_Reply;
72 rep.length = 0;
73 rep.sequenceNumber = client->sequence;
74 rep.majorVersion = VMWARE_CTRL_MAJOR_VERSION;
75 rep.minorVersion = VMWARE_CTRL_MINOR_VERSION;
76 if (client->swapped) {
77 swaps(&rep.sequenceNumber, n);
78 swapl(&rep.length, n);
79 swapl(&rep.majorVersion, n);
80 swapl(&rep.minorVersion, n);
81 }
82 WriteToClient(client, sizeof(xVMwareCtrlQueryVersionReply), (char *)&rep);
83
84 return client->noClientException;
85 }
86
87
88 /*
89 *----------------------------------------------------------------------------
90 *
91 * VMwareCtrlDoSetRes --
92 *
93 * Set the custom resolution into the mode list.
94 *
95 * This is done by alternately updating one of two dynamic modes. It is
96 * done this way because the server gets upset if you try to switch
97 * to a new resolution that has the same index as the current one.
98 *
99 * Results:
100 * TRUE on success, FALSE otherwise.
101 *
102 * Side effects:
103 * One dynamic mode will be updated if successful.
104 *
105 *----------------------------------------------------------------------------
106 */
107
108 static Bool
109 VMwareCtrlDoSetRes(ScrnInfoPtr pScrn,
110 CARD32 x,
111 CARD32 y)
112 {
113 struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn));
114 struct vmw_rect rect;
115 rect.x = 0;
116 rect.y = 0;
117 rect.w = x;
118 rect.h = y;
119
120 vmw_ioctl_update_layout(vmw, 1, &rect);
121
122 return TRUE;
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 struct vmw_rect *rects;
211 struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn));
212 int i;
213
214 rects = xcalloc(number, sizeof(*rects));
215 if (!rects)
216 return FALSE;
217
218 for (i = 0; i < number; i++) {
219 rects[i].x = extents[i].x_org;
220 rects[i].y = extents[i].y_org;
221 rects[i].w = extents[i].width;
222 rects[i].h = extents[i].height;
223 }
224
225 vmw_ioctl_update_layout(vmw, number, rects);
226
227 xfree(rects);
228 return TRUE;
229 }
230
231
232 /*
233 *----------------------------------------------------------------------------
234 *
235 * VMwareCtrlSetTopology --
236 *
237 * Implementation of SetTopology command handler. Initialises and sends a
238 * reply.
239 *
240 * Results:
241 * Standard response codes.
242 *
243 * Side effects:
244 * Writes reply to client
245 *
246 *----------------------------------------------------------------------------
247 */
248
249 static int
250 VMwareCtrlSetTopology(ClientPtr client)
251 {
252 REQUEST(xVMwareCtrlSetTopologyReq);
253 xVMwareCtrlSetTopologyReply rep = { 0, };
254 ScrnInfoPtr pScrn;
255 ExtensionEntry *ext;
256 register int n;
257 xXineramaScreenInfo *extents;
258
259 REQUEST_AT_LEAST_SIZE(xVMwareCtrlSetTopologyReq);
260
261 if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
262 return BadMatch;
263 }
264
265 pScrn = ext->extPrivate;
266 if (pScrn->scrnIndex != stuff->screen) {
267 return BadMatch;
268 }
269
270 extents = (xXineramaScreenInfo *)(stuff + 1);
271 if (!VMwareCtrlDoSetTopology(pScrn, extents, stuff->number)) {
272 return BadValue;
273 }
274
275 rep.type = X_Reply;
276 rep.length = (sizeof(xVMwareCtrlSetTopologyReply) - sizeof(xGenericReply)) >> 2;
277 rep.sequenceNumber = client->sequence;
278 rep.screen = stuff->screen;
279 if (client->swapped) {
280 swaps(&rep.sequenceNumber, n);
281 swapl(&rep.length, n);
282 swapl(&rep.screen, n);
283 }
284 WriteToClient(client, sizeof(xVMwareCtrlSetTopologyReply), (char *)&rep);
285
286 return client->noClientException;
287 }
288
289
290 /*
291 *----------------------------------------------------------------------------
292 *
293 * VMwareCtrlDispatch --
294 *
295 * Dispatcher for VMWARE_CTRL commands. Calls the correct handler for
296 * each command type.
297 *
298 * Results:
299 * Standard response codes.
300 *
301 * Side effects:
302 * Side effects of individual command handlers.
303 *
304 *----------------------------------------------------------------------------
305 */
306
307 static int
308 VMwareCtrlDispatch(ClientPtr client)
309 {
310 REQUEST(xReq);
311
312 switch(stuff->data) {
313 case X_VMwareCtrlQueryVersion:
314 return VMwareCtrlQueryVersion(client);
315 case X_VMwareCtrlSetRes:
316 return VMwareCtrlSetRes(client);
317 case X_VMwareCtrlSetTopology:
318 return VMwareCtrlSetTopology(client);
319 }
320 return BadRequest;
321 }
322
323
324 /*
325 *----------------------------------------------------------------------------
326 *
327 * SVMwareCtrlQueryVersion --
328 *
329 * Wrapper for QueryVersion handler that handles input from other-endian
330 * clients.
331 *
332 * Results:
333 * Standard response codes.
334 *
335 * Side effects:
336 * Side effects of unswapped implementation.
337 *
338 *----------------------------------------------------------------------------
339 */
340
341 static int
342 SVMwareCtrlQueryVersion(ClientPtr client)
343 {
344 register int n;
345
346 REQUEST(xVMwareCtrlQueryVersionReq);
347 REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
348
349 swaps(&stuff->length, n);
350
351 return VMwareCtrlQueryVersion(client);
352 }
353
354
355 /*
356 *----------------------------------------------------------------------------
357 *
358 * SVMwareCtrlSetRes --
359 *
360 * Wrapper for SetRes handler that handles input from other-endian
361 * clients.
362 *
363 * Results:
364 * Standard response codes.
365 *
366 * Side effects:
367 * Side effects of unswapped implementation.
368 *
369 *----------------------------------------------------------------------------
370 */
371
372 static int
373 SVMwareCtrlSetRes(ClientPtr client)
374 {
375 register int n;
376
377 REQUEST(xVMwareCtrlSetResReq);
378 REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq);
379
380 swaps(&stuff->length, n);
381 swapl(&stuff->screen, n);
382 swapl(&stuff->x, n);
383 swapl(&stuff->y, n);
384
385 return VMwareCtrlSetRes(client);
386 }
387
388
389 /*
390 *----------------------------------------------------------------------------
391 *
392 * SVMwareCtrlSetTopology --
393 *
394 * Wrapper for SetTopology handler that handles input from other-endian
395 * clients.
396 *
397 * Results:
398 * Standard response codes.
399 *
400 * Side effects:
401 * Side effects of unswapped implementation.
402 *
403 *----------------------------------------------------------------------------
404 */
405
406 static int
407 SVMwareCtrlSetTopology(ClientPtr client)
408 {
409 register int n;
410
411 REQUEST(xVMwareCtrlSetTopologyReq);
412 REQUEST_SIZE_MATCH(xVMwareCtrlSetTopologyReq);
413
414 swaps(&stuff->length, n);
415 swapl(&stuff->screen, n);
416 swapl(&stuff->number, n);
417 /* Each extent is a struct of shorts. */
418 SwapRestS(stuff);
419
420 return VMwareCtrlSetTopology(client);
421 }
422
423
424 /*
425 *----------------------------------------------------------------------------
426 *
427 * SVMwareCtrlDispatch --
428 *
429 * Wrapper for dispatcher that handles input from other-endian clients.
430 *
431 * Results:
432 * Standard response codes.
433 *
434 * Side effects:
435 * Side effects of individual command handlers.
436 *
437 *----------------------------------------------------------------------------
438 */
439
440 static int
441 SVMwareCtrlDispatch(ClientPtr client)
442 {
443 REQUEST(xReq);
444
445 switch(stuff->data) {
446 case X_VMwareCtrlQueryVersion:
447 return SVMwareCtrlQueryVersion(client);
448 case X_VMwareCtrlSetRes:
449 return SVMwareCtrlSetRes(client);
450 case X_VMwareCtrlSetTopology:
451 return SVMwareCtrlSetTopology(client);
452 }
453 return BadRequest;
454 }
455
456
457 /*
458 *----------------------------------------------------------------------------
459 *
460 * VMwareCtrlResetProc --
461 *
462 * Cleanup handler called when the extension is removed.
463 *
464 * Results:
465 * None
466 *
467 * Side effects:
468 * None
469 *
470 *----------------------------------------------------------------------------
471 */
472
473 static void
474 VMwareCtrlResetProc(ExtensionEntry* extEntry)
475 {
476 /* Currently, no cleanup is necessary. */
477 }
478
479
480 /*
481 *----------------------------------------------------------------------------
482 *
483 * VMwareCtrl_ExitInit --
484 *
485 * Initialiser for the VMWARE_CTRL protocol extension.
486 *
487 * Results:
488 * None.
489 *
490 * Side effects:
491 * Protocol extension will be registered if successful.
492 *
493 *----------------------------------------------------------------------------
494 */
495
496 void
497 vmw_ctrl_ext_init(struct vmw_customizer *vmw)
498 {
499 ExtensionEntry *myext;
500 ScrnInfoPtr pScrn = vmw->pScrn;
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 }