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
28 RRModeEqual(xRRModeInfo
* a
, xRRModeInfo
* b
)
30 if (a
->width
!= b
->width
)
32 if (a
->height
!= b
->height
)
34 if (a
->dotClock
!= b
->dotClock
)
36 if (a
->hSyncStart
!= b
->hSyncStart
)
38 if (a
->hSyncEnd
!= b
->hSyncEnd
)
40 if (a
->hTotal
!= b
->hTotal
)
42 if (a
->hSkew
!= b
->hSkew
)
44 if (a
->vSyncStart
!= b
->vSyncStart
)
46 if (a
->vSyncEnd
!= b
->vSyncEnd
)
48 if (a
->vTotal
!= b
->vTotal
)
50 if (a
->nameLength
!= b
->nameLength
)
52 if (a
->modeFlags
!= b
->modeFlags
)
58 * Keep a list so it's easy to find modes in the resource database.
61 static RRModePtr
*modes
;
64 RRModeCreate(xRRModeInfo
* modeInfo
, const char *name
, ScreenPtr userScreen
)
66 RRModePtr mode
, *newModes
;
71 mode
= malloc(sizeof(RRModeRec
) + modeInfo
->nameLength
+ 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
;
82 newModes
= realloc(modes
, (num_modes
+ 1) * sizeof(RRModePtr
));
84 newModes
= malloc(sizeof(RRModePtr
));
91 mode
->mode
.id
= FakeClientID(0);
92 if (!AddResource(mode
->mode
.id
, RRModeType
, (pointer
) mode
))
95 modes
[num_modes
++] = mode
;
98 * give the caller a reference to this mode
105 RRModeFindByName(const char *name
, CARD16 nameLength
)
110 for (i
= 0; i
< num_modes
; i
++) {
112 if (mode
->mode
.nameLength
== nameLength
&&
113 !memcmp(name
, mode
->name
, nameLength
)) {
121 RRModeGet(xRRModeInfo
* modeInfo
, const char *name
)
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
)) {
135 return RRModeCreate(modeInfo
, name
, NULL
);
139 RRModeCreateUser(ScreenPtr pScreen
,
140 xRRModeInfo
* modeInfo
, const char *name
, int *error
)
144 mode
= RRModeFindByName(name
, modeInfo
->nameLength
);
150 mode
= RRModeCreate(modeInfo
, name
, pScreen
);
160 RRModesForScreen(ScreenPtr pScreen
, int *num_ret
)
164 RRModePtr
*screen_modes
;
165 int num_screen_modes
= 0;
167 screen_modes
= malloc((num_modes
? num_modes
: 1) * sizeof(RRModePtr
));
172 * Add modes from all outputs
174 for (o
= 0; o
< pScrPriv
->numOutputs
; o
++) {
175 RROutputPtr output
= pScrPriv
->outputs
[o
];
178 for (m
= 0; m
< output
->numModes
+ output
->numUserModes
; m
++) {
179 RRModePtr mode
= (m
< output
->numModes
?
181 output
->userModes
[m
- output
->numModes
]);
182 for (n
= 0; n
< num_screen_modes
; n
++)
183 if (screen_modes
[n
] == mode
)
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
;
201 for (n
= 0; n
< num_screen_modes
; n
++)
202 if (screen_modes
[n
] == mode
)
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
];
214 if (mode
->userScreen
!= pScreen
)
216 for (n
= 0; n
< num_screen_modes
; n
++)
217 if (screen_modes
[n
] == mode
)
219 if (n
== num_screen_modes
)
220 screen_modes
[num_screen_modes
++] = mode
;
223 *num_ret
= num_screen_modes
;
228 RRModeDestroy(RRModePtr mode
)
232 if (--mode
->refcnt
> 0)
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
));
251 RRModeDestroyResource(pointer value
, XID pid
)
253 RRModeDestroy((RRModePtr
) value
);
258 * Initialize mode type
263 assert(num_modes
== 0);
264 assert(modes
== NULL
);
265 RRModeType
= CreateNewResourceType(RRModeDestroyResource
, "MODE");
273 * Initialize mode type error value
276 RRModeInitErrorValue(void)
278 SetResourceTypeErrorValue(RRModeType
, RRErrorBase
+ BadRRMode
);
282 ProcRRCreateMode(ClientPtr client
)
284 REQUEST(xRRCreateModeReq
);
285 xRRCreateModeReply rep
= { 0 };
288 rrScrPrivPtr pScrPriv
;
289 xRRModeInfo
*modeInfo
;
295 REQUEST_AT_LEAST_SIZE(xRRCreateModeReq
);
296 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
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
)
311 mode
= RRModeCreateUser(pScreen
, modeInfo
, name
, &error
);
317 rep
.sequenceNumber
= client
->sequence
;
319 rep
.mode
= mode
->mode
.id
;
320 if (client
->swapped
) {
321 swaps(&rep
.sequenceNumber
);
325 WriteToClient(client
, sizeof(xRRCreateModeReply
), (char *) &rep
);
326 /* Drop out reference to this mode */
332 ProcRRDestroyMode(ClientPtr client
)
334 REQUEST(xRRDestroyModeReq
);
337 REQUEST_SIZE_MATCH(xRRDestroyModeReq
);
338 VERIFY_RR_MODE(stuff
->mode
, mode
, DixDestroyAccess
);
340 if (!mode
->userScreen
)
342 if (mode
->refcnt
> 1)
344 FreeResource(stuff
->mode
, 0);
349 ProcRRAddOutputMode(ClientPtr client
)
351 REQUEST(xRRAddOutputModeReq
);
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
);
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
);