1 /*
2 * Copyright © 2004 Keith Packard
3 * Copyright © 2016-2017 Bjorn Stahl
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission. Keith Packard makes no
12 * representations about the suitability of this software for any purpose. It
13 * is provided "as is" without express or implied warranty.
14 *
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 */
23
24 /*
25 * See README-Arcan.md for details on status and todo.
26 */
27
28 #ifdef HAVE_DIX_CONFIG_H
29 #include <dix-config.h>
30 #endif
31
32 #define WANT_ARCAN_SHMIF_HELPER
33 #include "arcan.h"
34 #include <X11/keysym.h>
35
36 #ifdef GLAMOR
37 #define MESA_EGL_NO_X11_HEADERS
38 #include <gbm.h>
39 #include "glamor.h"
40 #include "glamor_context.h"
41 #include "glamor_egl.h"
42 #include "dri3.h"
43 #include <drm_fourcc.h>
44 #endif
45
46 /*
47 * from Xwin
48 */
49 #include <opaque.h>
50 #define XSERV_t
51 #define TRANS_SERVER
52 #include <X11/Xtrans/Xtrans.h>
53 #include <present.h>
54
55 arcanInput arcanInputPriv;
56 arcanConfig arcanConfigPriv;
57 int arcanGlamor;
58
59 #ifdef __OpenBSD__
60 #include "../../dmx/input/atKeynames.h"
61 #include "bsd_KbdMap.c"
62
enqueueKeyboard(uint16_t scancode,int active)63 static void enqueueKeyboard(uint16_t scancode, int active)
64 {
65 KdEnqueueKeyboardEvent(arcanInputPriv.ki, wsUsbMap[scancode], !active);
66 }
67 #else
enqueueKeyboard(uint16_t scancode,int active)68 static void enqueueKeyboard(uint16_t scancode, int active)
69 {
70 KdEnqueueKeyboardEvent(arcanInputPriv.ki, scancode, !active);
71 }
72 #endif
73
74 static struct arcan_shmif_cont cursor;
75 static DevPrivateKeyRec cursor_private_key;
76
77 static uint8_t code_tbl[512];
78 static struct arcan_shmif_initial* arcan_init;
79 static DevPrivateKeyRec pixmap_private_key;
80
trace(const char * msg,...)81 static inline void trace(const char* msg, ...)
82 {
83 #ifdef ARCAN_TRACE
84 va_list args;
85 va_start( args, msg );
86 vfprintf(stderr, msg, args );
87 fprintf(stderr, "\n");
88 va_end( args);
89 fflush(stderr);
90 #endif
91 }
92
93 /*
94 * likely that these calculations are incorrect, need BE machines to
95 * test between both setArcan and setGlamor versions, stick with the
96 * setGlamor version for now.
97 */
setArcanMask(KdScreenInfo * screen)98 static void setArcanMask(KdScreenInfo* screen)
99 {
100 screen->rate = 60;
101 screen->fb.depth = 24;
102 screen->fb.bitsPerPixel = 32;
103 screen->fb.visuals = (1 << TrueColor) | (1 << DirectColor);
104 screen->fb.redMask = SHMIF_RGBA(0xff, 0x00, 0x00, 0x00);
105 screen->fb.greenMask = SHMIF_RGBA(0x00, 0xff, 0x00, 0x00);
106 screen->fb.blueMask = SHMIF_RGBA(0x00, 0x00, 0xff, 0x00);
107 }
108
setGlamorMask(KdScreenInfo * screen)109 static void setGlamorMask(KdScreenInfo* screen)
110 {
111 int bpc, green_bpc;
112 screen->rate = 60;
113 screen->fb.visuals = (1 << TrueColor) | (1 << DirectColor);
114 screen->fb.depth = 24;
115 /* calculations used in xWayland and elsewhere */
116 bpc = 24 / 3;
117 green_bpc = 24 - 2 * bpc;
118 screen->fb.bitsPerPixel = 32;
119 screen->fb.blueMask = (1 << bpc) - 1;
120 screen->fb.greenMask = ((1 << green_bpc) - 1) << bpc;
121 screen->fb.redMask = screen->fb.blueMask << (green_bpc + bpc);
122 }
123
124 Bool
arcanInitialize(KdCardInfo * card,arcanPriv * priv)125 arcanInitialize(KdCardInfo * card, arcanPriv * priv)
126 {
127 trace("arcanInitialize");
128 priv->base = 0;
129 priv->bytes_per_line = 0;
130 return TRUE;
131 }
132
133 Bool
arcanCardInit(KdCardInfo * card)134 arcanCardInit(KdCardInfo * card)
135 {
136 arcanPriv *priv;
137 trace("arcanCardInit");
138
139 priv = (arcanPriv *) malloc(sizeof(arcanPriv));
140 if (!priv)
141 return FALSE;
142
143 if (!arcanInitialize(card, priv)) {
144 free(priv);
145 return FALSE;
146 }
147 card->driver = priv;
148
149 return TRUE;
150 }
151
152 Bool
arcanScreenInitialize(KdScreenInfo * screen,arcanScrPriv * scrpriv)153 arcanScreenInitialize(KdScreenInfo * screen, arcanScrPriv * scrpriv)
154 {
155 scrpriv->acon->hints =
156 SHMIF_RHINT_SUBREGION | SHMIF_RHINT_IGNORE_ALPHA |SHMIF_RHINT_VSIGNAL_EV;
157 trace("arcanScreenInitialize");
158
159 if (!screen->width || !screen->height) {
160 screen->width = scrpriv->acon->w;
161 screen->height = scrpriv->acon->h;
162 }
163
164 /* if the size dimensions exceed the permitted values, shrink. Also try and
165 * enable the color control subprotocol */
166 if (!arcan_shmif_resize_ext(scrpriv->acon, screen->width, screen->height,
167 (struct shmif_resize_ext){
168 #ifdef RANDR
169 .meta = SHMIF_META_CM
170 #endif
171 })){
172 screen->width = scrpriv->acon->w;
173 screen->height = scrpriv->acon->h;
174 }
175
176 arcan_shmifsub_getramp(scrpriv->acon, 0, &scrpriv->block);
177
178 /* default guess, we cache this between screen init/deinit */
179 if (!arcan_init)
180 arcan_shmif_initial(scrpriv->acon, &arcan_init);
181
182 if (arcan_init->density > 0){
183 screen->width_mm = (float)screen->width / (0.1 * arcan_init->density);
184 screen->height_mm = (float)screen->height / (0.1 * arcan_init->density);
185 }
186
187 scrpriv->randr = screen->randr;
188 if (1 || arcanGlamor)
189 setGlamorMask(screen);
190 else
191 setArcanMask(screen);
192 return arcanMapFramebuffer(screen);
193 }
194
195 static void
TranslateInput(struct arcan_shmif_cont * con,arcan_ioevent * ev,int * x,int * y)196 TranslateInput(struct arcan_shmif_cont* con, arcan_ioevent* ev, int* x, int* y)
197 {
198 if (ev->devkind == EVENT_IDEVKIND_MOUSE){
199 int flags = arcanInputPriv.pi->buttonState;
200 if (ev->datatype == EVENT_IDATATYPE_ANALOG){
201 /* buffer the relatives and push them in once fell swoop */
202 if (ev->input.analog.gotrel){
203 switch (ev->input.analog.nvalues){
204 case 1:
205 case 2:
206 case 3:
207 if (ev->subid == 0)
208 *x += ev->input.analog.axisval[0];
209 else if (ev->subid == 1)
210 *y += ev->input.analog.axisval[0];
211 break;
212 case 4:
213 *x += ev->input.analog.axisval[0];
214 *y += ev->input.analog.axisval[2];
215 break;
216 }
217 }
218 else {
219 static int ox, oy;
220 bool dirty = false;
221 flags |= KD_POINTER_DESKTOP;
222
223 switch (ev->input.analog.nvalues){
224 case 1: case 2:
225 if (ev->subid == 0){
226 dirty |= ev->input.analog.axisval[0] != ox;
227 ox = ev->input.analog.axisval[0];
228 }
229 else if (ev->subid == 1){
230 dirty |= ev->input.analog.axisval[0] != oy;
231 oy = ev->input.analog.axisval[0];
232 }
233 break;
234 case 3: case 4:
235 dirty |= ev->input.analog.axisval[0] != ox;
236 dirty |= ev->input.analog.axisval[2] != oy;
237 ox = ev->input.analog.axisval[0];
238 oy = ev->input.analog.axisval[2];
239 break;
240 }
241
242 if (dirty)
243 KdEnqueuePointerEvent(arcanInputPriv.pi, flags, ox, oy, 0);
244 }
245 }
246 else {
247 int ind = -1;
248 flags |= KD_MOUSE_DELTA;
249 switch (ev->subid){
250 case MBTN_LEFT_IND: ind = KD_BUTTON_1; break;
251 case MBTN_RIGHT_IND: ind = KD_BUTTON_3; break;
252 case MBTN_MIDDLE_IND: ind = KD_BUTTON_2; break;
253 case MBTN_WHEEL_UP_IND: ind = KD_BUTTON_4; break;
254 case MBTN_WHEEL_DOWN_IND: ind = KD_BUTTON_5; break;
255 default:
256 return;
257 }
258 if (ev->input.digital.active)
259 flags |= ind;
260 else
261 flags = flags & (~ind);
262 if (*x != 0 || *y != 0){
263 KdEnqueuePointerEvent(arcanInputPriv.pi, flags, *x, *y, 0);
264 *x = 0;
265 *y = 0;
266 }
267 KdEnqueuePointerEvent(arcanInputPriv.pi, flags, 0, 0, 0);
268 }
269 }
270 else if (ev->datatype == EVENT_IDATATYPE_TRANSLATED){
271 code_tbl[ev->input.translated.scancode % 512] = ev->input.translated.active;
272 enqueueKeyboard(
273 ev->input.translated.scancode, ev->input.translated.active);
274 }
275 }
276
277 #ifdef RANDR
278 static Bool
279 arcanRandRScreenResize(ScreenPtr pScreen,
280 CARD16 width, CARD16 height, CARD32 mmWidth, CARD32 mmHeight);
281 #else
282 static Bool
arcanRandRScreenResize(ScreenPtr pScreen,CARD16 width,CARD16 height,CARD32 mmWidth,CARD32 mmHeight)283 arcanRandRScreenResize(ScreenPtr pScreen,
284 CARD16 width, CARD16 height, CARD32 mmWidth, CARD32 mmHeight)
285 {
286 return false;
287 }
288 #endif
289
290 static
291 void
arcanDisplayHint(struct arcan_shmif_cont * con,int w,int h,int fl,int rgb,float ppcm)292 arcanDisplayHint(struct arcan_shmif_cont* con,
293 int w, int h, int fl, int rgb, float ppcm)
294 {
295 arcanScrPriv* apriv = con->user;
296
297 /* release on focus loss, open point, does this actually cover mods? */
298 if (fl & 4){
299 for (size_t i = 0; i < sizeof(code_tbl) / sizeof(code_tbl[0]); i++){
300 if (code_tbl[i]){
301 enqueueKeyboard(i, 1);
302 code_tbl[i] = 0;
303 }
304 }
305 KdEnqueuePointerEvent(arcanInputPriv.pi, KD_MOUSE_DELTA, 0, 0, 0);
306 }
307
308 if (arcanConfigPriv.no_dynamic_resize)
309 return;
310
311 if (w >= 640 && h >= 480 && (con->w != w || con->h != h) && !(fl & 1)){
312 #ifdef RANDR
313 if (ppcm == 0 && arcan_init)
314 ppcm = arcan_init->density;
315
316 RRScreenSetSizeRange(apriv->screen,
317 640, 480, PP_SHMPAGE_MAXW, PP_SHMPAGE_MAXH);
318 arcanRandRScreenResize(apriv->screen,
319 w, h,
320 ppcm > 0 ? (float)w / (0.1 * ppcm) : 0,
321 ppcm > 0 ? (float)h / (0.1 * ppcm) : 0
322 );
323 RRScreenSizeNotify(apriv->screen);
324 return;
325 #endif
326 }
327 /* NOTE:
328 * on focus lost or window hidden, should we just stop synching and
329 * waiting for it to return?
330 */
331 }
332
333 void
arcanFlushEvents(int fd,void * tag)334 arcanFlushEvents(int fd, void* tag)
335 {
336 int mx = 0, my = 0;
337 struct arcan_shmif_cont* con = arcan_shmif_primary(SHMIF_INPUT);
338 struct arcan_event ev;
339 if (!con || !con->user)
340 return;
341
342 while (arcan_shmif_poll(con, &ev) > 0){
343 if (ev.category == EVENT_IO){
344 TranslateInput(con, &(ev.io), &mx, &my);
345 }
346 else if (ev.category != EVENT_TARGET)
347 continue;
348 else
349 switch (ev.tgt.kind){
350 case TARGET_COMMAND_STEPFRAME:{
351 arcanScrPriv *scrpriv = con->user;
352 if (scrpriv->dirty){
353 arcan_shmif_signal(con, SHMIF_SIGVID | SHMIF_SIGBLK_NONE);
354 con->dirty.x1 = con->w;
355 con->dirty.y1 = con->h;
356 con->dirty.y2 = 0;
357 con->dirty.x2 = 0;
358 scrpriv->dirty = false;
359 }
360 }
361 case TARGET_COMMAND_RESET:
362 switch(ev.tgt.ioevs[0].iv){
363 /* not much 'state' that we can extract or track from the Xorg internals,
364 * possibly input related and likely not worth it */
365 case 0:
366 case 1:
367 break;
368 /* for recovery / hard-migrate, we don't really need to do anything yet */
369 case 2:
370 break;
371 /* swap-out monitored FD */
372 case 3:
373 InputThreadUnregisterDev(con->epipe);
374 InputThreadRegisterDev(con->epipe, (void*) arcanFlushEvents, con);
375 break;
376 }
377 break;
378 case TARGET_COMMAND_DISPLAYHINT:
379 arcanDisplayHint(con,
380 ev.tgt.ioevs[0].iv, ev.tgt.ioevs[1].iv,
381 ev.tgt.ioevs[2].iv, ev.tgt.ioevs[3].iv, ev.tgt.ioevs[4].iv);
382 break;
383 case TARGET_COMMAND_OUTPUTHINT:
384 break;
385 case TARGET_COMMAND_NEWSEGMENT:
386 /* Only thing we care about here is if a new output segment is pushed, that
387 * would indicate that we have received a buffer to 'provide' if a client
388 * attempts to read or capture anything from the root display. Clipboard is
389 * used with the aclip tool, so no need here - and mouse cursor registration is
390 * performed much earlier */
391 break;
392 case TARGET_COMMAND_EXIT:
393 CloseWellKnownConnections();
394 OsCleanup(1);
395 exit(1);
396 break;
397 default:
398 break;
399 }
400 }
401
402 /* aggregate mouse input events unless it's clicks,
403 * where we have to flush for the values to register correctly */
404 if (mx != 0 || my != 0){
405 KdEnqueuePointerEvent(arcanInputPriv.pi,
406 KD_MOUSE_DELTA | arcanInputPriv.pi->buttonState,
407 mx, my, 0
408 );
409 }
410 }
411
412 Bool
arcanScreenInit(KdScreenInfo * screen)413 arcanScreenInit(KdScreenInfo * screen)
414 {
415 arcanScrPriv *scrpriv;
416 struct arcan_shmif_cont* con = arcan_shmif_primary(SHMIF_INPUT);
417 trace("arcanScreenInit");
418 if (!con)
419 return FALSE;
420
421 scrpriv = calloc(1, sizeof(arcanScrPriv));
422 if (!scrpriv)
423 return FALSE;
424
425 if (!dixRegisterPrivateKey(&pixmap_private_key, PRIVATE_PIXMAP, 0)){
426 return FALSE;
427 }
428
429 /* primary connection is a allocated once and then retained for the length of
430 * the process */
431 if (con->user){
432 fprintf(stderr, "multiple screen support still missing\n");
433 abort();
434 }
435
436 scrpriv->pending_fd = -1;
437 scrpriv->acon = con;
438 arcan_shmifsub_getramp(scrpriv->acon, 0, &scrpriv->block);
439 con->user = scrpriv;
440
441 if (!scrpriv->acon){
442 free(scrpriv);
443 return FALSE;
444 }
445
446 screen->driver = scrpriv;
447 if (!arcanScreenInitialize(screen, scrpriv)) {
448 screen->driver = 0;
449 free(scrpriv);
450 return FALSE;
451 }
452
453 return TRUE;
454 }
455
arcanInternalDamageRedisplay(ScreenPtr pScreen)456 static void arcanInternalDamageRedisplay(ScreenPtr pScreen)
457 {
458 KdScreenPriv(pScreen);
459 KdScreenInfo *screen = pScreenPriv->screen;
460 arcanScrPriv *scrpriv = screen->driver;
461 RegionPtr region;
462 BoxPtr box;
463
464 if (!pScreen)
465 return;
466
467 region = DamageRegion(scrpriv->damage);
468
469 if (!RegionNotEmpty(region) || scrpriv->acon->addr->vready)
470 return;
471
472 /*
473 * We don't use fine-grained dirty regions really, the data gathered gave
474 * quite few benefits as cases with many dirty regions quickly exceeded the
475 * magic ratio where subtex- update vs full texture update tipped in favor
476 * of the latter.
477 */
478 box = RegionExtents(region);
479 if (box->x1 < scrpriv->acon->dirty.x1)
480 scrpriv->acon->dirty.x1 = box->x1;
481
482 if (box->x2 > scrpriv->acon->dirty.x2)
483 scrpriv->acon->dirty.x2 = box->x2;
484
485 if (box->y1 < scrpriv->acon->dirty.y1)
486 scrpriv->acon->dirty.y1 = box->y1;
487
488 if (box->y2 > scrpriv->acon->dirty.y2)
489 scrpriv->acon->dirty.y2 = box->y2;
490
491 #ifdef GLAMOR
492 if (scrpriv->in_glamor){
493 int fd = -1;
494 size_t stride = 0;
495 int fourcc = 0;
496
497 /* does glamor buffer somewhere internally? this do not seem to be
498 * plagued by tearing or locking issues, even though it likely should.
499 * maybe it's just because the tested display and simulated rate match?
500 * in that case, the delivery- approach used for non-glamor should work */
501 if (scrpriv->bo){
502 fd = gbm_bo_get_fd(scrpriv->bo);
503 stride = gbm_bo_get_stride(scrpriv->bo);
504 fourcc = DRM_FORMAT_XRGB8888;
505 }
506 else if (scrpriv->tex != -1){
507 uintptr_t disp;
508 arcan_shmifext_egl_meta(scrpriv->acon, &disp, NULL, NULL);
509 arcan_shmifext_gltex_handle(scrpriv->acon, disp,
510 scrpriv->tex, &fd, &stride, &fourcc);
511 }
512
513 arcan_shmif_signalhandle(scrpriv->acon,
514 SHMIF_SIGVID | SHMIF_SIGBLK_NONE,
515 fd, stride, fourcc);
516 if (-1 != scrpriv->pending_fd){
517 close(scrpriv->pending_fd);
518 }
519 scrpriv->pending_fd = fd;
520 }
521 #endif
522 /* use frame delivery event to indicate next time we should signal */
523 arcan_shmif_signal(scrpriv->acon, SHMIF_SIGVID | SHMIF_SIGBLK_NONE);
524 scrpriv->dirty = true;
525 DamageEmpty(scrpriv->damage);
526 }
527
onDamageDestroy(DamagePtr damage,void * closure)528 static void onDamageDestroy(DamagePtr damage, void *closure)
529 {
530 trace("OnArcanDamageDestroy(%p)", damage);
531 }
532
arcanSetInternalDamage(ScreenPtr pScreen)533 static Bool arcanSetInternalDamage(ScreenPtr pScreen)
534 {
535 KdScreenPriv(pScreen);
536 KdScreenInfo *screen = pScreenPriv->screen;
537 arcanScrPriv *scrpriv = screen->driver;
538 PixmapPtr pPixmap = NULL;
539
540 scrpriv->damage = DamageCreate((DamageReportFunc) 0,
541 (DamageDestroyFunc) onDamageDestroy,
542 DamageReportBoundingBox,
543 TRUE, pScreen, pScreen);
544
545 trace("arcanSetInternalDamage(%p)", scrpriv->damage);
546 pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
547
548 DamageRegister(&pPixmap->drawable, scrpriv->damage);
549 DamageSetReportAfterOp(scrpriv->damage, TRUE);
550
551 return TRUE;
552 }
553
554 Bool
arcanCreateResources(ScreenPtr pScreen)555 arcanCreateResources(ScreenPtr pScreen)
556 {
557 trace("arcanCreateResources");
558 return arcanSetInternalDamage(pScreen);
559 }
560
arcanUnsetInternalDamage(ScreenPtr pScreen)561 static void arcanUnsetInternalDamage(ScreenPtr pScreen)
562 {
563 KdScreenPriv(pScreen);
564 KdScreenInfo *screen = pScreenPriv->screen;
565 arcanScrPriv *scrpriv = screen->driver;
566 trace("arcanUnsetInternalDamage(%p)", scrpriv->damage);
567 if (scrpriv->damage){
568 DamageUnregister(scrpriv->damage);
569 DamageDestroy(scrpriv->damage);
570 scrpriv->damage = NULL;
571 }
572 }
573
574 static
ArcanSetPixmapVisitWindow(WindowPtr window,void * data)575 int ArcanSetPixmapVisitWindow(WindowPtr window, void *data)
576 {
577 ScreenPtr screen = window->drawable.pScreen;
578 trace("arcanSetPixmapVisitWindow");
579 if (screen->GetWindowPixmap(window) == data){
580 screen->SetWindowPixmap(window, screen->GetScreenPixmap(screen));
581 return WT_WALKCHILDREN;
582 }
583 return WT_DONTWALKCHILDREN;
584 }
585
586 #ifdef GLAMOR
587 /*
588 static
589 int drmFmt(int depth)
590 {
591 switch (depth){
592 case 16: return DRM_FORMAT_RGB565;
593 case 24: return DRM_FORMAT_XRGB8888;
594 case 32: return DRM_FORMAT_ARGB8888;
595 default:
596 return -1;
597 break;
598 }
599 }*/
600
601 static
gbmFmt(int depth)602 int gbmFmt(int depth)
603 {
604 switch (depth){
605 case 16: return GBM_FORMAT_RGB565;
606 case 24: return GBM_FORMAT_XRGB8888;
607 case 32: return GBM_FORMAT_ARGB8888;
608 default:
609 return -1;
610 break;
611 }
612 }
613
614 static
boToPixmap(ScreenPtr pScreen,struct gbm_bo * bo,int depth)615 PixmapPtr boToPixmap(ScreenPtr pScreen, struct gbm_bo* bo, int depth)
616 {
617 KdScreenPriv(pScreen);
618 KdScreenInfo *screen = pScreenPriv->screen;
619 arcanScrPriv *scrpriv = screen->driver;
620 PixmapPtr pixmap;
621 struct pixmap_ext *ext_pixmap;
622 uintptr_t adisp, actx;
623 /* Unfortunately shmifext- don't expose the buffer-import setup yet,
624 * waiting for the whole GBM v Streams to sort itself out, so just
625 * replicate that code once more. */
626 pixmap = glamor_create_pixmap(pScreen,
627 gbm_bo_get_width(bo),
628 gbm_bo_get_height(bo),
629 depth,
630 GLAMOR_CREATE_PIXMAP_NO_TEXTURE);
631
632 if (pixmap == NULL) {
633 trace("ArcanDRI3PixmapFromFD()::Couldn't create pixmap from BO");
634 gbm_bo_destroy(bo);
635 return NULL;
636 }
637
638 /* Could probably do more sneaky things here to forward this buffer
639 * to arcan as its own window/source to cut down on the dedicated
640 * fullscreen stuff. */
641 arcan_shmifext_make_current(scrpriv->acon);
642 ext_pixmap = malloc(sizeof(struct pixmap_ext));
643 if (!ext_pixmap){
644 trace("ArcanDRI3PixmapFromFD()::Couldn't allocate pixmap metadata");
645 gbm_bo_destroy(bo);
646 glamor_destroy_pixmap(pixmap);
647 return NULL;
648 }
649
650 arcan_shmifext_egl_meta(scrpriv->acon, &adisp, NULL, &actx);
651 ext_pixmap->bo = bo;
652 ext_pixmap->image = eglCreateImageKHR((EGLDisplay) adisp,
653 (EGLContext) actx,
654 EGL_NATIVE_PIXMAP_KHR,
655 ext_pixmap->bo, NULL);
656
657 glGenTextures(1, &ext_pixmap->texture);
658 glBindTexture(GL_TEXTURE_2D, ext_pixmap->texture);
659 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
660 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
661
662 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, ext_pixmap->image);
663 glBindTexture(GL_TEXTURE_2D, 0);
664
665 dixSetPrivate(&pixmap->devPrivates, &pixmap_private_key, ext_pixmap);
666 glamor_set_pixmap_texture(pixmap, ext_pixmap->texture);
667 glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
668
669 return pixmap;
670 }
671 #endif
672
673 static
arcanGlamorCreateScreenResources(ScreenPtr pScreen)674 Bool arcanGlamorCreateScreenResources(ScreenPtr pScreen)
675 {
676 #ifdef GLAMOR
677 KdScreenPriv(pScreen);
678 KdScreenInfo *screen = pScreenPriv->screen;
679 arcanScrPriv *scrpriv = screen->driver;
680 PixmapPtr oldpix, newpix = NULL;
681 uintptr_t dev;
682 int fmt;
683
684 trace("arcanGlamorCreateScreenResources");
685
686 oldpix = pScreen->GetScreenPixmap(pScreen);
687 if (-1 == arcan_shmifext_dev(scrpriv->acon, &dev, false)){
688 trace("ArcanDRI3PixmapFromFD()::Couldn't get device handle");
689 return false;
690 }
691
692 fmt = gbmFmt(pScreen->rootDepth);
693 if (-1 != fmt){
694 struct gbm_bo *bo = gbm_bo_create((struct gbm_device*) dev,
695 pScreen->width,
696 pScreen->height,
697 fmt,
698 GBM_BO_USE_SCANOUT |
699 GBM_BO_USE_RENDERING);
700 newpix = boToPixmap(pScreen, bo, pScreen->rootDepth);
701 scrpriv->bo = bo;
702 }
703 if (!newpix){
704 newpix = pScreen->CreatePixmap(pScreen,
705 pScreen->width,
706 pScreen->height,
707 pScreen->rootDepth,
708 CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
709 scrpriv->bo = NULL;
710 scrpriv->tex = (newpix ? glamor_get_pixmap_texture(newpix) : -1);
711 }
712
713 if (newpix){
714 trace("SetScreenPixmap(new)");
715 pScreen->SetScreenPixmap(newpix);
716 /* glamor_set_screen_pixmap(newpix, NULL); */
717
718 if (pScreen->root && pScreen->SetWindowPixmap)
719 TraverseTree(pScreen->root, ArcanSetPixmapVisitWindow, oldpix);
720
721 SetRootClip(pScreen, ROOT_CLIP_FULL);
722 }
723
724 return TRUE;
725 #endif
726 return FALSE;
727 }
728
729 void *
arcanWindowLinear(ScreenPtr pScreen,CARD32 row,CARD32 offset,int mode,CARD32 * size,void * closure)730 arcanWindowLinear(ScreenPtr pScreen,
731 CARD32 row,
732 CARD32 offset, int mode, CARD32 *size, void *closure)
733 {
734 KdScreenPriv(pScreen);
735 arcanPriv *priv = pScreenPriv->card->driver;
736
737 if (!pScreenPriv->enabled)
738 return 0;
739 *size = priv->bytes_per_line;
740 return priv->base + row * priv->bytes_per_line;
741 }
742
743 Bool
arcanMapFramebuffer(KdScreenInfo * screen)744 arcanMapFramebuffer(KdScreenInfo * screen)
745 {
746 arcanScrPriv *scrpriv = screen->driver;
747 KdPointerMatrix m;
748
749 trace("arcanMapFramebuffer");
750 KdComputePointerMatrix(&m, scrpriv->randr, screen->width, screen->height);
751 KdSetPointerMatrix(&m);
752
753 if (scrpriv->in_glamor){
754 screen->fb.frameBuffer = NULL;
755 }
756 else {
757 screen->fb.byteStride = scrpriv->acon->stride;
758 screen->fb.pixelStride = scrpriv->acon->pitch;
759 screen->fb.frameBuffer = (CARD8 *) (scrpriv->acon->vidp);
760 }
761 return TRUE;
762 }
763
764 void
arcanSetScreenSizes(ScreenPtr pScreen)765 arcanSetScreenSizes(ScreenPtr pScreen)
766 {
767 KdScreenPriv(pScreen);
768 KdScreenInfo *screen = pScreenPriv->screen;
769 arcanScrPriv *scrpriv = screen->driver;
770 float ind = ARCAN_SHMPAGE_DEFAULT_PPCM * 0.1;
771 int inw, inh;
772
773 /* default guess */
774 trace("arcanSetScreenSizes");
775 inw = scrpriv->acon->w;
776 inh = scrpriv->acon->h;
777
778 if (arcan_init && arcan_init->density > 0)
779 ind = arcan_init->density * 0.1;
780
781 pScreen->width = inw;
782 pScreen->height = inh;
783 pScreen->mmWidth = (float) inw / ind;
784 pScreen->mmHeight = (float) inh / ind;
785 }
786
787 Bool
arcanUnmapFramebuffer(KdScreenInfo * screen)788 arcanUnmapFramebuffer(KdScreenInfo * screen)
789 {
790 trace("arcanUnmapFramebuffer");
791 /*
792 * free(priv->base);
793 priv->base = NULL;
794 */
795 return TRUE;
796 }
797
arcanInit(void)798 int arcanInit(void)
799 {
800 struct arcan_shmif_cont* con = calloc(1, sizeof(struct arcan_shmif_cont));
801 char dispstr[512] = "";
802 if (!con)
803 return 0;
804
805 /* windisplay.c */
806 trace("ArcanInit");
807 if (_XSERVTransIsListening("local")){
808 snprintf(dispstr, 512, "%s:%d", display, 0);
809 }
810 else if (_XSERVTransIsListening("inet")){
811 snprintf(dispstr, 512, "127.0.0.1:%s.%d", display, 0);
812 }
813 else if (_XSERVTransIsListening("inet6")){
814 snprintf(dispstr, 512, "::1:%s.%d", display, 0);
815 }
816
817 *con = arcan_shmif_open_ext(0, NULL, (struct shmif_open_ext){
818 .type = SEGID_BRIDGE_X11,
819 arcanConfigPriv.title ? arcanConfigPriv.title : "Xorg",
820 arcanConfigPriv.ident ? arcanConfigPriv.ident : dispstr
821 }, sizeof(struct shmif_open_ext));
822 if (!con->addr){
823 free(con);
824 return 0;
825 }
826
827 /* indicate that we can/want to do color-management, RandR will check this
828 * with the arcan_shmif_substruct calls */
829 arcan_shmif_resize_ext(con, con->w, con->h,
830 (struct shmif_resize_ext){
831 #ifdef RANDR
832 .meta = SHMIF_META_CM
833 #endif
834 });
835
836 /* try and request a mouse segment for accelerated mouse (unless disabled)
837 * or at least indicate that we do software cursor rendering */
838 if (arcanConfigPriv.accel_cursor){
839 arcan_shmif_enqueue(con, &(struct arcan_event){
840 .ext.kind = ARCAN_EVENT(SEGREQ),
841 .ext.segreq.width = 32,
842 .ext.segreq.height = 32,
843 .ext.segreq.kind = SEGID_CURSOR,
844 .ext.segreq.id = 0xbad1dea
845 });
846
847 /*
848 * wd->cursor = arcan_shmif_acquire(&wd->mcont, NULL, SEGID_CURSOR, 0);
849 printf("parent REJECTED cursor\n");
850 wd->cursor_reject = true;
851 */
852 }
853
854
855 /* we will do dirty- region updates rather than full swaps, and alpha
856 * channel will be set to 00 so ignore that one */
857 arcan_shmif_setprimary(SHMIF_INPUT, con);
858
859 return 1;
860 }
861
arcanFini(void)862 void arcanFini(void)
863 {
864 struct arcan_shmif_cont* con = arcan_shmif_primary(SHMIF_INPUT);
865 trace("ArcanFini");
866 if (con){
867 arcan_shmif_drop(con);
868 }
869 }
870
871 #ifdef RANDR
872 Bool
arcanRandRGetInfo(ScreenPtr pScreen,Rotation * rotations)873 arcanRandRGetInfo(ScreenPtr pScreen, Rotation * rotations)
874 {
875 KdScreenPriv(pScreen);
876 KdScreenInfo *screen = pScreenPriv->screen;
877 arcanScrPriv *scrpriv = screen->driver;
878 RRScreenSizePtr pSize;
879 Rotation randr;
880 int n;
881
882 trace("ArcanRandRGetInfo");
883 *rotations = RR_Rotate_0;
884
885 for (n = 0; n < pScreen->numDepths; n++)
886 if (pScreen->allowedDepths[n].numVids)
887 break;
888 if (n == pScreen->numDepths)
889 return FALSE;
890
891 pSize = RRRegisterSize(pScreen,
892 screen->width,
893 screen->height, screen->width_mm, screen->height_mm);
894
895 randr = KdSubRotation(scrpriv->randr, screen->randr);
896
897 RRSetCurrentConfig(pScreen, randr, 0, pSize);
898
899 return TRUE;
900 }
901
902 static Bool
arcanRandRScreenResize(ScreenPtr pScreen,CARD16 width,CARD16 height,CARD32 mmWidth,CARD32 mmHeight)903 arcanRandRScreenResize(ScreenPtr pScreen,
904 CARD16 width, CARD16 height, CARD32 mmWidth, CARD32 mmHeight)
905 {
906 KdScreenPriv(pScreen);
907 KdScreenInfo *screen = pScreenPriv->screen;
908 RRScreenSize size = {0};
909 arcanScrPriv *scrpriv = screen->driver;
910
911 if (width == screen->width && height == screen->height)
912 return FALSE;
913
914 trace("ArcanRandRScreenResize");
915 size.width = width;
916 size.height = height;
917 size.mmWidth = mmWidth;
918 size.mmHeight = mmHeight;
919
920 if (arcanRandRSetConfig(pScreen, screen->randr, 0, &size)){
921 RRModePtr mode = arcan_cvt(width, height, 60.0 / 1000.0, 0, 0);
922
923 if (!scrpriv->randrOutput){
924 trace("arcanRandRInit(No output)");
925 return FALSE;
926 }
927
928 /* need something else here, like Crtcnotify */
929 RROutputSetModes(scrpriv->randrOutput, &mode, 1, 1);
930 RRCrtcGammaSetSize(scrpriv->randrCrtc, scrpriv->block.plane_sizes[0] / 3);
931 RROutputSetPhysicalSize(scrpriv->randrOutput, size.mmWidth, size.mmHeight);
932
933 /*
934 RCrtcNotify(scrpriv->randrOutput, mode, 0, 0, RR_ROTATE_0, NULL, 1, ???)
935 */
936 }
937
938 return TRUE;
939 }
940
941 Bool
arcanRandRSetConfig(ScreenPtr pScreen,Rotation randr,int rate,RRScreenSizePtr pSize)942 arcanRandRSetConfig(ScreenPtr pScreen,
943 Rotation randr, int rate, RRScreenSizePtr pSize)
944 {
945 KdScreenPriv(pScreen);
946 KdScreenInfo *screen = pScreenPriv->screen;
947 arcanScrPriv *scrpriv = screen->driver;
948 Bool wasEnabled = pScreenPriv->enabled;
949 arcanScrPriv oldscr;
950 int oldwidth;
951 int oldheight;
952 int oldmmwidth;
953 int oldmmheight;
954 int newwidth, newheight;
955
956 /* Ignore rotations etc. If those are desired properties, it will happen on
957 * a higher level. */
958 trace("ArcanRandRSetConfig");
959 newwidth = pSize->width;
960 newheight = pSize->height;
961
962 if (wasEnabled)
963 KdDisableScreen(pScreen);
964
965 oldscr = *scrpriv;
966
967 oldwidth = screen->width;
968 oldheight = screen->height;
969 oldmmwidth = pScreen->mmWidth;
970 oldmmheight = pScreen->mmHeight;
971
972 /*
973 * Set new configuration
974 */
975
976 scrpriv->randr = KdAddRotation(screen->randr, randr);
977 arcan_shmif_resize_ext(scrpriv->acon, newwidth, newheight,
978 (struct shmif_resize_ext){
979 #ifdef RANDR
980 .meta = SHMIF_META_CM
981 #endif
982 });
983 arcan_shmifsub_getramp(scrpriv->acon, 0, &scrpriv->block);
984 arcanUnmapFramebuffer(screen);
985
986 if (!arcanMapFramebuffer(screen))
987 goto bail4;
988
989 arcanUnsetInternalDamage(pScreen);
990
991 arcanSetScreenSizes(screen->pScreen);
992
993 #ifdef GLAMOR
994 if (arcanGlamor){
995 arcan_shmifext_make_current(scrpriv->acon);
996 arcanGlamorCreateScreenResources(pScreen);
997 }
998 #endif
999 if (!arcanSetInternalDamage(screen->pScreen))
1000 goto bail4;
1001
1002 /*
1003 * Set frame buffer mapping
1004 */
1005 (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap(pScreen),
1006 pScreen->width,
1007 pScreen->height,
1008 screen->fb.depth,
1009 screen->fb.bitsPerPixel,
1010 screen->fb.byteStride,
1011 screen->fb.frameBuffer);
1012
1013 KdSetSubpixelOrder(pScreen, scrpriv->randr);
1014
1015 if (wasEnabled)
1016 KdEnableScreen(pScreen);
1017
1018 RRScreenSizeNotify(pScreen);
1019
1020 return TRUE;
1021
1022 bail4:
1023 arcanUnmapFramebuffer(screen);
1024 *scrpriv = oldscr;
1025 (void) arcanMapFramebuffer(screen);
1026 pScreen->width = oldwidth;
1027 pScreen->height = oldheight;
1028 pScreen->mmWidth = oldmmwidth;
1029 pScreen->mmHeight = oldmmheight;
1030
1031 if (wasEnabled)
1032 KdEnableScreen(pScreen);
1033 return FALSE;
1034 }
1035
1036 #if RANDR_12_INTERFACE
arcanRandRSetGamma(ScreenPtr pScreen,RRCrtcPtr crtc)1037 static Bool arcanRandRSetGamma(ScreenPtr pScreen, RRCrtcPtr crtc)
1038 {
1039 KdScreenPriv(pScreen);
1040 /* rrScrPrivPtr pScrPriv; */
1041 KdScreenInfo *screen = pScreenPriv->screen;
1042 arcanScrPriv *scrpriv = screen->driver;
1043
1044 size_t plane_sz = scrpriv->block.plane_sizes[0] / 3;
1045
1046 for (size_t i = 0, j = 0; i < crtc->gammaSize && j < plane_sz; i++, j++){
1047 scrpriv->block.planes[i] = (float)crtc->gammaRed[i] / 65536.0f;
1048 scrpriv->block.planes[i+plane_sz] = (float)crtc->gammaGreen[i] / 65536.0f;
1049 scrpriv->block.planes[i+2*plane_sz] = (float)crtc->gammaBlue[i] / 65536.0f;
1050 }
1051
1052 return arcan_shmifsub_setramp(scrpriv->acon, 0, &scrpriv->block) ? TRUE : FALSE;
1053 }
1054
arcanRandRGetGamma(ScreenPtr pScreen,RRCrtcPtr crtc)1055 static Bool arcanRandRGetGamma(ScreenPtr pScreen, RRCrtcPtr crtc)
1056 {
1057 KdScreenPriv(pScreen);
1058 /* rrScrPrivPtr pScrPriv; */
1059 KdScreenInfo *screen = pScreenPriv->screen;
1060 arcanScrPriv *scrpriv = screen->driver;
1061 arcan_shmifsub_getramp(scrpriv->acon, 0, &scrpriv->block);
1062 size_t plane_sz = scrpriv->block.plane_sizes[0] / 3;
1063
1064 for (size_t i = 0; i < crtc->gammaSize && i < scrpriv->block.plane_sizes[0]; i++){
1065 crtc->gammaRed[i] = scrpriv->block.planes[i] * 65535;
1066 crtc->gammaGreen[i] = scrpriv->block.planes[i + plane_sz] * 65535;
1067 crtc->gammaBlue[i] = scrpriv->block.planes[i + plane_sz + plane_sz] * 65535;
1068 }
1069
1070 return TRUE;
1071 }
1072 #endif
1073
1074 Bool
arcanRandRInit(ScreenPtr pScreen)1075 arcanRandRInit(ScreenPtr pScreen)
1076 {
1077 KdScreenPriv(pScreen);
1078 rrScrPrivPtr pScrPriv;
1079 KdScreenInfo *screen = pScreenPriv->screen;
1080 arcanScrPriv *scrpriv = screen->driver;
1081 scrpriv->screen = pScreen;
1082
1083 if (!RRScreenInit(pScreen))
1084 return FALSE;
1085
1086 trace("ArcanRandRInit");
1087 pScrPriv = rrGetScrPriv(pScreen);
1088 pScrPriv->rrGetInfo = arcanRandRGetInfo;
1089 pScrPriv->rrSetConfig = arcanRandRSetConfig;
1090
1091 RRScreenSetSizeRange(pScreen, 640, 480, PP_SHMPAGE_MAXW, PP_SHMPAGE_MAXH);
1092
1093 #if RANDR_12_INTERFACE
1094 pScrPriv->rrScreenSetSize = arcanRandRScreenResize;
1095 pScrPriv->rrCrtcSetGamma = arcanRandRSetGamma;
1096 pScrPriv->rrCrtcGetGamma = arcanRandRGetGamma;
1097 #endif
1098
1099 /* NOTE regarding data model:
1100 * to the RandR screen, we create an Output that is assigned a Crtc
1101 * to which we attach one or several modes. We then notify rander as to
1102 * changes in the Crtc config. It is the gamma ramps of this crtc that
1103 * we can then finally access. */
1104 scrpriv->randrOutput = RROutputCreate(pScreen, "screen", 6, NULL);
1105 scrpriv->randrCrtc = RRCrtcCreate(pScreen, scrpriv->randrOutput);
1106 if (!scrpriv->randrCrtc){
1107 trace("arcanRandRInit(Failed to create CRTC)");
1108 return FALSE;
1109 }
1110
1111 RRCrtcSetRotations(scrpriv->randrCrtc, RR_Rotate_0);
1112 RRCrtcGammaSetSize(scrpriv->randrCrtc, scrpriv->block.plane_sizes[0] / 3);
1113
1114 RROutputSetCrtcs(scrpriv->randrOutput, &scrpriv->randrCrtc, 1);
1115 RROutputSetConnection(scrpriv->randrOutput, RR_Connected);
1116
1117 return TRUE;
1118 }
1119 #endif
1120
1121 #ifdef GLAMOR
1122 static
arcanGlamorEglMakeCurrent(struct glamor_context * ctx)1123 void arcanGlamorEglMakeCurrent(struct glamor_context *ctx)
1124 {
1125 trace("ArcanGlamorEglMakeCurrent");
1126 arcan_shmifext_make_current((struct arcan_shmif_cont*) ctx->ctx);
1127 }
1128
1129 _X_EXPORT int
glamor_egl_fd_from_pixmap(ScreenPtr screen,PixmapPtr pixmap,CARD16 * stride,CARD32 * size)1130 glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
1131 CARD16 *stride, CARD32 *size)
1132 {
1133 return -1;
1134 }
1135
1136 _X_EXPORT int
glamor_egl_fds_from_pixmap(ScreenPtr screen,PixmapPtr pixmap,int * fds,uint32_t * strides,uint32_t * offsets,uint64_t * modifier)1137 glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
1138 uint32_t *strides, uint32_t *offsets,
1139 uint64_t *modifier)
1140 {
1141 return 0;
1142 /* return number of fds, write into fds, trides, offsets, modifiers */
1143 }
1144
1145
glamor_egl_dri3_fd_name_from_tex(ScreenPtr pScreen,PixmapPtr pixmap,unsigned int tex,Bool want_name,CARD16 * stride,CARD32 * size)1146 int glamor_egl_dri3_fd_name_from_tex(ScreenPtr pScreen,
1147 PixmapPtr pixmap,
1148 unsigned int tex,
1149 Bool want_name, CARD16 *stride, CARD32 *size)
1150 {
1151 KdScreenPriv(pScreen);
1152 KdScreenInfo *screen = pScreenPriv->screen;
1153 arcanScrPriv *scrpriv = screen->driver;
1154 size_t dstr;
1155 int fmt, fd;
1156
1157 trace("(arcan) glamor_egl_dri3_fd_name_from_tex");
1158 *size = pixmap->drawable.width * (*stride);
1159
1160 if (arcan_shmifext_gltex_handle(scrpriv->acon, 0,
1161 tex, &fd, &dstr, &fmt)){
1162 *stride = dstr;
1163 return fd;
1164 }
1165
1166 *stride = 0;
1167 *size = 0;
1168 return -1;
1169 }
1170
1171 void
glamor_egl_screen_init(ScreenPtr pScreen,struct glamor_context * glamor_ctx)1172 glamor_egl_screen_init(ScreenPtr pScreen, struct glamor_context *glamor_ctx)
1173 {
1174 KdScreenPriv(pScreen);
1175 KdScreenInfo *screen = pScreenPriv->screen;
1176 arcanScrPriv *scrpriv = screen->driver;
1177 uintptr_t egl_disp = 0, egl_ctx = 0;
1178 arcan_shmifext_egl_meta(scrpriv->acon, &egl_disp, NULL, &egl_ctx);
1179
1180 trace("(Arcan) glamor_egl_screen_init");
1181 glamor_ctx->ctx = (void*)(scrpriv->acon);
1182 glamor_ctx->display = (EGLDisplay) egl_disp;
1183 glamor_ctx->make_current = arcanGlamorEglMakeCurrent;
1184 arcan_shmifext_make_current(scrpriv->acon);
1185 /*
1186 * something when this is done breaks damage regions
1187 */
1188 if (!arcanConfigPriv.no_dri3)
1189 glamor_enable_dri3(pScreen);
1190 }
1191
arcanGlamorEnable(ScreenPtr pScreen)1192 void arcanGlamorEnable(ScreenPtr pScreen)
1193 {
1194 KdScreenPriv(pScreen);
1195 KdScreenInfo *screen = pScreenPriv->screen;
1196 arcanScrPriv *scrpriv = screen->driver;
1197 trace("ArcanGlamorEnable");
1198 scrpriv->in_glamor = TRUE;
1199 }
1200
arcanGlamorDisable(ScreenPtr pScreen)1201 void arcanGlamorDisable(ScreenPtr pScreen)
1202 {
1203 KdScreenPriv(pScreen);
1204 KdScreenInfo *screen = pScreenPriv->screen;
1205 arcanScrPriv *scrpriv = screen->driver;
1206 trace("ArcanGlamorDisable");
1207 if (scrpriv){
1208 scrpriv->in_glamor = FALSE;
1209 }
1210 }
1211
arcanGlamorFini(ScreenPtr pScreen)1212 void arcanGlamorFini(ScreenPtr pScreen)
1213 {
1214 KdScreenPriv(pScreen);
1215 KdScreenInfo *screen = pScreenPriv->screen;
1216 arcanScrPriv *scrpriv = screen->driver;
1217 trace("ArcanGlamorFini");
1218 if (scrpriv){
1219 arcan_shmifext_drop(scrpriv->acon);
1220 }
1221 glamor_fini(pScreen);
1222 }
1223
dri3FdFromPixmap(ScreenPtr pScreen,PixmapPtr pixmap,CARD16 * stride,CARD32 * size)1224 static int dri3FdFromPixmap(ScreenPtr pScreen, PixmapPtr pixmap,
1225 CARD16 *stride, CARD32 *size)
1226 {
1227 struct pixmap_ext *ext_pixmap = dixLookupPrivate(
1228 &pixmap->devPrivates,
1229 &pixmap_private_key);
1230 trace("ArcanDRI3FdFromPixmap");
1231 if (!ext_pixmap || !ext_pixmap->bo){
1232 return -1;
1233 }
1234
1235 *stride = gbm_bo_get_stride(ext_pixmap->bo);
1236 *size = pixmap->drawable.width * *stride;
1237
1238 return gbm_bo_get_fd(ext_pixmap->bo);
1239 }
1240
dri3PixmapFromFd(ScreenPtr pScreen,int fd,CARD16 w,CARD16 h,CARD16 stride,CARD8 depth,CARD8 bpp)1241 static PixmapPtr dri3PixmapFromFd(ScreenPtr pScreen, int fd,
1242 CARD16 w, CARD16 h, CARD16 stride,
1243 CARD8 depth, CARD8 bpp)
1244 {
1245 KdScreenPriv(pScreen);
1246 KdScreenInfo *screen = pScreenPriv->screen;
1247 arcanScrPriv *scrpriv = screen->driver;
1248 uintptr_t dev;
1249 struct gbm_bo *bo;
1250 int gbm_fmt = gbmFmt(depth);
1251 struct gbm_import_fd_data data = {
1252 .fd = fd, .width = w, .height = h, .stride = stride };
1253
1254 trace("ArcanDRI3PixmapFromFD(%d, %d, %d, %d, %d)",
1255 (int)w, (int)h,
1256 (int)stride, (int)depth,
1257 (int)bpp );
1258
1259 if (!scrpriv->in_glamor){
1260 trace("ArcanDRI3PixmapFromFD()::Not in GLAMOR state");
1261 return NULL;
1262 }
1263
1264 if (!w || !h || bpp != BitsPerPixel(depth) ||
1265 stride < w * (bpp / 8)){
1266 trace("ArcanDRI3PixmapFromFD()::Bad arguments");
1267 return NULL;
1268 }
1269
1270 if (-1 == gbm_fmt){
1271 ErrorF("ArcanDRI3PixmapFromFD()::unknown input format");
1272 return NULL;
1273 }
1274
1275 if (-1 == arcan_shmifext_dev(scrpriv->acon, &dev, false)){
1276 trace("ArcanDRI3PixmapFromFD()::Couldn't get device handle");
1277 }
1278
1279 bo = gbm_bo_import((struct gbm_device*)dev, GBM_BO_IMPORT_FD,
1280 &data, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
1281 if (bo == NULL){
1282 trace("ArcanDRI3PixmapFromFD()::Couldn't import BO");
1283 return NULL;
1284 }
1285
1286 return boToPixmap(pScreen, bo, depth);
1287 }
1288
dri3Open(ClientPtr client,ScreenPtr pScreen,RRProviderPtr provider,int * pfd)1289 static int dri3Open(ClientPtr client,
1290 ScreenPtr pScreen,
1291 RRProviderPtr provider,
1292 int *pfd)
1293 {
1294 KdScreenPriv(pScreen);
1295 KdScreenInfo *screen = pScreenPriv->screen;
1296 arcanScrPriv *scrpriv = screen->driver;
1297 int fd;
1298
1299 if (arcanConfigPriv.no_dri3)
1300 return BadAlloc;
1301
1302 fd = arcan_shmifext_dev(scrpriv->acon, NULL, true);
1303 trace("ArcanDri3Open(%d)", fd);
1304 if (-1 != fd){
1305 *pfd = fd;
1306 return Success;
1307 }
1308 return BadAlloc;
1309 }
1310
1311 static dri3_screen_info_rec dri3_info = {
1312 .version = 1,
1313 .open_client = dri3Open,
1314 .pixmap_from_fd = dri3PixmapFromFd,
1315 .fd_from_pixmap = dri3FdFromPixmap,
1316 /* more here these days (due to modifiers):
1317 * dri3_pixmap_from_fds,
1318 * dri3_fds_from_pixmap,
1319 * dri3_get_formats_proc,
1320 * dri3_get_modifiers_proc,
1321 * dri3_get_drawable_modifiers_proc
1322 */
1323 };
1324
arcanGlamorInit(ScreenPtr pScreen)1325 Bool arcanGlamorInit(ScreenPtr pScreen)
1326 {
1327 KdScreenPriv(pScreen);
1328 KdScreenInfo *screen = pScreenPriv->screen;
1329 arcanScrPriv *scrpriv = screen->driver;
1330
1331 /* It may be better to create a subsurface that we escalate to GL, and map
1332 * the placement of this surface relative to the display similar to old-style
1333 * overlays. */
1334
1335 struct arcan_shmifext_setup defs = arcan_shmifext_defaults(scrpriv->acon);
1336 int errc;
1337 defs.depth = 0;
1338 defs.alpha = 0;
1339 defs.major = GLAMOR_GL_CORE_VER_MAJOR;
1340 defs.minor = GLAMOR_GL_CORE_VER_MINOR;
1341 defs.mask = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
1342 trace("arcanGlamorInit");
1343
1344 defs.builtin_fbo = false;
1345 errc = arcan_shmifext_setup(scrpriv->acon, defs);
1346 if (errc != SHMIFEXT_OK){
1347 ErrorF("xarcan/glamor::init() - EGL context failed (reason: %d), "
1348 "lowering version\n", errc);
1349 defs.major = 2;
1350 defs.minor = 1;
1351 defs.mask = 0;
1352 if (SHMIFEXT_OK != arcan_shmifext_setup(scrpriv->acon, defs)){
1353 ErrorF("xarcan/glamor::init(21) - EGL context failed again, giving up");
1354 return FALSE;
1355 }
1356 }
1357 #ifdef XV
1358 /* Seem to be some Kdrive wrapper to deal with less of this crap,
1359 * though is it still relevant / needed?
1360 * arcanGlamorXvInit(pScreen);
1361 */
1362 #endif
1363
1364 if (glamor_init(pScreen, GLAMOR_USE_EGL_SCREEN | GLAMOR_NO_DRI3)){
1365 scrpriv->in_glamor = TRUE;
1366 }
1367 else {
1368 ErrorF("arcanGlamorInit() - failed to initialize glamor");
1369 goto bail;
1370 }
1371 if (!arcanConfigPriv.no_dri3){
1372 if (!dri3_screen_init(pScreen, &dri3_info)){
1373 ErrorF("arcanGlamorInit() - failed to set DRI3");
1374 arcan_shmifext_drop(scrpriv->acon);
1375 goto bail;
1376 }
1377 }
1378
1379 scrpriv->CreateScreenResources = pScreen->CreateScreenResources;
1380 pScreen->CreateScreenResources = arcanGlamorCreateScreenResources;
1381
1382 return TRUE;
1383 bail:
1384 arcan_shmifext_drop(scrpriv->acon);
1385 scrpriv->in_glamor = FALSE;
1386 return FALSE;
1387 }
1388 #endif
1389
1390 static void
arcanScreenBlockHandler(ScreenPtr pScreen,void * timeout)1391 arcanScreenBlockHandler(ScreenPtr pScreen, void* timeout)
1392 {
1393 KdScreenPriv(pScreen);
1394 KdScreenInfo *screen = pScreenPriv->screen;
1395 arcanScrPriv *scrpriv = screen->driver;
1396
1397 /*
1398 * This one is rather unfortunate as it seems to be called 'whenever' and we
1399 * don't know the synch- state of the contents in the buffer. At the same
1400 * time, it doesn't trigger when idle- so we can't just skip synching and wait
1401 * for the next one. We can also set the context to be in event-frame delivery
1402 * mode and use the STEPFRAME event as a trigger to signal-if-dirty
1403 */
1404 // trace("arcanScreenBlockHandler(%lld)",(long long) currentTime.milliseconds);
1405 pScreen->BlockHandler = scrpriv->BlockHandler;
1406 (*pScreen->BlockHandler)(pScreen, timeout);
1407 scrpriv->BlockHandler = pScreen->BlockHandler;
1408 pScreen->BlockHandler = arcanScreenBlockHandler;
1409
1410 if (scrpriv->damage)
1411 arcanInternalDamageRedisplay(pScreen);
1412 /*
1413 * else if (!arcan_shmif_signalstatus)
1414 arcan_shmif_signal(scrpriv->acon, SHMIF_SIGVID | SHMIF_SIGBLK_NONE);
1415 */
1416 }
1417
1418 Bool
arcanCreateColormap(ColormapPtr pmap)1419 arcanCreateColormap(ColormapPtr pmap)
1420 {
1421 trace("arcanCreateColormap");
1422 return fbInitializeColormap(pmap);
1423 }
1424
1425 Bool
arcanInitScreen(ScreenPtr pScreen)1426 arcanInitScreen(ScreenPtr pScreen)
1427 {
1428 pScreen->CreateColormap = arcanCreateColormap;
1429 trace("arcanInitScreen");
1430 return TRUE;
1431 }
1432
1433 static Bool
arcanCloseScreenWrap(ScreenPtr pScreen)1434 arcanCloseScreenWrap(ScreenPtr pScreen)
1435 {
1436 trace("arcanCloseScreenWrap");
1437 /* arcanCloseScreen(pScreen); */
1438 return TRUE;
1439 }
1440 static RRCrtcPtr
arcanPresentGetCrtc(WindowPtr window)1441 arcanPresentGetCrtc(WindowPtr window)
1442 {
1443 ScreenPtr pScreen = window->drawable.pScreen;
1444 KdScreenPriv(pScreen);
1445 KdScreenInfo *screen = pScreenPriv->screen;
1446 arcanScrPriv *scrpriv = screen->driver;
1447 trace("present:get_crtc");
1448
1449 if (!scrpriv)
1450 return NULL;
1451
1452 return scrpriv->randrCrtc;
1453 }
1454
arcanPresentGetUstMsc(RRCrtcPtr crtc,CARD64 * ust,CARD64 * msc)1455 static int arcanPresentGetUstMsc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
1456 {
1457 trace("present:get_ust_msc");
1458 return 0;
1459 }
1460
arcanPresentAbortVblank(void * data)1461 static void arcanPresentAbortVblank(void *data)
1462 {
1463 struct ms_present_vblank_event *event = data;
1464 trace("present:vblank abort");
1465 free(event);
1466 }
1467
arcanPresentQueueVblank(RRCrtcPtr crtc,uint64_t evid,uint64_t msc)1468 static int arcanPresentQueueVblank(RRCrtcPtr crtc, uint64_t evid, uint64_t msc)
1469 {
1470 trace("present:queue vblank (wait for vready)");
1471 return Success;
1472 }
1473
1474 static void
arcanPresentFlush(WindowPtr window)1475 arcanPresentFlush(WindowPtr window)
1476 {
1477 trace("present:flush");
1478 #ifdef GLAMOR
1479 /*
1480 ScreenPtr screen = window->drawable.pScreen;
1481 ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1482 modesettingPtr ms = modesettingPTR(scrn);
1483
1484 if (ms->drmmode.glamor)
1485 glamor_block_handler(screen);
1486 */
1487 #endif
1488 }
1489
1490 static Bool
arcanPresentFlip(RRCrtcPtr crtc,uint64_t event_id,uint64_t target_msc,PixmapPtr pixmap,Bool sync_flip)1491 arcanPresentFlip(RRCrtcPtr crtc,
1492 uint64_t event_id,
1493 uint64_t target_msc,
1494 PixmapPtr pixmap,
1495 Bool sync_flip)
1496 {
1497 /* if sync flip is true, wait for "blank" then signal */
1498 trace("present:flip");
1499 return true;
1500 }
1501
1502 static void
arcanPresentUnflip(ScreenPtr screen,uint64_t eventid)1503 arcanPresentUnflip(ScreenPtr screen, uint64_t eventid)
1504 {
1505 trace("present:unflip");
1506 }
1507
1508 static Bool
arcanPresentCheckFlip(RRCrtcPtr crtc,WindowPtr window,PixmapPtr pixmap,Bool sync_flip)1509 arcanPresentCheckFlip(RRCrtcPtr crtc,
1510 WindowPtr window,
1511 PixmapPtr pixmap,
1512 Bool sync_flip)
1513 {
1514 trace("present:check flip");
1515 return true;
1516 }
1517
1518 static present_screen_info_rec arcan_present_info = {
1519 .version = PRESENT_SCREEN_INFO_VERSION,
1520 .get_crtc = arcanPresentGetCrtc,
1521 .get_ust_msc = arcanPresentGetUstMsc,
1522 .queue_vblank = arcanPresentQueueVblank,
1523 .abort_vblank = arcanPresentAbortVblank,
1524 .flush = arcanPresentFlush,
1525 .capabilities = PresentCapabilityAsync,
1526 .check_flip = arcanPresentCheckFlip,
1527 .flip = arcanPresentFlip,
1528 .unflip = arcanPresentUnflip
1529 };
1530
1531 Bool
arcanFinishInitScreen(ScreenPtr pScreen)1532 arcanFinishInitScreen(ScreenPtr pScreen)
1533 {
1534 KdScreenPriv(pScreen);
1535 KdScreenInfo *screen = pScreenPriv->screen;
1536 arcanScrPriv *scrpriv = screen->driver;
1537
1538 trace("arcanFinishInitScreen");
1539 #ifdef RANDR
1540 if (!arcanRandRInit(pScreen))
1541 return FALSE;
1542 #endif
1543
1544 scrpriv->CloseHandler = pScreen->CloseScreen;
1545 pScreen->CloseScreen = arcanCloseScreenWrap;
1546 scrpriv->BlockHandler = pScreen->BlockHandler;
1547 pScreen->BlockHandler = arcanScreenBlockHandler;
1548
1549 present_screen_init(pScreen, &arcan_present_info);
1550 return TRUE;
1551 }
1552
1553 void
arcanScreenFini(KdScreenInfo * screen)1554 arcanScreenFini(KdScreenInfo * screen)
1555 {
1556 struct arcan_shmif_cont* con = arcan_shmif_primary(SHMIF_INPUT);
1557 con->user = NULL;
1558 trace("arcanScreenFini");
1559 }
1560
1561 static Status
ArcanKeyboardInit(KdKeyboardInfo * ki)1562 ArcanKeyboardInit(KdKeyboardInfo * ki)
1563 {
1564 ki->minScanCode = 0;
1565 ki->maxScanCode = 247;
1566 arcanInputPriv.ki = ki;
1567
1568 return Success;
1569 }
1570
1571 static Status
ArcanKeyboardEnable(KdKeyboardInfo * ki)1572 ArcanKeyboardEnable(KdKeyboardInfo * ki)
1573 {
1574 return Success;
1575 }
1576
1577 static void
ArcanKeyboardDisable(KdKeyboardInfo * ki)1578 ArcanKeyboardDisable(KdKeyboardInfo * ki)
1579 {
1580 return;
1581 }
1582
1583 static void
ArcanKeyboardFini(KdKeyboardInfo * ki)1584 ArcanKeyboardFini(KdKeyboardInfo * ki)
1585 {
1586 }
1587
1588 static void
ArcanKeyboardLeds(KdKeyboardInfo * ki,int leds)1589 ArcanKeyboardLeds(KdKeyboardInfo * ki, int leds)
1590 {
1591 /* we need a provision to signal this, can probably use the input-
1592 * event used by remoting */
1593 trace("arcanKeyboardLeds(%d)", leds);
1594 }
1595
1596 static void
ArcanKeyboardBell(KdKeyboardInfo * ki,int volume,int frequency,int duration)1597 ArcanKeyboardBell(KdKeyboardInfo * ki, int volume, int frequency, int duration)
1598 {
1599 /* find primary segment, enqueue as alert */
1600 }
1601
1602 KdKeyboardDriver arcanKeyboardDriver = {
1603 "arcan",
1604 ArcanKeyboardInit,
1605 ArcanKeyboardEnable,
1606 ArcanKeyboardLeds,
1607 ArcanKeyboardBell,
1608 ArcanKeyboardDisable,
1609 ArcanKeyboardFini,
1610 NULL,
1611 };
1612 void
arcanCardFini(KdCardInfo * card)1613 arcanCardFini(KdCardInfo * card)
1614 {
1615 arcanPriv *priv = card->driver;
1616
1617 trace("arcanCardFini");
1618 free(priv->base);
1619 free(priv);
1620 }
1621
1622 void
arcanCloseScreen(ScreenPtr pScreen)1623 arcanCloseScreen(ScreenPtr pScreen)
1624 {
1625 KdScreenPriv(pScreen);
1626 KdScreenInfo *screen = pScreenPriv->screen;
1627 arcanScrPriv *scrpriv = screen->driver;
1628
1629 trace("arcanCloseScreen");
1630 if (!scrpriv)
1631 return;
1632
1633 /* ASAN reports UAF if we manually Unset @ Close
1634 * arcanUnsetInternalDamage(pScreen);
1635 */
1636 arcan_shmifext_drop(scrpriv->acon);
1637
1638 scrpriv->acon->user = NULL;
1639 pScreen->CloseScreen = scrpriv->CloseHandler;
1640 free(scrpriv);
1641 screen->driver = NULL;
1642 (*pScreen->CloseScreen)(pScreen);
1643 }
1644
1645 void
arcanPutColors(ScreenPtr pScreen,int n,xColorItem * pdefs)1646 arcanPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs)
1647 {
1648 /*
1649 * FIXME:
1650 * should probably forward some cmap_entry thing and invalidate
1651 * the entire region. Somewhat unsure how this actually works
1652 */
1653 trace("arcanPutColors");
1654 }
1655
1656 int
glamor_egl_fd_name_from_pixmap(ScreenPtr screen,PixmapPtr pixmap,CARD16 * stride,CARD32 * size)1657 glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
1658 PixmapPtr pixmap,
1659 CARD16 *stride, CARD32 *size)
1660 {
1661 return 0;
1662 }
1663
1664 void
arcanGetColors(ScreenPtr pScreen,int n,xColorItem * pdefs)1665 arcanGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs)
1666 {
1667 while (n--) {
1668 pdefs->red = 8;
1669 pdefs->green = 8;
1670 pdefs->blue = 8;
1671 pdefs++;
1672 }
1673 trace("arcanGetColors");
1674 }
1675
1676 miPointerScreenFuncRec ArcanPointerScreenFuncs = {
1677 /* CursorOffScreen
1678 * CrossScreen
1679 * WarpCursor */
1680 };
1681
1682 miPointerSpriteFuncRec ArcanPointerSpriteFuncs = {
1683 /*
1684 * Realize
1685 * Unrealize
1686 * SetCursor
1687 * MoveCursor
1688 * Initialize
1689 * Cleanup
1690 */
1691 };
1692
1693 Bool
arcanCursorInit(ScreenPtr screen)1694 arcanCursorInit(ScreenPtr screen)
1695 {
1696 if (!arcanConfigPriv.accel_cursor)
1697 return FALSE;
1698
1699 if (!dixRegisterPrivateKey(&cursor_private_key, PRIVATE_CURSOR_BITS, 0))
1700 return FALSE;
1701
1702 miPointerInitialize(screen,
1703 &ArcanPointerSpriteFuncs,
1704 &ArcanPointerSpriteFuncs, FALSE);
1705
1706 return TRUE;
1707 }
1708
1709 static Status
MouseInit(KdPointerInfo * pi)1710 MouseInit(KdPointerInfo * pi)
1711 {
1712 arcanInputPriv.pi = pi;
1713 return Success;
1714 }
1715
1716 static Status
MouseEnable(KdPointerInfo * pi)1717 MouseEnable(KdPointerInfo * pi)
1718 {
1719 return Success;
1720 }
1721
1722 static void
MouseDisable(KdPointerInfo * pi)1723 MouseDisable(KdPointerInfo * pi)
1724 {
1725 return;
1726 }
1727
1728 static void
MouseFini(KdPointerInfo * pi)1729 MouseFini(KdPointerInfo * pi)
1730 {
1731 return;
1732 }
1733
1734 KdPointerDriver arcanPointerDriver = {
1735 "arcan",
1736 MouseInit,
1737 MouseEnable,
1738 MouseDisable,
1739 MouseFini,
1740 NULL
1741 };
1742