1 /*
2 Copyright 2005-2017 Jay Sorg
3
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
7 copyright notice and this permission notice appear in supporting
8 documentation.
9
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
12
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
17 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20 misc draw calls
21
22 */
23
24 #if defined(HAVE_CONFIG_H)
25 #include "config_ac.h"
26 #endif
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 /* this should be before all X11 .h files */
33 #include <xorg-server.h>
34 #include <xorgVersion.h>
35
36 /* all driver need this */
37 #include <xf86.h>
38 #include <xf86_OSproc.h>
39
40 #include <mipointer.h>
41 #include <fb.h>
42 #include <micmap.h>
43 #include <mi.h>
44 #include <dixfontstr.h>
45
46 #include "rdp.h"
47 #include "rdpDraw.h"
48 #include "rdpClientCon.h"
49 #include "rdpMisc.h"
50 #include "rdpGlyphs.h"
51 #include "rdpReg.h"
52 #include "rdpMain.h"
53
54 #define LOG_LEVEL 1
55 #define LLOGLN(_level, _args) \
56 do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0)
57
58 #if !defined(XORG_VERSION_CURRENT)
59 #warning XORG_VERSION_CURRENT not defined
60 #endif
61
62 /******************************************************************************/
63 static int
is_clientClip_region(GCPtr gc)64 is_clientClip_region(GCPtr gc)
65 {
66 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 16, 99, 901, 0)
67 return gc->clientClipType == CT_REGION;
68 #else
69 return gc->clientClip != NULL;
70 #endif
71 }
72
73 /******************************************************************************/
74 /* return 0, draw nothing */
75 /* return 1, draw with no clip */
76 /* return 2, draw using clip */
77 int
rdpDrawGetClip(rdpPtr dev,RegionPtr pRegion,DrawablePtr pDrawable,GCPtr pGC)78 rdpDrawGetClip(rdpPtr dev, RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC)
79 {
80 WindowPtr pWindow;
81 RegionPtr temp;
82 BoxRec box;
83 int rv;
84
85 rv = 0;
86
87 if (pDrawable->type == DRAWABLE_PIXMAP)
88 {
89 if (is_clientClip_region(pGC))
90 {
91 miComputeCompositeClip(pGC, pDrawable);
92 RegionCopy(pRegion, pGC->pCompositeClip);
93 rv = 2;
94 }
95 else
96 {
97 rv = 1;
98 }
99
100 if (rv == 2) /* check if the clip is the entire pixmap */
101 {
102 box.x1 = 0;
103 box.y1 = 0;
104 box.x2 = pDrawable->width;
105 box.y2 = pDrawable->height;
106
107 if (rdpRegionContainsRect(pRegion, &box) == rgnIN)
108 {
109 rv = 1;
110 }
111 }
112 }
113 else if (pDrawable->type == DRAWABLE_WINDOW)
114 {
115 pWindow = (WindowPtr)pDrawable;
116
117 if (pWindow->viewable)
118 {
119 if (pGC->subWindowMode == IncludeInferiors)
120 {
121 temp = &pWindow->borderClip;
122 }
123 else
124 {
125 temp = &pWindow->clipList;
126 }
127
128 if (rdpRegionNotEmpty(temp))
129 {
130 if (is_clientClip_region(pGC))
131 {
132 rdpRegionCopy(pRegion, pGC->clientClip);
133 rdpRegionTranslate(pRegion,
134 pDrawable->x + pGC->clipOrg.x,
135 pDrawable->y + pGC->clipOrg.y);
136 rdpRegionIntersect(pRegion, pRegion, temp);
137 rv = 2;
138 }
139 else
140 {
141 rdpRegionCopy(pRegion, temp);
142 rv = 2;
143 }
144
145 if (rv == 2) /* check if the clip is the entire screen */
146 {
147 box.x1 = 0;
148 box.y1 = 0;
149 box.x2 = dev->width;
150 box.y2 = dev->height;
151
152 if (rdpRegionContainsRect(pRegion, &box) == rgnIN)
153 {
154 rv = 1;
155 }
156 }
157 }
158 }
159 }
160
161 return rv;
162 }
163
164 /******************************************************************************/
165 void
GetTextBoundingBox(DrawablePtr pDrawable,FontPtr font,int x,int y,int n,BoxPtr pbox)166 GetTextBoundingBox(DrawablePtr pDrawable, FontPtr font, int x, int y,
167 int n, BoxPtr pbox)
168 {
169 int maxAscent;
170 int maxDescent;
171 int maxCharWidth;
172
173 if (FONTASCENT(font) > FONTMAXBOUNDS(font, ascent))
174 {
175 maxAscent = FONTASCENT(font);
176 }
177 else
178 {
179 maxAscent = FONTMAXBOUNDS(font, ascent);
180 }
181
182 if (FONTDESCENT(font) > FONTMAXBOUNDS(font, descent))
183 {
184 maxDescent = FONTDESCENT(font);
185 }
186 else
187 {
188 maxDescent = FONTMAXBOUNDS(font, descent);
189 }
190
191 if (FONTMAXBOUNDS(font, rightSideBearing) >
192 FONTMAXBOUNDS(font, characterWidth))
193 {
194 maxCharWidth = FONTMAXBOUNDS(font, rightSideBearing);
195 }
196 else
197 {
198 maxCharWidth = FONTMAXBOUNDS(font, characterWidth);
199 }
200
201 pbox->x1 = pDrawable->x + x;
202 pbox->y1 = pDrawable->y + y - maxAscent;
203 pbox->x2 = pbox->x1 + maxCharWidth * n;
204 pbox->y2 = pbox->y1 + maxAscent + maxDescent;
205
206 if (FONTMINBOUNDS(font, leftSideBearing) < 0)
207 {
208 pbox->x1 += FONTMINBOUNDS(font, leftSideBearing);
209 }
210 }
211
212 /******************************************************************************/
213 int
rdpDrawItemAdd(rdpPtr dev,rdpPixmapRec * priv,struct rdp_draw_item * di)214 rdpDrawItemAdd(rdpPtr dev, rdpPixmapRec *priv, struct rdp_draw_item *di)
215 {
216 priv->is_alpha_dirty_not = FALSE;
217
218 if (priv->draw_item_tail == NULL)
219 {
220 priv->draw_item_tail = di;
221 priv->draw_item_head = di;
222 }
223 else
224 {
225 di->prev = priv->draw_item_tail;
226 priv->draw_item_tail->next = di;
227 priv->draw_item_tail = di;
228 }
229
230 if (priv == &(dev->screenPriv))
231 {
232 rdpClientConScheduleDeferredUpdate(dev);
233 }
234
235 return 0;
236 }
237
238 /******************************************************************************/
239 int
rdpDrawItemRemove(rdpPtr dev,rdpPixmapRec * priv,struct rdp_draw_item * di)240 rdpDrawItemRemove(rdpPtr dev, rdpPixmapRec *priv, struct rdp_draw_item *di)
241 {
242 if (di->prev != NULL)
243 {
244 di->prev->next = di->next;
245 }
246
247 if (di->next != NULL)
248 {
249 di->next->prev = di->prev;
250 }
251
252 if (priv->draw_item_head == di)
253 {
254 priv->draw_item_head = di->next;
255 }
256
257 if (priv->draw_item_tail == di)
258 {
259 priv->draw_item_tail = di->prev;
260 }
261
262 if (di->type == RDI_LINE)
263 {
264 if (di->u.line.segs != NULL)
265 {
266 free(di->u.line.segs);
267 }
268 }
269
270 if (di->type == RDI_TEXT)
271 {
272 rdpGlyphDeleteRdpText(di->u.text.rtext);
273 }
274
275 rdpRegionDestroy(di->reg);
276 free(di);
277 return 0;
278 }
279
280 /******************************************************************************/
281 int
rdpDrawItemRemoveAll(rdpPtr dev,rdpPixmapRec * priv)282 rdpDrawItemRemoveAll(rdpPtr dev, rdpPixmapRec *priv)
283 {
284 struct rdp_draw_item *di;
285
286 di = priv->draw_item_head;
287
288 while (di != NULL)
289 {
290 rdpDrawItemRemove(dev, priv, di);
291 di = priv->draw_item_head;
292 }
293
294 return 0;
295 }
296
297 /*****************************************************************************/
298 void
rdpCopyWindow(WindowPtr pWin,DDXPointRec ptOldOrg,RegionPtr pOldRegion)299 rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion)
300 {
301 ScreenPtr pScreen;
302 rdpPtr dev;
303 RegionRec reg;
304 RegionRec clip;
305 int dx;
306 int dy;
307 int num_clip_rects;
308 int num_reg_rects;
309 BoxPtr box;
310 BoxRec box1;
311
312 LLOGLN(10, ("rdpCopyWindow:"));
313 pScreen = pWin->drawable.pScreen;
314 dev = rdpGetDevFromScreen(pScreen);
315 dev->counts.rdpCopyWindowCallCount++;
316
317 rdpRegionInit(®, NullBox, 0);
318 rdpRegionCopy(®, pOldRegion);
319 rdpRegionInit(&clip, NullBox, 0);
320 rdpRegionCopy(&clip, &pWin->borderClip);
321 dx = pWin->drawable.x - ptOldOrg.x;
322 dy = pWin->drawable.y - ptOldOrg.y;
323
324 dev->pScreen->CopyWindow = dev->CopyWindow;
325 dev->pScreen->CopyWindow(pWin, ptOldOrg, pOldRegion);
326 dev->pScreen->CopyWindow = rdpCopyWindow;
327
328 num_clip_rects = REGION_NUM_RECTS(&clip);
329 num_reg_rects = REGION_NUM_RECTS(®);
330
331 if ((num_clip_rects == 0) || (num_reg_rects == 0))
332 {
333 }
334 else
335 {
336 if ((num_clip_rects > 16) || (num_reg_rects > 16))
337 {
338 LLOGLN(10, ("rdpCopyWindow: big list"));
339 box = rdpRegionExtents(®);
340 box1 = *box;
341 box1.x1 += dx;
342 box1.y1 += dy;
343 box1.x2 += dx;
344 box1.y2 += dy;
345 rdpClientConAddAllBox(dev, &box1, &(pWin->drawable));
346 }
347 else
348 {
349 rdpRegionTranslate(®, dx, dy);
350 rdpRegionIntersect(®, ®, &clip);
351 rdpClientConAddAllReg(dev, ®, &(pWin->drawable));
352 }
353 }
354 rdpRegionUninit(®);
355 rdpRegionUninit(&clip);
356 }
357
358 #if XRDP_CLOSESCR == 1 /* before v1.13 */
359
360 /*****************************************************************************/
361 Bool
rdpCloseScreen(int index,ScreenPtr pScreen)362 rdpCloseScreen(int index, ScreenPtr pScreen)
363 {
364 rdpPtr dev;
365 Bool rv;
366
367 LLOGLN(0, ("rdpCloseScreen:"));
368 dev = rdpGetDevFromScreen(pScreen);
369 dev->pScreen->CloseScreen = dev->CloseScreen;
370 rv = dev->pScreen->CloseScreen(index, pScreen);
371 dev->pScreen->CloseScreen = rdpCloseScreen;
372 xorgxrdpDownDown(pScreen);
373 return rv;
374 }
375
376 #else
377
378 /*****************************************************************************/
379 Bool
rdpCloseScreen(ScreenPtr pScreen)380 rdpCloseScreen(ScreenPtr pScreen)
381 {
382 rdpPtr dev;
383 Bool rv;
384
385 LLOGLN(0, ("rdpCloseScreen:"));
386 dev = rdpGetDevFromScreen(pScreen);
387 dev->pScreen->CloseScreen = dev->CloseScreen;
388 rv = dev->pScreen->CloseScreen(pScreen);
389 dev->pScreen->CloseScreen = rdpCloseScreen;
390 xorgxrdpDownDown(pScreen);
391 return rv;
392 }
393
394 #endif
395
396 /******************************************************************************/
397 WindowPtr
rdpGetRootWindowPtr(ScreenPtr pScreen)398 rdpGetRootWindowPtr(ScreenPtr pScreen)
399 {
400 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 0, 0, 0)
401 return WindowTable[pScreen->myNum]; /* in globals.c */
402 #else
403 return pScreen->root;
404 #endif
405 }
406
407 /******************************************************************************/
408 rdpPtr
rdpGetDevFromScreen(ScreenPtr pScreen)409 rdpGetDevFromScreen(ScreenPtr pScreen)
410 {
411 ScrnInfoPtr pScrn;
412 rdpPtr dev;
413
414 if (pScreen == NULL)
415 {
416 pScrn = xf86Screens[0];
417 }
418 else
419 {
420 pScrn = xf86Screens[pScreen->myNum];
421 }
422 dev = XRDPPTR(pScrn);
423 return dev;
424 }
425