1/*
2
3Copyright 1990, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27*/
28
29#ifdef HAVE_DIX_CONFIG_H
30#include <dix-config.h>
31#endif
32
33#include <X11/X.h>
34#include "servermd.h"
35#include "misc.h"
36#include "mi.h"
37#include "scrnintstr.h"
38#include "pixmapstr.h"
39#include "dix.h"
40#include "miline.h"
41#ifdef MITSHM
42#include <X11/extensions/shm.h>
43#include "shmint.h"
44#endif
45
46/* We use this structure to propogate some information from miScreenInit to
47 * miCreateScreenResources.  miScreenInit allocates the structure, fills it
48 * in, and puts it into pScreen->devPrivate.  miCreateScreenResources
49 * extracts the info and frees the structure.  We could've accomplished the
50 * same thing by adding fields to the screen structure, but they would have
51 * ended up being redundant, and would have exposed this mi implementation
52 * detail to the whole server.
53 */
54
55typedef struct
56{
57    pointer pbits; /* pointer to framebuffer */
58    int width;    /* delta to add to a framebuffer addr to move one row down */
59} miScreenInitParmsRec, *miScreenInitParmsPtr;
60
61
62/* this plugs into pScreen->ModifyPixmapHeader */
63Bool
64miModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
65                     int bitsPerPixel, int devKind, pointer pPixData)
66{
67    if (!pPixmap)
68	return FALSE;
69
70    /*
71     * If all arguments are specified, reinitialize everything (including
72     * validated state).
73     */
74    if ((width > 0) && (height > 0) && (depth > 0) && (bitsPerPixel > 0) &&
75	(devKind > 0) && pPixData) {
76	pPixmap->drawable.depth = depth;
77	pPixmap->drawable.bitsPerPixel = bitsPerPixel;
78	pPixmap->drawable.id = 0;
79	pPixmap->drawable.x = 0;
80	pPixmap->drawable.y = 0;
81	pPixmap->drawable.width = width;
82	pPixmap->drawable.height = height;
83	pPixmap->devKind = devKind;
84	pPixmap->refcnt = 1;
85	pPixmap->devPrivate.ptr = pPixData;
86    } else {
87	/*
88	 * Only modify specified fields, keeping all others intact.
89	 */
90
91	if (width > 0)
92	    pPixmap->drawable.width = width;
93
94	if (height > 0)
95	    pPixmap->drawable.height = height;
96
97	if (depth > 0)
98	    pPixmap->drawable.depth = depth;
99
100	if (bitsPerPixel > 0)
101	    pPixmap->drawable.bitsPerPixel = bitsPerPixel;
102	else if ((bitsPerPixel < 0) && (depth > 0))
103	    pPixmap->drawable.bitsPerPixel = BitsPerPixel(depth);
104
105	/*
106	 * CAVEAT:  Non-SI DDXen may use devKind and devPrivate fields for
107	 *          other purposes.
108	 */
109	if (devKind > 0)
110	    pPixmap->devKind = devKind;
111	else if ((devKind < 0) && ((width > 0) || (depth > 0)))
112	    pPixmap->devKind = PixmapBytePad(pPixmap->drawable.width,
113		pPixmap->drawable.depth);
114
115	if (pPixData)
116	    pPixmap->devPrivate.ptr = pPixData;
117    }
118    pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
119    return TRUE;
120}
121
122static Bool
123miCloseScreen (int iScreen, ScreenPtr pScreen)
124{
125    return ((*pScreen->DestroyPixmap)((PixmapPtr)pScreen->devPrivate));
126}
127
128/* With the introduction of pixmap privates, the "screen pixmap" can no
129 * longer be created in miScreenInit, since all the modules that could
130 * possibly ask for pixmap private space have not been initialized at
131 * that time.  pScreen->CreateScreenResources is called after all
132 * possible private-requesting modules have been inited; we create the
133 * screen pixmap here.
134 */
135Bool
136miCreateScreenResources(ScreenPtr pScreen)
137{
138    miScreenInitParmsPtr pScrInitParms;
139    pointer value;
140
141    pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate;
142
143    /* if width is non-zero, pScreen->devPrivate will be a pixmap
144     * else it will just take the value pbits
145     */
146    if (pScrInitParms->width)
147    {
148	PixmapPtr pPixmap;
149
150	/* create a pixmap with no data, then redirect it to point to
151	 * the screen
152	 */
153	pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0);
154	if (!pPixmap)
155	    return FALSE;
156
157	if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width,
158		    pScreen->height, pScreen->rootDepth,
159		    BitsPerPixel(pScreen->rootDepth),
160		    PixmapBytePad(pScrInitParms->width, pScreen->rootDepth),
161		    pScrInitParms->pbits))
162	    return FALSE;
163	value = (pointer)pPixmap;
164    }
165    else
166    {
167	value = pScrInitParms->pbits;
168    }
169    free(pScreen->devPrivate); /* freeing miScreenInitParmsRec */
170    pScreen->devPrivate = value; /* pPixmap or pbits */
171    return TRUE;
172}
173
174Bool
175miScreenDevPrivateInit(ScreenPtr pScreen, int width, pointer pbits)
176{
177    miScreenInitParmsPtr pScrInitParms;
178
179    /* Stash pbits and width in a short-lived miScreenInitParmsRec attached
180     * to the screen, until CreateScreenResources can put them in the
181     * screen pixmap.
182     */
183    pScrInitParms = malloc(sizeof(miScreenInitParmsRec));
184    if (!pScrInitParms)
185	return FALSE;
186    pScrInitParms->pbits = pbits;
187    pScrInitParms->width = width;
188    pScreen->devPrivate = (pointer)pScrInitParms;
189    return TRUE;
190}
191
192static PixmapPtr
193miGetScreenPixmap(ScreenPtr pScreen)
194{
195    return (PixmapPtr)(pScreen->devPrivate);
196}
197
198static void
199miSetScreenPixmap(PixmapPtr pPix)
200{
201    if (pPix)
202	pPix->drawable.pScreen->devPrivate = (pointer)pPix;
203}
204
205Bool
206miScreenInit(
207    ScreenPtr pScreen,
208    pointer pbits,		/* pointer to screen bits */
209    int xsize, int ysize,	/* in pixels */
210    int dpix, int dpiy,		/* dots per inch */
211    int width,			/* pixel width of frame buffer */
212    int rootDepth,		/* depth of root window */
213    int numDepths,		/* number of depths supported */
214    DepthRec *depths,		/* supported depths */
215    VisualID rootVisual,	/* root visual */
216    int numVisuals,		/* number of visuals supported */
217    VisualRec *visuals		/* supported visuals */
218    )
219{
220    pScreen->width = xsize;
221    pScreen->height = ysize;
222    pScreen->mmWidth = (xsize * 254 + dpix * 5) / (dpix * 10);
223    pScreen->mmHeight = (ysize * 254 + dpiy * 5) / (dpiy * 10);
224    pScreen->numDepths = numDepths;
225    pScreen->rootDepth = rootDepth;
226    pScreen->allowedDepths = depths;
227    pScreen->rootVisual = rootVisual;
228    /* defColormap */
229    pScreen->minInstalledCmaps = 1;
230    pScreen->maxInstalledCmaps = 1;
231    pScreen->backingStoreSupport = NotUseful;
232    pScreen->saveUnderSupport = NotUseful;
233    /* whitePixel, blackPixel */
234    pScreen->ModifyPixmapHeader = miModifyPixmapHeader;
235    pScreen->CreateScreenResources = miCreateScreenResources;
236    pScreen->GetScreenPixmap = miGetScreenPixmap;
237    pScreen->SetScreenPixmap = miSetScreenPixmap;
238    pScreen->numVisuals = numVisuals;
239    pScreen->visuals = visuals;
240    if (width)
241    {
242#ifdef MITSHM
243	ShmRegisterFbFuncs(pScreen);
244#endif
245	pScreen->CloseScreen = miCloseScreen;
246    }
247    /* else CloseScreen */
248    /* QueryBestSize, SaveScreen, GetImage, GetSpans */
249    pScreen->SourceValidate = (SourceValidateProcPtr) 0;
250    /* CreateWindow, DestroyWindow, PositionWindow, ChangeWindowAttributes */
251    /* RealizeWindow, UnrealizeWindow */
252    pScreen->ValidateTree = miValidateTree;
253    pScreen->PostValidateTree = (PostValidateTreeProcPtr) 0;
254    pScreen->WindowExposures = miWindowExposures;
255    /* CopyWindow */
256    pScreen->ClearToBackground = miClearToBackground;
257    pScreen->ClipNotify = (ClipNotifyProcPtr) 0;
258    pScreen->RestackWindow = (RestackWindowProcPtr) 0;
259    /* CreatePixmap, DestroyPixmap */
260    /* RealizeFont, UnrealizeFont */
261    /* CreateGC */
262    /* CreateColormap, DestroyColormap, InstallColormap, UninstallColormap */
263    /* ListInstalledColormaps, StoreColors, ResolveColor */
264    /* BitmapToRegion */
265    pScreen->SendGraphicsExpose = miSendGraphicsExpose;
266    pScreen->BlockHandler = (ScreenBlockHandlerProcPtr)NoopDDA;
267    pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr)NoopDDA;
268    pScreen->blockData = (pointer)0;
269    pScreen->wakeupData = (pointer)0;
270    pScreen->MarkWindow = miMarkWindow;
271    pScreen->MarkOverlappedWindows = miMarkOverlappedWindows;
272    pScreen->MoveWindow = miMoveWindow;
273    pScreen->ResizeWindow = miSlideAndSizeWindow;
274    pScreen->GetLayerWindow = miGetLayerWindow;
275    pScreen->HandleExposures = miHandleValidateExposures;
276    pScreen->ReparentWindow = (ReparentWindowProcPtr) 0;
277    pScreen->ChangeBorderWidth = miChangeBorderWidth;
278    pScreen->SetShape = miSetShape;
279    pScreen->MarkUnrealizedWindow = miMarkUnrealizedWindow;
280
281    miSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS);
282
283    return miScreenDevPrivateInit(pScreen, width, pbits);
284}
285
286DevPrivateKeyRec miZeroLineScreenKeyRec;
287
288void
289miSetZeroLineBias(ScreenPtr pScreen, unsigned int bias)
290{
291    if (!dixRegisterPrivateKey(&miZeroLineScreenKeyRec, PRIVATE_SCREEN, 0))
292	return;
293
294    dixSetPrivate(&pScreen->devPrivates, miZeroLineScreenKey,
295					(unsigned long *)(unsigned long)bias);
296}
297