hw/xwin/glx: Use silent rules
[xserver/hramrach.git] / randr / rrmode.c
blobb637c06b9b523f47e1a0bf2ad879a011c38443bb
1 /*
2 * Copyright © 2006 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
23 #include "randrstr.h"
25 RESTYPE RRModeType;
27 static Bool
28 RRModeEqual(xRRModeInfo * a, xRRModeInfo * b)
30 if (a->width != b->width)
31 return FALSE;
32 if (a->height != b->height)
33 return FALSE;
34 if (a->dotClock != b->dotClock)
35 return FALSE;
36 if (a->hSyncStart != b->hSyncStart)
37 return FALSE;
38 if (a->hSyncEnd != b->hSyncEnd)
39 return FALSE;
40 if (a->hTotal != b->hTotal)
41 return FALSE;
42 if (a->hSkew != b->hSkew)
43 return FALSE;
44 if (a->vSyncStart != b->vSyncStart)
45 return FALSE;
46 if (a->vSyncEnd != b->vSyncEnd)
47 return FALSE;
48 if (a->vTotal != b->vTotal)
49 return FALSE;
50 if (a->nameLength != b->nameLength)
51 return FALSE;
52 if (a->modeFlags != b->modeFlags)
53 return FALSE;
54 return TRUE;
58 * Keep a list so it's easy to find modes in the resource database.
60 static int num_modes;
61 static RRModePtr *modes;
63 static RRModePtr
64 RRModeCreate(xRRModeInfo * modeInfo, const char *name, ScreenPtr userScreen)
66 RRModePtr mode, *newModes;
68 if (!RRInit())
69 return NULL;
71 mode = malloc(sizeof(RRModeRec) + modeInfo->nameLength + 1);
72 if (!mode)
73 return NULL;
74 mode->refcnt = 1;
75 mode->mode = *modeInfo;
76 mode->name = (char *) (mode + 1);
77 memcpy(mode->name, name, modeInfo->nameLength);
78 mode->name[modeInfo->nameLength] = '\0';
79 mode->userScreen = userScreen;
81 if (num_modes)
82 newModes = realloc(modes, (num_modes + 1) * sizeof(RRModePtr));
83 else
84 newModes = malloc(sizeof(RRModePtr));
86 if (!newModes) {
87 free(mode);
88 return NULL;
91 mode->mode.id = FakeClientID(0);
92 if (!AddResource(mode->mode.id, RRModeType, (pointer) mode))
93 return NULL;
94 modes = newModes;
95 modes[num_modes++] = mode;
98 * give the caller a reference to this mode
100 ++mode->refcnt;
101 return mode;
104 static RRModePtr
105 RRModeFindByName(const char *name, CARD16 nameLength)
107 int i;
108 RRModePtr mode;
110 for (i = 0; i < num_modes; i++) {
111 mode = modes[i];
112 if (mode->mode.nameLength == nameLength &&
113 !memcmp(name, mode->name, nameLength)) {
114 return mode;
117 return NULL;
120 RRModePtr
121 RRModeGet(xRRModeInfo * modeInfo, const char *name)
123 int i;
125 for (i = 0; i < num_modes; i++) {
126 RRModePtr mode = modes[i];
128 if (RRModeEqual(&mode->mode, modeInfo) &&
129 !memcmp(name, mode->name, modeInfo->nameLength)) {
130 ++mode->refcnt;
131 return mode;
135 return RRModeCreate(modeInfo, name, NULL);
138 static RRModePtr
139 RRModeCreateUser(ScreenPtr pScreen,
140 xRRModeInfo * modeInfo, const char *name, int *error)
142 RRModePtr mode;
144 mode = RRModeFindByName(name, modeInfo->nameLength);
145 if (mode) {
146 *error = BadName;
147 return NULL;
150 mode = RRModeCreate(modeInfo, name, pScreen);
151 if (!mode) {
152 *error = BadAlloc;
153 return NULL;
155 *error = Success;
156 return mode;
159 RRModePtr *
160 RRModesForScreen(ScreenPtr pScreen, int *num_ret)
162 rrScrPriv(pScreen);
163 int o, c, m;
164 RRModePtr *screen_modes;
165 int num_screen_modes = 0;
167 screen_modes = malloc((num_modes ? num_modes : 1) * sizeof(RRModePtr));
168 if (!screen_modes)
169 return NULL;
172 * Add modes from all outputs
174 for (o = 0; o < pScrPriv->numOutputs; o++) {
175 RROutputPtr output = pScrPriv->outputs[o];
176 int m, n;
178 for (m = 0; m < output->numModes + output->numUserModes; m++) {
179 RRModePtr mode = (m < output->numModes ?
180 output->modes[m] :
181 output->userModes[m - output->numModes]);
182 for (n = 0; n < num_screen_modes; n++)
183 if (screen_modes[n] == mode)
184 break;
185 if (n == num_screen_modes)
186 screen_modes[num_screen_modes++] = mode;
190 * Add modes from all crtcs. The goal is to
191 * make sure all available and active modes
192 * are visible to the client
194 for (c = 0; c < pScrPriv->numCrtcs; c++) {
195 RRCrtcPtr crtc = pScrPriv->crtcs[c];
196 RRModePtr mode = crtc->mode;
197 int n;
199 if (!mode)
200 continue;
201 for (n = 0; n < num_screen_modes; n++)
202 if (screen_modes[n] == mode)
203 break;
204 if (n == num_screen_modes)
205 screen_modes[num_screen_modes++] = mode;
208 * Add all user modes for this screen
210 for (m = 0; m < num_modes; m++) {
211 RRModePtr mode = modes[m];
212 int n;
214 if (mode->userScreen != pScreen)
215 continue;
216 for (n = 0; n < num_screen_modes; n++)
217 if (screen_modes[n] == mode)
218 break;
219 if (n == num_screen_modes)
220 screen_modes[num_screen_modes++] = mode;
223 *num_ret = num_screen_modes;
224 return screen_modes;
227 void
228 RRModeDestroy(RRModePtr mode)
230 int m;
232 if (--mode->refcnt > 0)
233 return;
234 for (m = 0; m < num_modes; m++) {
235 if (modes[m] == mode) {
236 memmove(modes + m, modes + m + 1,
237 (num_modes - m - 1) * sizeof(RRModePtr));
238 num_modes--;
239 if (!num_modes) {
240 free(modes);
241 modes = NULL;
243 break;
247 free(mode);
250 static int
251 RRModeDestroyResource(pointer value, XID pid)
253 RRModeDestroy((RRModePtr) value);
254 return 1;
258 * Initialize mode type
260 Bool
261 RRModeInit(void)
263 assert(num_modes == 0);
264 assert(modes == NULL);
265 RRModeType = CreateNewResourceType(RRModeDestroyResource, "MODE");
266 if (!RRModeType)
267 return FALSE;
269 return TRUE;
273 * Initialize mode type error value
275 void
276 RRModeInitErrorValue(void)
278 SetResourceTypeErrorValue(RRModeType, RRErrorBase + BadRRMode);
282 ProcRRCreateMode(ClientPtr client)
284 REQUEST(xRRCreateModeReq);
285 xRRCreateModeReply rep = { 0 };
286 WindowPtr pWin;
287 ScreenPtr pScreen;
288 rrScrPrivPtr pScrPriv;
289 xRRModeInfo *modeInfo;
290 long units_after;
291 char *name;
292 int error, rc;
293 RRModePtr mode;
295 REQUEST_AT_LEAST_SIZE(xRRCreateModeReq);
296 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
297 if (rc != Success)
298 return rc;
300 pScreen = pWin->drawable.pScreen;
301 pScrPriv = rrGetScrPriv(pScreen);
303 modeInfo = &stuff->modeInfo;
304 name = (char *) (stuff + 1);
305 units_after = (stuff->length - bytes_to_int32(sizeof(xRRCreateModeReq)));
307 /* check to make sure requested name fits within the data provided */
308 if (bytes_to_int32(modeInfo->nameLength) > units_after)
309 return BadLength;
311 mode = RRModeCreateUser(pScreen, modeInfo, name, &error);
312 if (!mode)
313 return error;
315 rep.type = X_Reply;
316 rep.pad0 = 0;
317 rep.sequenceNumber = client->sequence;
318 rep.length = 0;
319 rep.mode = mode->mode.id;
320 if (client->swapped) {
321 swaps(&rep.sequenceNumber);
322 swapl(&rep.length);
323 swapl(&rep.mode);
325 WriteToClient(client, sizeof(xRRCreateModeReply), (char *) &rep);
326 /* Drop out reference to this mode */
327 RRModeDestroy(mode);
328 return Success;
332 ProcRRDestroyMode(ClientPtr client)
334 REQUEST(xRRDestroyModeReq);
335 RRModePtr mode;
337 REQUEST_SIZE_MATCH(xRRDestroyModeReq);
338 VERIFY_RR_MODE(stuff->mode, mode, DixDestroyAccess);
340 if (!mode->userScreen)
341 return BadMatch;
342 if (mode->refcnt > 1)
343 return BadAccess;
344 FreeResource(stuff->mode, 0);
345 return Success;
349 ProcRRAddOutputMode(ClientPtr client)
351 REQUEST(xRRAddOutputModeReq);
352 RRModePtr mode;
353 RROutputPtr output;
355 REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
356 VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
357 VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess);
359 return RROutputAddUserMode(output, mode);
363 ProcRRDeleteOutputMode(ClientPtr client)
365 REQUEST(xRRDeleteOutputModeReq);
366 RRModePtr mode;
367 RROutputPtr output;
369 REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
370 VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
371 VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess);
373 return RROutputDeleteUserMode(output, mode);