Tizen 2.0 Release
[profile/ivi/osmesa.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 = 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    vmw_ioctl_update_layout(vmw, number, rects);
227
228    free(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 }