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
)) {
97 modes
[num_modes
++] = mode
;
100 * give the caller a reference to this mode
107 RRModeFindByName(const char *name
, CARD16 nameLength
)
112 for (i
= 0; i
< num_modes
; i
++) {
114 if (mode
->mode
.nameLength
== nameLength
&&
115 !memcmp(name
, mode
->name
, nameLength
)) {
123 RRModeGet(xRRModeInfo
* modeInfo
, const char *name
)
127 for (i
= 0; i
< num_modes
; i
++) {
128 RRModePtr mode
= modes
[i
];
130 if (RRModeEqual(&mode
->mode
, modeInfo
) &&
131 !memcmp(name
, mode
->name
, modeInfo
->nameLength
)) {
137 return RRModeCreate(modeInfo
, name
, NULL
);
141 RRModeCreateUser(ScreenPtr pScreen
,
142 xRRModeInfo
* modeInfo
, const char *name
, int *error
)
146 mode
= RRModeFindByName(name
, modeInfo
->nameLength
);
152 mode
= RRModeCreate(modeInfo
, name
, pScreen
);
162 RRModesForScreen(ScreenPtr pScreen
, int *num_ret
)
166 RRModePtr
*screen_modes
;
167 int num_screen_modes
= 0;
169 screen_modes
= malloc((num_modes
? num_modes
: 1) * sizeof(RRModePtr
));
174 * Add modes from all outputs
176 for (o
= 0; o
< pScrPriv
->numOutputs
; o
++) {
177 RROutputPtr output
= pScrPriv
->outputs
[o
];
180 for (m
= 0; m
< output
->numModes
+ output
->numUserModes
; m
++) {
181 RRModePtr mode
= (m
< output
->numModes
?
183 output
->userModes
[m
- output
->numModes
]);
184 for (n
= 0; n
< num_screen_modes
; n
++)
185 if (screen_modes
[n
] == mode
)
187 if (n
== num_screen_modes
)
188 screen_modes
[num_screen_modes
++] = mode
;
192 * Add modes from all crtcs. The goal is to
193 * make sure all available and active modes
194 * are visible to the client
196 for (c
= 0; c
< pScrPriv
->numCrtcs
; c
++) {
197 RRCrtcPtr crtc
= pScrPriv
->crtcs
[c
];
198 RRModePtr mode
= crtc
->mode
;
203 for (n
= 0; n
< num_screen_modes
; n
++)
204 if (screen_modes
[n
] == mode
)
206 if (n
== num_screen_modes
)
207 screen_modes
[num_screen_modes
++] = mode
;
210 * Add all user modes for this screen
212 for (m
= 0; m
< num_modes
; m
++) {
213 RRModePtr mode
= modes
[m
];
216 if (mode
->userScreen
!= pScreen
)
218 for (n
= 0; n
< num_screen_modes
; n
++)
219 if (screen_modes
[n
] == mode
)
221 if (n
== num_screen_modes
)
222 screen_modes
[num_screen_modes
++] = mode
;
225 *num_ret
= num_screen_modes
;
230 RRModeDestroy(RRModePtr mode
)
234 if (--mode
->refcnt
> 0)
236 for (m
= 0; m
< num_modes
; m
++) {
237 if (modes
[m
] == mode
) {
238 memmove(modes
+ m
, modes
+ m
+ 1,
239 (num_modes
- m
- 1) * sizeof(RRModePtr
));
253 RRModeDestroyResource(pointer value
, XID pid
)
255 RRModeDestroy((RRModePtr
) value
);
260 * Initialize mode type
265 assert(num_modes
== 0);
266 assert(modes
== NULL
);
267 RRModeType
= CreateNewResourceType(RRModeDestroyResource
, "MODE");
275 * Initialize mode type error value
278 RRModeInitErrorValue(void)
280 SetResourceTypeErrorValue(RRModeType
, RRErrorBase
+ BadRRMode
);
284 ProcRRCreateMode(ClientPtr client
)
286 REQUEST(xRRCreateModeReq
);
287 xRRCreateModeReply rep
;
290 xRRModeInfo
*modeInfo
;
296 REQUEST_AT_LEAST_SIZE(xRRCreateModeReq
);
297 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
301 pScreen
= pWin
->drawable
.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
);
315 rep
= (xRRCreateModeReply
) {
317 .sequenceNumber
= client
->sequence
,
319 .mode
= mode
->mode
.id
321 if (client
->swapped
) {
322 swaps(&rep
.sequenceNumber
);
326 WriteToClient(client
, sizeof(xRRCreateModeReply
), &rep
);
327 /* Drop out reference to this mode */
333 ProcRRDestroyMode(ClientPtr client
)
335 REQUEST(xRRDestroyModeReq
);
338 REQUEST_SIZE_MATCH(xRRDestroyModeReq
);
339 VERIFY_RR_MODE(stuff
->mode
, mode
, DixDestroyAccess
);
341 if (!mode
->userScreen
)
343 if (mode
->refcnt
> 1)
345 FreeResource(stuff
->mode
, 0);
350 ProcRRAddOutputMode(ClientPtr client
)
352 REQUEST(xRRAddOutputModeReq
);
356 REQUEST_SIZE_MATCH(xRRAddOutputModeReq
);
357 VERIFY_RR_OUTPUT(stuff
->output
, output
, DixReadAccess
);
358 VERIFY_RR_MODE(stuff
->mode
, mode
, DixUseAccess
);
360 return RROutputAddUserMode(output
, mode
);
364 ProcRRDeleteOutputMode(ClientPtr client
)
366 REQUEST(xRRDeleteOutputModeReq
);
370 REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq
);
371 VERIFY_RR_OUTPUT(stuff
->output
, output
, DixReadAccess
);
372 VERIFY_RR_MODE(stuff
->mode
, mode
, DixUseAccess
);
374 return RROutputDeleteUserMode(output
, mode
);