Merge branch 'glsl2-head' 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
36 #define NEED_REPLIES
37 #define NEED_EVENTS
38 #include "dixstruct.h"
39 #include "extnsionst.h"
40 #include <X11/X.h>
41 #include <X11/extensions/panoramiXproto.h>
42
43 #include "vmw_driver.h"
44 #include "vmwarectrlproto.h"
45
46 #include "xf86drm.h"
47
48
49 /*
50 *----------------------------------------------------------------------------
51 *
52 * VMwareCtrlQueryVersion --
53 *
54 * Implementation of QueryVersion command handler. Initialises and
55 * sends a reply.
56 *
57 * Results:
58 * Standard response codes.
59 *
60 * Side effects:
61 * Writes reply to client
62 *
63 *----------------------------------------------------------------------------
64 */
65
66 static int
67 VMwareCtrlQueryVersion(ClientPtr client)
68 {
69 xVMwareCtrlQueryVersionReply rep = { 0, };
70 register int n;
71
72 REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
73
74 rep.type = X_Reply;
75 rep.length = 0;
76 rep.sequenceNumber = client->sequence;
77 rep.majorVersion = VMWARE_CTRL_MAJOR_VERSION;
78 rep.minorVersion = VMWARE_CTRL_MINOR_VERSION;
79 if (client->swapped) {
80 swaps(&rep.sequenceNumber, n);
81 swapl(&rep.length, n);
82 swapl(&rep.majorVersion, n);
83 swapl(&rep.minorVersion, n);
84 }
85 WriteToClient(client, sizeof(xVMwareCtrlQueryVersionReply), (char *)&rep);
86
87 return client->noClientException;
88 }
89
90
91 /*
92 *----------------------------------------------------------------------------
93 *
94 * VMwareCtrlDoSetRes --
95 *
96 * Set the custom resolution into the mode list.
97 *
98 * This is done by alternately updating one of two dynamic modes. It is
99 * done this way because the server gets upset if you try to switch
100 * to a new resolution that has the same index as the current one.
101 *
102 * Results:
103 * TRUE on success, FALSE otherwise.
104 *
105 * Side effects:
106 * One dynamic mode will be updated if successful.
107 *
108 *----------------------------------------------------------------------------
109 */
110
111 static Bool
112 VMwareCtrlDoSetRes(ScrnInfoPtr pScrn,
113 CARD32 x,
114 CARD32 y)
115 {
116 struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn));
117 struct vmw_rect rect;
118 rect.x = 0;
119 rect.y = 0;
120 rect.w = x;
121 rect.h = y;
122
123 vmw_ioctl_update_layout(vmw, 1, &rect);
124
125 return TRUE;
126 }
127
128
129 /*
130 *----------------------------------------------------------------------------
131 *
132 * VMwareCtrlSetRes --
133 *
134 * Implementation of SetRes command handler. Initialises and sends a
135 * reply.
136 *
137 * Results:
138 * Standard response codes.
139 *
140 * Side effects:
141 * Writes reply to client
142 *
143 *----------------------------------------------------------------------------
144 */
145
146 static int
147 VMwareCtrlSetRes(ClientPtr client)
148 {
149 REQUEST(xVMwareCtrlSetResReq);
150 xVMwareCtrlSetResReply rep = { 0, };
151 ScrnInfoPtr pScrn;
152 ExtensionEntry *ext;
153 register int n;
154
155 REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq);
156
157 if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
158 return BadMatch;
159 }
160
161 pScrn = ext->extPrivate;
162 if (pScrn->scrnIndex != stuff->screen) {
163 return BadMatch;
164 }
165
166 if (!VMwareCtrlDoSetRes(pScrn, stuff->x, stuff->y)) {
167 return BadValue;
168 }
169
170 rep.type = X_Reply;
171 rep.length = (sizeof(xVMwareCtrlSetResReply) - sizeof(xGenericReply)) >> 2;
172 rep.sequenceNumber = client->sequence;
173 rep.screen = stuff->screen;
174 rep.x = stuff->x;
175 rep.y = stuff->y;
176 if (client->swapped) {
177 swaps(&rep.sequenceNumber, n);
178 swapl(&rep.length, n);
179 swapl(&rep.screen, n);
180 swapl(&rep.x, n);
181 swapl(&rep.y, n);
182 }
183 WriteToClient(client, sizeof(xVMwareCtrlSetResReply), (char *)&rep);
184
185 return client->noClientException;
186 }
187
188
189 /*
190 *----------------------------------------------------------------------------
191 *
192 * VMwareCtrlDoSetTopology --
193 *
194 * Set the custom topology and set a dynamic mode to the bounding box
195 * of the passed topology. If a topology is already pending, then do
196 * nothing but do not return failure.
197 *
198 * Results:
199 * TRUE on success, FALSE otherwise.
200 *
201 * Side effects:
202 * One dynamic mode and the pending xinerama state will be updated if
203 * successful.
204 *
205 *----------------------------------------------------------------------------
206 */
207
208 static Bool
209 VMwareCtrlDoSetTopology(ScrnInfoPtr pScrn,
210 xXineramaScreenInfo *extents,
211 unsigned long number)
212 {
213 struct vmw_rect *rects;
214 struct vmw_customizer *vmw = vmw_customizer(xorg_customizer(pScrn));
215 int i;
216
217 rects = xcalloc(number, sizeof(*rects));
218 if (!rects)
219 return FALSE;
220
221 for (i = 0; i < number; i++) {
222 rects[i].x = extents[i].x_org;
223 rects[i].y = extents[i].y_org;
224 rects[i].w = extents[i].width;
225 rects[i].h = extents[i].height;
226 }
227
228 vmw_ioctl_update_layout(vmw, number, rects);
229
230 xfree(rects);
231 return TRUE;
232 }
233
234
235 /*
236 *----------------------------------------------------------------------------
237 *
238 * VMwareCtrlSetTopology --
239 *
240 * Implementation of SetTopology command handler. Initialises and sends a
241 * reply.
242 *
243 * Results:
244 * Standard response codes.
245 *
246 * Side effects:
247 * Writes reply to client
248 *
249 *----------------------------------------------------------------------------
250 */
251
252 static int
253 VMwareCtrlSetTopology(ClientPtr client)
254 {
255 REQUEST(xVMwareCtrlSetTopologyReq);
256 xVMwareCtrlSetTopologyReply rep = { 0, };
257 ScrnInfoPtr pScrn;
258 ExtensionEntry *ext;
259 register int n;
260 xXineramaScreenInfo *extents;
261
262 REQUEST_AT_LEAST_SIZE(xVMwareCtrlSetTopologyReq);
263
264 if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
265 return BadMatch;
266 }
267
268 pScrn = ext->extPrivate;
269 if (pScrn->scrnIndex != stuff->screen) {
270 return BadMatch;
271 }
272
273 extents = (xXineramaScreenInfo *)(stuff + 1);
274 if (!VMwareCtrlDoSetTopology(pScrn, extents, stuff->number)) {
275 return BadValue;
276 }
277
278 rep.type = X_Reply;
279 rep.length = (sizeof(xVMwareCtrlSetTopologyReply) - sizeof(xGenericReply)) >> 2;
280 rep.sequenceNumber = client->sequence;
281 rep.screen = stuff->screen;
282 if (client->swapped) {
283 swaps(&rep.sequenceNumber, n);
284 swapl(&rep.length, n);
285 swapl(&rep.screen, n);
286 }
287 WriteToClient(client, sizeof(xVMwareCtrlSetTopologyReply), (char *)&rep);
288
289 return client->noClientException;
290 }
291
292
293 /*
294 *----------------------------------------------------------------------------
295 *
296 * VMwareCtrlDispatch --
297 *
298 * Dispatcher for VMWARE_CTRL commands. Calls the correct handler for
299 * each command type.
300 *
301 * Results:
302 * Standard response codes.
303 *
304 * Side effects:
305 * Side effects of individual command handlers.
306 *
307 *----------------------------------------------------------------------------
308 */
309
310 static int
311 VMwareCtrlDispatch(ClientPtr client)
312 {
313 REQUEST(xReq);
314
315 switch(stuff->data) {
316 case X_VMwareCtrlQueryVersion:
317 return VMwareCtrlQueryVersion(client);
318 case X_VMwareCtrlSetRes:
319 return VMwareCtrlSetRes(client);
320 case X_VMwareCtrlSetTopology:
321 return VMwareCtrlSetTopology(client);
322 }
323 return BadRequest;
324 }
325
326
327 /*
328 *----------------------------------------------------------------------------
329 *
330 * SVMwareCtrlQueryVersion --
331 *
332 * Wrapper for QueryVersion handler that handles input from other-endian
333 * clients.
334 *
335 * Results:
336 * Standard response codes.
337 *
338 * Side effects:
339 * Side effects of unswapped implementation.
340 *
341 *----------------------------------------------------------------------------
342 */
343
344 static int
345 SVMwareCtrlQueryVersion(ClientPtr client)
346 {
347 register int n;
348
349 REQUEST(xVMwareCtrlQueryVersionReq);
350 REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
351
352 swaps(&stuff->length, n);
353
354 return VMwareCtrlQueryVersion(client);
355 }
356
357
358 /*
359 *----------------------------------------------------------------------------
360 *
361 * SVMwareCtrlSetRes --
362 *
363 * Wrapper for SetRes handler that handles input from other-endian
364 * clients.
365 *
366 * Results:
367 * Standard response codes.
368 *
369 * Side effects:
370 * Side effects of unswapped implementation.
371 *
372 *----------------------------------------------------------------------------
373 */
374
375 static int
376 SVMwareCtrlSetRes(ClientPtr client)
377 {
378 register int n;
379
380 REQUEST(xVMwareCtrlSetResReq);
381 REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq);
382
383 swaps(&stuff->length, n);
384 swapl(&stuff->screen, n);
385 swapl(&stuff->x, n);
386 swapl(&stuff->y, n);
387
388 return VMwareCtrlSetRes(client);
389 }
390
391
392 /*
393 *----------------------------------------------------------------------------
394 *
395 * SVMwareCtrlSetTopology --
396 *
397 * Wrapper for SetTopology handler that handles input from other-endian
398 * clients.
399 *
400 * Results:
401 * Standard response codes.
402 *
403 * Side effects:
404 * Side effects of unswapped implementation.
405 *
406 *----------------------------------------------------------------------------
407 */
408
409 static int
410 SVMwareCtrlSetTopology(ClientPtr client)
411 {
412 register int n;
413
414 REQUEST(xVMwareCtrlSetTopologyReq);
415 REQUEST_SIZE_MATCH(xVMwareCtrlSetTopologyReq);
416
417 swaps(&stuff->length, n);
418 swapl(&stuff->screen, n);
419 swapl(&stuff->number, n);
420 /* Each extent is a struct of shorts. */
421 SwapRestS(stuff);
422
423 return VMwareCtrlSetTopology(client);
424 }
425
426
427 /*
428 *----------------------------------------------------------------------------
429 *
430 * SVMwareCtrlDispatch --
431 *
432 * Wrapper for dispatcher that handles input from other-endian clients.
433 *
434 * Results:
435 * Standard response codes.
436 *
437 * Side effects:
438 * Side effects of individual command handlers.
439 *
440 *----------------------------------------------------------------------------
441 */
442
443 static int
444 SVMwareCtrlDispatch(ClientPtr client)
445 {
446 REQUEST(xReq);
447
448 switch(stuff->data) {
449 case X_VMwareCtrlQueryVersion:
450 return SVMwareCtrlQueryVersion(client);
451 case X_VMwareCtrlSetRes:
452 return SVMwareCtrlSetRes(client);
453 case X_VMwareCtrlSetTopology:
454 return SVMwareCtrlSetTopology(client);
455 }
456 return BadRequest;
457 }
458
459
460 /*
461 *----------------------------------------------------------------------------
462 *
463 * VMwareCtrlResetProc --
464 *
465 * Cleanup handler called when the extension is removed.
466 *
467 * Results:
468 * None
469 *
470 * Side effects:
471 * None
472 *
473 *----------------------------------------------------------------------------
474 */
475
476 static void
477 VMwareCtrlResetProc(ExtensionEntry* extEntry)
478 {
479 /* Currently, no cleanup is necessary. */
480 }
481
482
483 /*
484 *----------------------------------------------------------------------------
485 *
486 * VMwareCtrl_ExitInit --
487 *
488 * Initialiser for the VMWARE_CTRL protocol extension.
489 *
490 * Results:
491 * None.
492 *
493 * Side effects:
494 * Protocol extension will be registered if successful.
495 *
496 *----------------------------------------------------------------------------
497 */
498
499 void
500 vmw_ctrl_ext_init(struct vmw_customizer *vmw)
501 {
502 ExtensionEntry *myext;
503 ScrnInfoPtr pScrn = vmw->pScrn;
504
505 if (!(myext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
506 if (!(myext = AddExtension(VMWARE_CTRL_PROTOCOL_NAME, 0, 0,
507 VMwareCtrlDispatch,
508 SVMwareCtrlDispatch,
509 VMwareCtrlResetProc,
510 StandardMinorOpcode))) {
511 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
512 "Failed to add VMWARE_CTRL extension\n");
513 return;
514 }
515
516 /*
517 * For now, only support one screen as that's all the virtual
518 * hardware supports.
519 */
520 myext->extPrivate = pScrn;
521
522 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
523 "Initialized VMWARE_CTRL extension version %d.%d\n",
524 VMWARE_CTRL_MAJOR_VERSION, VMWARE_CTRL_MINOR_VERSION);
525 }
526 }