1 /*
2 Copyright 2011-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 RandR 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
45 #include "rdp.h"
46 #include "rdpDraw.h"
47 #include "rdpReg.h"
48 #include "rdpMisc.h"
49 #include "rdpRandR.h"
50
51 #if defined(XORGXRDP_GLAMOR)
52 #include <glamor.h>
53 #endif
54
55 static int g_panning = 0;
56
57 /******************************************************************************/
58 #define LOG_LEVEL 1
59 #define LLOGLN(_level, _args) \
60 do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0)
61
62 /******************************************************************************/
63 Bool
rdpRRRegisterSize(ScreenPtr pScreen,int width,int height)64 rdpRRRegisterSize(ScreenPtr pScreen, int width, int height)
65 {
66 int mmwidth;
67 int mmheight;
68 RRScreenSizePtr pSize;
69 ScrnInfoPtr pScrn;
70
71 LLOGLN(0, ("rdpRRRegisterSize: width %d height %d", width, height));
72 pScrn = xf86Screens[pScreen->myNum];
73 mmwidth = PixelToMM(width, pScrn->xDpi);
74 mmheight = PixelToMM(height, pScrn->yDpi);
75 pSize = RRRegisterSize(pScreen, width, height, mmwidth, mmheight);
76 /* Tell RandR what the current config is */
77 RRSetCurrentConfig(pScreen, RR_Rotate_0, 0, pSize);
78 return TRUE;
79 }
80
81 /******************************************************************************/
82 Bool
rdpRRSetConfig(ScreenPtr pScreen,Rotation rotateKind,int rate,RRScreenSizePtr pSize)83 rdpRRSetConfig(ScreenPtr pScreen, Rotation rotateKind, int rate,
84 RRScreenSizePtr pSize)
85 {
86 LLOGLN(0, ("rdpRRSetConfig:"));
87 return TRUE;
88 }
89
90 /******************************************************************************/
91 Bool
rdpRRGetInfo(ScreenPtr pScreen,Rotation * pRotations)92 rdpRRGetInfo(ScreenPtr pScreen, Rotation *pRotations)
93 {
94 LLOGLN(0, ("rdpRRGetInfo:"));
95 *pRotations = RR_Rotate_0;
96 return TRUE;
97 }
98
99 #if defined(XORGXRDP_GLAMOR)
100 /*****************************************************************************/
101 static int
rdpRRSetPixmapVisitWindow(WindowPtr window,void * data)102 rdpRRSetPixmapVisitWindow(WindowPtr window, void *data)
103 {
104 ScreenPtr screen;
105
106 LLOGLN(10, ("rdpRRSetPixmapVisitWindow:"));
107 screen = window->drawable.pScreen;
108 if (screen->GetWindowPixmap(window) == data)
109 {
110 screen->SetWindowPixmap(window, screen->GetScreenPixmap(screen));
111 return WT_WALKCHILDREN;
112 }
113 return WT_DONTWALKCHILDREN;
114 }
115 #endif
116
117 /******************************************************************************/
118 Bool
rdpRRScreenSetSize(ScreenPtr pScreen,CARD16 width,CARD16 height,CARD32 mmWidth,CARD32 mmHeight)119 rdpRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height,
120 CARD32 mmWidth, CARD32 mmHeight)
121 {
122 WindowPtr root;
123 PixmapPtr screenPixmap;
124 BoxRec box;
125 rdpPtr dev;
126
127 LLOGLN(0, ("rdpRRScreenSetSize: width %d height %d mmWidth %d mmHeight %d",
128 width, height, (int)mmWidth, (int)mmHeight));
129 dev = rdpGetDevFromScreen(pScreen);
130 if (dev->allow_screen_resize == 0)
131 {
132 if ((width == pScreen->width) && (height == pScreen->height) &&
133 (mmWidth == pScreen->mmWidth) && (mmHeight == pScreen->mmHeight))
134 {
135 LLOGLN(0, ("rdpRRScreenSetSize: already this size"));
136 return TRUE;
137 }
138 LLOGLN(0, ("rdpRRScreenSetSize: not allowing resize"));
139 return FALSE;
140 }
141 root = rdpGetRootWindowPtr(pScreen);
142 if ((width < 1) || (height < 1))
143 {
144 LLOGLN(10, (" error width %d height %d", width, height));
145 return FALSE;
146 }
147 dev->width = width;
148 dev->height = height;
149 dev->paddedWidthInBytes = PixmapBytePad(dev->width, dev->depth);
150 dev->sizeInBytes = dev->paddedWidthInBytes * dev->height;
151 pScreen->width = width;
152 pScreen->height = height;
153 pScreen->mmWidth = mmWidth;
154 pScreen->mmHeight = mmHeight;
155 screenPixmap = dev->screenSwPixmap;
156 free(dev->pfbMemory_alloc);
157 dev->pfbMemory_alloc = g_new0(uint8_t, dev->sizeInBytes + 16);
158 dev->pfbMemory = (uint8_t *) RDPALIGN(dev->pfbMemory_alloc, 16);
159 pScreen->ModifyPixmapHeader(screenPixmap, width, height,
160 -1, -1,
161 dev->paddedWidthInBytes,
162 dev->pfbMemory);
163 if (dev->glamor)
164 {
165 #if defined(XORGXRDP_GLAMOR)
166 PixmapPtr old_screen_pixmap;
167 uint32_t screen_tex;
168 old_screen_pixmap = pScreen->GetScreenPixmap(pScreen);
169 screenPixmap = pScreen->CreatePixmap(pScreen,
170 pScreen->width,
171 pScreen->height,
172 pScreen->rootDepth,
173 GLAMOR_CREATE_NO_LARGE);
174 if (screenPixmap == NULL)
175 {
176 return FALSE;
177 }
178 screen_tex = glamor_get_pixmap_texture(screenPixmap);
179 LLOGLN(0, ("rdpRRScreenSetSize: screen_tex 0x%8.8x", screen_tex));
180 pScreen->SetScreenPixmap(screenPixmap);
181 if ((pScreen->root != NULL) && (pScreen->SetWindowPixmap != NULL))
182 {
183 TraverseTree(pScreen->root, rdpRRSetPixmapVisitWindow, old_screen_pixmap);
184 }
185 pScreen->DestroyPixmap(old_screen_pixmap);
186 #endif
187 }
188 box.x1 = 0;
189 box.y1 = 0;
190 box.x2 = width;
191 box.y2 = height;
192 rdpRegionInit(&root->winSize, &box, 1);
193 rdpRegionInit(&root->borderSize, &box, 1);
194 rdpRegionReset(&root->borderClip, &box);
195 rdpRegionBreak(&root->clipList);
196 root->drawable.width = width;
197 root->drawable.height = height;
198 ResizeChildrenWinSize(root, 0, 0, 0, 0);
199 RRGetInfo(pScreen, 1);
200 LLOGLN(0, (" screen resized to %dx%d", pScreen->width, pScreen->height));
201 RRScreenSizeNotify(pScreen);
202 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 13, 0, 0, 0)
203 xf86EnableDisableFBAccess(pScreen->myNum, FALSE);
204 xf86EnableDisableFBAccess(pScreen->myNum, TRUE);
205 #else
206 xf86EnableDisableFBAccess(xf86Screens[pScreen->myNum], FALSE);
207 xf86EnableDisableFBAccess(xf86Screens[pScreen->myNum], TRUE);
208 #endif
209 return TRUE;
210 }
211
212 /******************************************************************************/
213 Bool
rdpRRCrtcSet(ScreenPtr pScreen,RRCrtcPtr crtc,RRModePtr mode,int x,int y,Rotation rotation,int numOutputs,RROutputPtr * outputs)214 rdpRRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc, RRModePtr mode,
215 int x, int y, Rotation rotation, int numOutputs,
216 RROutputPtr *outputs)
217 {
218 LLOGLN(0, ("rdpRRCrtcSet:"));
219 return TRUE;
220 }
221
222 /******************************************************************************/
223 Bool
rdpRRCrtcSetGamma(ScreenPtr pScreen,RRCrtcPtr crtc)224 rdpRRCrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr crtc)
225 {
226 LLOGLN(0, ("rdpRRCrtcSetGamma:"));
227 return TRUE;
228 }
229
230 /******************************************************************************/
231 Bool
rdpRRCrtcGetGamma(ScreenPtr pScreen,RRCrtcPtr crtc)232 rdpRRCrtcGetGamma(ScreenPtr pScreen, RRCrtcPtr crtc)
233 {
234 LLOGLN(0, ("rdpRRCrtcGetGamma: %p %p %p %p", crtc, crtc->gammaRed,
235 crtc->gammaBlue, crtc->gammaGreen));
236 return TRUE;
237 }
238
239 /******************************************************************************/
240 Bool
rdpRROutputSetProperty(ScreenPtr pScreen,RROutputPtr output,Atom property,RRPropertyValuePtr value)241 rdpRROutputSetProperty(ScreenPtr pScreen, RROutputPtr output, Atom property,
242 RRPropertyValuePtr value)
243 {
244 LLOGLN(0, ("rdpRROutputSetProperty:"));
245 return TRUE;
246 }
247
248 /******************************************************************************/
249 Bool
rdpRROutputValidateMode(ScreenPtr pScreen,RROutputPtr output,RRModePtr mode)250 rdpRROutputValidateMode(ScreenPtr pScreen, RROutputPtr output,
251 RRModePtr mode)
252 {
253 LLOGLN(0, ("rdpRROutputValidateMode:"));
254 return TRUE;
255 }
256
257 /******************************************************************************/
258 void
rdpRRModeDestroy(ScreenPtr pScreen,RRModePtr mode)259 rdpRRModeDestroy(ScreenPtr pScreen, RRModePtr mode)
260 {
261 LLOGLN(0, ("rdpRRModeDestroy:"));
262 }
263
264 /******************************************************************************/
265 Bool
rdpRROutputGetProperty(ScreenPtr pScreen,RROutputPtr output,Atom property)266 rdpRROutputGetProperty(ScreenPtr pScreen, RROutputPtr output, Atom property)
267 {
268 LLOGLN(0, ("rdpRROutputGetProperty:"));
269 return TRUE;
270 }
271
272 /******************************************************************************/
273 #if 0
274 static int
275 get_rect(rdpPtr dev, const char *name, BoxPtr rect)
276 {
277 if (strcmp(name, "rdp0") == 0)
278 {
279 rect->x1 = dev->minfo[0].left;
280 rect->y1 = dev->minfo[0].top;
281 rect->x2 = dev->minfo[0].right + 1;
282 rect->y2 = dev->minfo[0].bottom + 1;
283 }
284 else if (strcmp(name, "rdp1") == 0)
285 {
286 rect->x1 = dev->minfo[1].left;
287 rect->y1 = dev->minfo[1].top;
288 rect->x2 = dev->minfo[1].right + 1;
289 rect->y2 = dev->minfo[1].bottom + 1;
290 }
291 else if (strcmp(name, "rdp2") == 0)
292 {
293 rect->x1 = dev->minfo[2].left;
294 rect->y1 = dev->minfo[2].top;
295 rect->x2 = dev->minfo[2].right + 1;
296 rect->y2 = dev->minfo[2].bottom + 1;
297 }
298 else if (strcmp(name, "rdp3") == 0)
299 {
300 rect->x1 = dev->minfo[3].left;
301 rect->y1 = dev->minfo[3].top;
302 rect->x2 = dev->minfo[3].right + 1;
303 rect->y2 = dev->minfo[3].bottom + 1;
304 }
305 return 0;
306 }
307 #endif
308
309 /******************************************************************************/
310 Bool
rdpRRGetPanning(ScreenPtr pScreen,RRCrtcPtr crtc,BoxPtr totalArea,BoxPtr trackingArea,INT16 * border)311 rdpRRGetPanning(ScreenPtr pScreen, RRCrtcPtr crtc, BoxPtr totalArea,
312 BoxPtr trackingArea, INT16 *border)
313 {
314 rdpPtr dev;
315 BoxRec totalAreaRect;
316 BoxRec trackingAreaRect;
317
318 LLOGLN(10, ("rdpRRGetPanning: totalArea %p trackingArea %p border %p",
319 totalArea, trackingArea, border));
320
321 if (!g_panning)
322 {
323 return FALSE;
324 }
325
326 dev = rdpGetDevFromScreen(pScreen);
327
328 totalAreaRect.x1 = 0;
329 totalAreaRect.y1 = 0;
330 totalAreaRect.x2 = dev->width;
331 totalAreaRect.y2 = dev->height;
332
333 trackingAreaRect.x1 = 0;
334 trackingAreaRect.y1 = 0;
335 trackingAreaRect.x2 = dev->width;
336 trackingAreaRect.y2 = dev->height;
337
338 if (totalArea != 0)
339 {
340 *totalArea = totalAreaRect;
341 }
342
343 if (trackingArea != 0)
344 {
345 *trackingArea = trackingAreaRect;
346 }
347
348 if (border != 0)
349 {
350 border[0] = 0;
351 border[1] = 0;
352 border[2] = 0;
353 border[3] = 0;
354 }
355 return TRUE;
356 }
357
358 /******************************************************************************/
359 Bool
rdpRRSetPanning(ScreenPtr pScreen,RRCrtcPtr crtc,BoxPtr totalArea,BoxPtr trackingArea,INT16 * border)360 rdpRRSetPanning(ScreenPtr pScreen, RRCrtcPtr crtc, BoxPtr totalArea,
361 BoxPtr trackingArea, INT16 *border)
362 {
363 LLOGLN(0, ("rdpRRSetPanning:"));
364 return TRUE;
365 }
366
367 /******************************************************************************/
368 static RROutputPtr
rdpRRAddOutput(rdpPtr dev,const char * aname,int x,int y,int width,int height)369 rdpRRAddOutput(rdpPtr dev, const char *aname, int x, int y, int width, int height)
370 {
371 RRModePtr mode;
372 RRCrtcPtr crtc;
373 RROutputPtr output;
374 xRRModeInfo modeInfo;
375 char name[64];
376 const int vfreq = 50;
377 int i;
378
379 sprintf (name, "%dx%d", width, height);
380 memset (&modeInfo, 0, sizeof(modeInfo));
381 modeInfo.width = width;
382 modeInfo.height = height;
383 modeInfo.hTotal = width;
384 modeInfo.vTotal = height;
385 modeInfo.dotClock = vfreq * width * height;
386 modeInfo.nameLength = strlen(name);
387 mode = RRModeGet(&modeInfo, name);
388 if (mode == 0)
389 {
390 LLOGLN(0, ("rdpRRAddOutput: RRModeGet failed"));
391 return 0;
392 }
393
394 crtc = RRCrtcCreate(dev->pScreen, NULL);
395 if (crtc == 0)
396 {
397 LLOGLN(0, ("rdpRRAddOutput: RRCrtcCreate failed"));
398 RRModeDestroy(mode);
399 return 0;
400 }
401 /* Create and initialise (unused) gamma ramps */
402 RRCrtcGammaSetSize (crtc, 256);
403 for (i = 0 ; i < crtc->gammaSize; ++i)
404 {
405 unsigned short val = (0xffff * i) / (crtc->gammaSize - 1);
406 crtc->gammaRed[i] = val;
407 crtc->gammaGreen[i] = val;
408 crtc->gammaBlue[i] = val;
409 }
410
411 output = RROutputCreate(dev->pScreen, aname, strlen(aname), NULL);
412 if (output == 0)
413 {
414 LLOGLN(0, ("rdpRRAddOutput: RROutputCreate failed"));
415 RRCrtcDestroy(crtc);
416 RRModeDestroy(mode);
417 return 0;
418 }
419 if (!RROutputSetClones(output, NULL, 0))
420 {
421 LLOGLN(0, ("rdpRRAddOutput: RROutputSetClones failed"));
422 }
423 if (!RROutputSetModes(output, &mode, 1, 0))
424 {
425 LLOGLN(0, ("rdpRRAddOutput: RROutputSetModes failed"));
426 }
427 if (!RROutputSetCrtcs(output, &crtc, 1))
428 {
429 LLOGLN(0, ("rdpRRAddOutput: RROutputSetCrtcs failed"));
430 }
431 if (!RROutputSetConnection(output, RR_Connected))
432 {
433 LLOGLN(0, ("rdpRRAddOutput: RROutputSetConnection failed"));
434 }
435 RRCrtcNotify(crtc, mode, x, y, RR_Rotate_0, NULL, 1, &output);
436 return output;
437 }
438
439 /******************************************************************************/
440 static RROutputPtr
rdpRRUpdateOutput(RROutputPtr output,RRCrtcPtr crtc,int x,int y,int width,int height)441 rdpRRUpdateOutput(RROutputPtr output, RRCrtcPtr crtc,
442 int x, int y, int width, int height)
443 {
444 RRModePtr mode;
445 xRRModeInfo modeInfo;
446 char name[64];
447 const int vfreq = 50;
448
449 LLOGLN(0, ("rdpRRUpdateOutput:"));
450 sprintf (name, "%dx%d", width, height);
451 memset (&modeInfo, 0, sizeof(modeInfo));
452 modeInfo.width = width;
453 modeInfo.height = height;
454 modeInfo.hTotal = width;
455 modeInfo.vTotal = height;
456 modeInfo.dotClock = vfreq * width * height;
457 modeInfo.nameLength = strlen(name);
458 mode = RRModeGet(&modeInfo, name);
459 if (mode == 0)
460 {
461 LLOGLN(0, ("rdpRRUpdateOutput: RRModeGet failed"));
462 return 0;
463 }
464 if (!RROutputSetModes(output, &mode, 1, 0))
465 {
466 LLOGLN(0, ("rdpRRUpdateOutput: RROutputSetModes failed"));
467 }
468 RRCrtcNotify(crtc, mode, x, y, RR_Rotate_0, NULL, 1, &output);
469 RROutputChanged(output, 1);
470 return output;
471 }
472
473 /******************************************************************************/
474 static void
RRSetPrimaryOutput(rrScrPrivPtr pScrPriv,RROutputPtr output)475 RRSetPrimaryOutput(rrScrPrivPtr pScrPriv, RROutputPtr output)
476 {
477 if (pScrPriv->primaryOutput == output)
478 {
479 return;
480 }
481 /* clear the old primary */
482 if (pScrPriv->primaryOutput)
483 {
484 RROutputChanged(pScrPriv->primaryOutput, 0);
485 pScrPriv->primaryOutput = NULL;
486 }
487 /* set the new primary */
488 if (output)
489 {
490 pScrPriv->primaryOutput = output;
491 RROutputChanged(output, 0);
492 }
493 pScrPriv->layoutChanged = TRUE;
494 }
495
496 /******************************************************************************/
497 static int
rdpRRRemoveExtra(rrScrPrivPtr pRRScrPriv,int count)498 rdpRRRemoveExtra(rrScrPrivPtr pRRScrPriv, int count)
499 {
500 int index;
501
502 while (pRRScrPriv->numCrtcs > count)
503 {
504 index = pRRScrPriv->numCrtcs - 1;
505 RRCrtcDestroy(pRRScrPriv->crtcs[index]);
506 pRRScrPriv->crtcs[index] = NULL;
507 }
508 while (pRRScrPriv->numOutputs > count)
509 {
510 index = pRRScrPriv->numOutputs - 1;
511 RROutputDestroy(pRRScrPriv->outputs[index]);
512 pRRScrPriv->outputs[index] = NULL;
513 }
514 return 0;
515 }
516
517 /******************************************************************************/
518 int
rdpRRSetRdpOutputs(rdpPtr dev)519 rdpRRSetRdpOutputs(rdpPtr dev)
520 {
521 rrScrPrivPtr pRRScrPriv;
522 int index;
523 int left;
524 int top;
525 int width;
526 int height;
527 char text[256];
528 RROutputPtr output;
529
530 pRRScrPriv = rrGetScrPriv(dev->pScreen);
531 LLOGLN(0, ("rdpRRSetRdpOutputs: numCrtcs %d numOutputs %d monitorCount %d",
532 pRRScrPriv->numCrtcs, pRRScrPriv->numOutputs, dev->monitorCount));
533 if (dev->monitorCount <= 0)
534 {
535 left = 0;
536 top = 0;
537 width = dev->width;
538 height = dev->height;
539 if (pRRScrPriv->numCrtcs > 0)
540 {
541 /* update */
542 LLOGLN(0, ("rdpRRSetRdpOutputs: update output %d "
543 "left %d top %d width %d height %d",
544 0, left, top, width, height));
545 output = rdpRRUpdateOutput(pRRScrPriv->outputs[0],
546 pRRScrPriv->crtcs[0],
547 left, top, width, height);
548 }
549 else
550 {
551 /* add */
552 LLOGLN(0, ("rdpRRSetRdpOutputs: add output %d "
553 "left %d top %d width %d height %d",
554 0, left, top, width, height));
555 snprintf(text, 255, "rdp%d", 0);
556 output = rdpRRAddOutput(dev, text,
557 left, top, width, height);
558 }
559 if (output == NULL)
560 {
561 LLOGLN(0, ("rdpRRSetRdpOutputs: rdpRRUpdateOutput failed"));
562 return 1;
563 }
564 /* remove any entra */
565 rdpRRRemoveExtra(pRRScrPriv, 1);
566 }
567 else
568 {
569 for (index = 0; index < dev->monitorCount; index++)
570 {
571 left = dev->minfo[index].left;
572 top = dev->minfo[index].top;
573 width = dev->minfo[index].right - dev->minfo[index].left + 1;
574 height = dev->minfo[index].bottom - dev->minfo[index].top + 1;
575 if (index < pRRScrPriv->numCrtcs)
576 {
577 /* update */
578 LLOGLN(0, ("rdpRRSetRdpOutputs: update output %d "
579 "left %d top %d width %d height %d",
580 index, left, top, width, height));
581 output = rdpRRUpdateOutput(pRRScrPriv->outputs[index],
582 pRRScrPriv->crtcs[index],
583 left, top, width, height);
584 }
585 else
586 {
587 /* add */
588 LLOGLN(0, ("rdpRRSetRdpOutputs: add output %d "
589 "left %d top %d width %d height %d",
590 index, left, top, width, height));
591 snprintf(text, 255, "rdp%d", index);
592 output = rdpRRAddOutput(dev, text,
593 left, top, width, height);
594 }
595 if ((output != 0) && (dev->minfo[index].is_primary))
596 {
597 RRSetPrimaryOutput(pRRScrPriv, output);
598 }
599 if (output == NULL)
600 {
601 LLOGLN(0, ("rdpRRSetRdpOutputs: rdpRRUpdateOutput failed"));
602 return 1;
603 }
604 }
605 /* remove any entra */
606 rdpRRRemoveExtra(pRRScrPriv, dev->monitorCount);
607 }
608 return 0;
609 }
610
611