xref: /OK3568_Linux_fs/external/xserver/randr/rrmode.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2006 Keith Packard
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission to use, copy, modify, distribute, and sell this software and its
5*4882a593Smuzhiyun  * documentation for any purpose is hereby granted without fee, provided that
6*4882a593Smuzhiyun  * the above copyright notice appear in all copies and that both that copyright
7*4882a593Smuzhiyun  * notice and this permission notice appear in supporting documentation, and
8*4882a593Smuzhiyun  * that the name of the copyright holders not be used in advertising or
9*4882a593Smuzhiyun  * publicity pertaining to distribution of the software without specific,
10*4882a593Smuzhiyun  * written prior permission.  The copyright holders make no representations
11*4882a593Smuzhiyun  * about the suitability of this software for any purpose.  It is provided "as
12*4882a593Smuzhiyun  * is" without express or implied warranty.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15*4882a593Smuzhiyun  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16*4882a593Smuzhiyun  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17*4882a593Smuzhiyun  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18*4882a593Smuzhiyun  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19*4882a593Smuzhiyun  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20*4882a593Smuzhiyun  * OF THIS SOFTWARE.
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include "randrstr.h"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun RESTYPE RRModeType;
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun static Bool
RRModeEqual(xRRModeInfo * a,xRRModeInfo * b)28*4882a593Smuzhiyun RRModeEqual(xRRModeInfo * a, xRRModeInfo * b)
29*4882a593Smuzhiyun {
30*4882a593Smuzhiyun     if (a->width != b->width)
31*4882a593Smuzhiyun         return FALSE;
32*4882a593Smuzhiyun     if (a->height != b->height)
33*4882a593Smuzhiyun         return FALSE;
34*4882a593Smuzhiyun     if (a->dotClock != b->dotClock)
35*4882a593Smuzhiyun         return FALSE;
36*4882a593Smuzhiyun     if (a->hSyncStart != b->hSyncStart)
37*4882a593Smuzhiyun         return FALSE;
38*4882a593Smuzhiyun     if (a->hSyncEnd != b->hSyncEnd)
39*4882a593Smuzhiyun         return FALSE;
40*4882a593Smuzhiyun     if (a->hTotal != b->hTotal)
41*4882a593Smuzhiyun         return FALSE;
42*4882a593Smuzhiyun     if (a->hSkew != b->hSkew)
43*4882a593Smuzhiyun         return FALSE;
44*4882a593Smuzhiyun     if (a->vSyncStart != b->vSyncStart)
45*4882a593Smuzhiyun         return FALSE;
46*4882a593Smuzhiyun     if (a->vSyncEnd != b->vSyncEnd)
47*4882a593Smuzhiyun         return FALSE;
48*4882a593Smuzhiyun     if (a->vTotal != b->vTotal)
49*4882a593Smuzhiyun         return FALSE;
50*4882a593Smuzhiyun     if (a->nameLength != b->nameLength)
51*4882a593Smuzhiyun         return FALSE;
52*4882a593Smuzhiyun     if (a->modeFlags != b->modeFlags)
53*4882a593Smuzhiyun         return FALSE;
54*4882a593Smuzhiyun     return TRUE;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /*
58*4882a593Smuzhiyun  * Keep a list so it's easy to find modes in the resource database.
59*4882a593Smuzhiyun  */
60*4882a593Smuzhiyun static int num_modes;
61*4882a593Smuzhiyun static RRModePtr *modes;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun static RRModePtr
RRModeCreate(xRRModeInfo * modeInfo,const char * name,ScreenPtr userScreen)64*4882a593Smuzhiyun RRModeCreate(xRRModeInfo * modeInfo, const char *name, ScreenPtr userScreen)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun     RRModePtr mode, *newModes;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun     if (!RRInit())
69*4882a593Smuzhiyun         return NULL;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun     mode = malloc(sizeof(RRModeRec) + modeInfo->nameLength + 1);
72*4882a593Smuzhiyun     if (!mode)
73*4882a593Smuzhiyun         return NULL;
74*4882a593Smuzhiyun     mode->refcnt = 1;
75*4882a593Smuzhiyun     mode->mode = *modeInfo;
76*4882a593Smuzhiyun     mode->name = (char *) (mode + 1);
77*4882a593Smuzhiyun     memcpy(mode->name, name, modeInfo->nameLength);
78*4882a593Smuzhiyun     mode->name[modeInfo->nameLength] = '\0';
79*4882a593Smuzhiyun     mode->userScreen = userScreen;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun     if (num_modes)
82*4882a593Smuzhiyun         newModes = reallocarray(modes, num_modes + 1, sizeof(RRModePtr));
83*4882a593Smuzhiyun     else
84*4882a593Smuzhiyun         newModes = malloc(sizeof(RRModePtr));
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun     if (!newModes) {
87*4882a593Smuzhiyun         free(mode);
88*4882a593Smuzhiyun         return NULL;
89*4882a593Smuzhiyun     }
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun     mode->mode.id = FakeClientID(0);
92*4882a593Smuzhiyun     if (!AddResource(mode->mode.id, RRModeType, (void *) mode)) {
93*4882a593Smuzhiyun         free(newModes);
94*4882a593Smuzhiyun         return NULL;
95*4882a593Smuzhiyun     }
96*4882a593Smuzhiyun     modes = newModes;
97*4882a593Smuzhiyun     modes[num_modes++] = mode;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun     /*
100*4882a593Smuzhiyun      * give the caller a reference to this mode
101*4882a593Smuzhiyun      */
102*4882a593Smuzhiyun     ++mode->refcnt;
103*4882a593Smuzhiyun     return mode;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun static RRModePtr
RRModeFindByName(const char * name,CARD16 nameLength)107*4882a593Smuzhiyun RRModeFindByName(const char *name, CARD16 nameLength)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun     int i;
110*4882a593Smuzhiyun     RRModePtr mode;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun     for (i = 0; i < num_modes; i++) {
113*4882a593Smuzhiyun         mode = modes[i];
114*4882a593Smuzhiyun         if (mode->mode.nameLength == nameLength &&
115*4882a593Smuzhiyun             !memcmp(name, mode->name, nameLength)) {
116*4882a593Smuzhiyun             return mode;
117*4882a593Smuzhiyun         }
118*4882a593Smuzhiyun     }
119*4882a593Smuzhiyun     return NULL;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun RRModePtr
RRModeGet(xRRModeInfo * modeInfo,const char * name)123*4882a593Smuzhiyun RRModeGet(xRRModeInfo * modeInfo, const char *name)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun     int i;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun     for (i = 0; i < num_modes; i++) {
128*4882a593Smuzhiyun         RRModePtr mode = modes[i];
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun         if (RRModeEqual(&mode->mode, modeInfo) &&
131*4882a593Smuzhiyun             !memcmp(name, mode->name, modeInfo->nameLength)) {
132*4882a593Smuzhiyun             ++mode->refcnt;
133*4882a593Smuzhiyun             return mode;
134*4882a593Smuzhiyun         }
135*4882a593Smuzhiyun     }
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun     return RRModeCreate(modeInfo, name, NULL);
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun static RRModePtr
RRModeCreateUser(ScreenPtr pScreen,xRRModeInfo * modeInfo,const char * name,int * error)141*4882a593Smuzhiyun RRModeCreateUser(ScreenPtr pScreen,
142*4882a593Smuzhiyun                  xRRModeInfo * modeInfo, const char *name, int *error)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun     RRModePtr mode;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun     mode = RRModeFindByName(name, modeInfo->nameLength);
147*4882a593Smuzhiyun     if (mode) {
148*4882a593Smuzhiyun         *error = BadName;
149*4882a593Smuzhiyun         return NULL;
150*4882a593Smuzhiyun     }
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun     mode = RRModeCreate(modeInfo, name, pScreen);
153*4882a593Smuzhiyun     if (!mode) {
154*4882a593Smuzhiyun         *error = BadAlloc;
155*4882a593Smuzhiyun         return NULL;
156*4882a593Smuzhiyun     }
157*4882a593Smuzhiyun     *error = Success;
158*4882a593Smuzhiyun     return mode;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun RRModePtr *
RRModesForScreen(ScreenPtr pScreen,int * num_ret)162*4882a593Smuzhiyun RRModesForScreen(ScreenPtr pScreen, int *num_ret)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun     rrScrPriv(pScreen);
165*4882a593Smuzhiyun     int o, c, m;
166*4882a593Smuzhiyun     RRModePtr *screen_modes;
167*4882a593Smuzhiyun     int num_screen_modes = 0;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun     screen_modes = xallocarray((num_modes ? num_modes : 1), sizeof(RRModePtr));
170*4882a593Smuzhiyun     if (!screen_modes)
171*4882a593Smuzhiyun         return NULL;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun     /*
174*4882a593Smuzhiyun      * Add modes from all outputs
175*4882a593Smuzhiyun      */
176*4882a593Smuzhiyun     for (o = 0; o < pScrPriv->numOutputs; o++) {
177*4882a593Smuzhiyun         RROutputPtr output = pScrPriv->outputs[o];
178*4882a593Smuzhiyun         int n;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun         for (m = 0; m < output->numModes + output->numUserModes; m++) {
181*4882a593Smuzhiyun             RRModePtr mode = (m < output->numModes ?
182*4882a593Smuzhiyun                               output->modes[m] :
183*4882a593Smuzhiyun                               output->userModes[m - output->numModes]);
184*4882a593Smuzhiyun             for (n = 0; n < num_screen_modes; n++)
185*4882a593Smuzhiyun                 if (screen_modes[n] == mode)
186*4882a593Smuzhiyun                     break;
187*4882a593Smuzhiyun             if (n == num_screen_modes)
188*4882a593Smuzhiyun                 screen_modes[num_screen_modes++] = mode;
189*4882a593Smuzhiyun         }
190*4882a593Smuzhiyun     }
191*4882a593Smuzhiyun     /*
192*4882a593Smuzhiyun      * Add modes from all crtcs. The goal is to
193*4882a593Smuzhiyun      * make sure all available and active modes
194*4882a593Smuzhiyun      * are visible to the client
195*4882a593Smuzhiyun      */
196*4882a593Smuzhiyun     for (c = 0; c < pScrPriv->numCrtcs; c++) {
197*4882a593Smuzhiyun         RRCrtcPtr crtc = pScrPriv->crtcs[c];
198*4882a593Smuzhiyun         RRModePtr mode = crtc->mode;
199*4882a593Smuzhiyun         int n;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun         if (!mode)
202*4882a593Smuzhiyun             continue;
203*4882a593Smuzhiyun         for (n = 0; n < num_screen_modes; n++)
204*4882a593Smuzhiyun             if (screen_modes[n] == mode)
205*4882a593Smuzhiyun                 break;
206*4882a593Smuzhiyun         if (n == num_screen_modes)
207*4882a593Smuzhiyun             screen_modes[num_screen_modes++] = mode;
208*4882a593Smuzhiyun     }
209*4882a593Smuzhiyun     /*
210*4882a593Smuzhiyun      * Add all user modes for this screen
211*4882a593Smuzhiyun      */
212*4882a593Smuzhiyun     for (m = 0; m < num_modes; m++) {
213*4882a593Smuzhiyun         RRModePtr mode = modes[m];
214*4882a593Smuzhiyun         int n;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun         if (mode->userScreen != pScreen)
217*4882a593Smuzhiyun             continue;
218*4882a593Smuzhiyun         for (n = 0; n < num_screen_modes; n++)
219*4882a593Smuzhiyun             if (screen_modes[n] == mode)
220*4882a593Smuzhiyun                 break;
221*4882a593Smuzhiyun         if (n == num_screen_modes)
222*4882a593Smuzhiyun             screen_modes[num_screen_modes++] = mode;
223*4882a593Smuzhiyun     }
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun     *num_ret = num_screen_modes;
226*4882a593Smuzhiyun     return screen_modes;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun void
RRModeDestroy(RRModePtr mode)230*4882a593Smuzhiyun RRModeDestroy(RRModePtr mode)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun     int m;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun     if (--mode->refcnt > 0)
235*4882a593Smuzhiyun         return;
236*4882a593Smuzhiyun     for (m = 0; m < num_modes; m++) {
237*4882a593Smuzhiyun         if (modes[m] == mode) {
238*4882a593Smuzhiyun             memmove(modes + m, modes + m + 1,
239*4882a593Smuzhiyun                     (num_modes - m - 1) * sizeof(RRModePtr));
240*4882a593Smuzhiyun             num_modes--;
241*4882a593Smuzhiyun             if (!num_modes) {
242*4882a593Smuzhiyun                 free(modes);
243*4882a593Smuzhiyun                 modes = NULL;
244*4882a593Smuzhiyun             }
245*4882a593Smuzhiyun             break;
246*4882a593Smuzhiyun         }
247*4882a593Smuzhiyun     }
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun     free(mode);
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun static int
RRModeDestroyResource(void * value,XID pid)253*4882a593Smuzhiyun RRModeDestroyResource(void *value, XID pid)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun     RRModeDestroy((RRModePtr) value);
256*4882a593Smuzhiyun     return 1;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun /*
260*4882a593Smuzhiyun  * Initialize mode type
261*4882a593Smuzhiyun  */
262*4882a593Smuzhiyun Bool
RRModeInit(void)263*4882a593Smuzhiyun RRModeInit(void)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun     assert(num_modes == 0);
266*4882a593Smuzhiyun     assert(modes == NULL);
267*4882a593Smuzhiyun     RRModeType = CreateNewResourceType(RRModeDestroyResource, "MODE");
268*4882a593Smuzhiyun     if (!RRModeType)
269*4882a593Smuzhiyun         return FALSE;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun     return TRUE;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun /*
275*4882a593Smuzhiyun  * Initialize mode type error value
276*4882a593Smuzhiyun  */
277*4882a593Smuzhiyun void
RRModeInitErrorValue(void)278*4882a593Smuzhiyun RRModeInitErrorValue(void)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun     SetResourceTypeErrorValue(RRModeType, RRErrorBase + BadRRMode);
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun int
ProcRRCreateMode(ClientPtr client)284*4882a593Smuzhiyun ProcRRCreateMode(ClientPtr client)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun     REQUEST(xRRCreateModeReq);
287*4882a593Smuzhiyun     xRRCreateModeReply rep;
288*4882a593Smuzhiyun     WindowPtr pWin;
289*4882a593Smuzhiyun     ScreenPtr pScreen;
290*4882a593Smuzhiyun     xRRModeInfo *modeInfo;
291*4882a593Smuzhiyun     long units_after;
292*4882a593Smuzhiyun     char *name;
293*4882a593Smuzhiyun     int error, rc;
294*4882a593Smuzhiyun     RRModePtr mode;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun     REQUEST_AT_LEAST_SIZE(xRRCreateModeReq);
297*4882a593Smuzhiyun     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
298*4882a593Smuzhiyun     if (rc != Success)
299*4882a593Smuzhiyun         return rc;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun     pScreen = pWin->drawable.pScreen;
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun     modeInfo = &stuff->modeInfo;
304*4882a593Smuzhiyun     name = (char *) (stuff + 1);
305*4882a593Smuzhiyun     units_after = (stuff->length - bytes_to_int32(sizeof(xRRCreateModeReq)));
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun     /* check to make sure requested name fits within the data provided */
308*4882a593Smuzhiyun     if (bytes_to_int32(modeInfo->nameLength) > units_after)
309*4882a593Smuzhiyun         return BadLength;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun     mode = RRModeCreateUser(pScreen, modeInfo, name, &error);
312*4882a593Smuzhiyun     if (!mode)
313*4882a593Smuzhiyun         return error;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun     rep = (xRRCreateModeReply) {
316*4882a593Smuzhiyun         .type = X_Reply,
317*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
318*4882a593Smuzhiyun         .length = 0,
319*4882a593Smuzhiyun         .mode = mode->mode.id
320*4882a593Smuzhiyun 	};
321*4882a593Smuzhiyun     if (client->swapped) {
322*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
323*4882a593Smuzhiyun         swapl(&rep.length);
324*4882a593Smuzhiyun         swapl(&rep.mode);
325*4882a593Smuzhiyun     }
326*4882a593Smuzhiyun     WriteToClient(client, sizeof(xRRCreateModeReply), &rep);
327*4882a593Smuzhiyun     /* Drop out reference to this mode */
328*4882a593Smuzhiyun     RRModeDestroy(mode);
329*4882a593Smuzhiyun     return Success;
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun int
ProcRRDestroyMode(ClientPtr client)333*4882a593Smuzhiyun ProcRRDestroyMode(ClientPtr client)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun     REQUEST(xRRDestroyModeReq);
336*4882a593Smuzhiyun     RRModePtr mode;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xRRDestroyModeReq);
339*4882a593Smuzhiyun     VERIFY_RR_MODE(stuff->mode, mode, DixDestroyAccess);
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun     if (!mode->userScreen)
342*4882a593Smuzhiyun         return BadMatch;
343*4882a593Smuzhiyun     if (mode->refcnt > 1)
344*4882a593Smuzhiyun         return BadAccess;
345*4882a593Smuzhiyun     FreeResource(stuff->mode, 0);
346*4882a593Smuzhiyun     return Success;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun int
ProcRRAddOutputMode(ClientPtr client)350*4882a593Smuzhiyun ProcRRAddOutputMode(ClientPtr client)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun     REQUEST(xRRAddOutputModeReq);
353*4882a593Smuzhiyun     RRModePtr mode;
354*4882a593Smuzhiyun     RROutputPtr output;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
357*4882a593Smuzhiyun     VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
358*4882a593Smuzhiyun     VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess);
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun     if (RROutputIsLeased(output))
361*4882a593Smuzhiyun         return BadAccess;
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun     return RROutputAddUserMode(output, mode);
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun int
ProcRRDeleteOutputMode(ClientPtr client)367*4882a593Smuzhiyun ProcRRDeleteOutputMode(ClientPtr client)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun     REQUEST(xRRDeleteOutputModeReq);
370*4882a593Smuzhiyun     RRModePtr mode;
371*4882a593Smuzhiyun     RROutputPtr output;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
374*4882a593Smuzhiyun     VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
375*4882a593Smuzhiyun     VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess);
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun     if (RROutputIsLeased(output))
378*4882a593Smuzhiyun         return BadAccess;
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun     return RROutputDeleteUserMode(output, mode);
381*4882a593Smuzhiyun }
382