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