Example #1
0
struct vl_screen *omx_get_screen(void)
{
   static bool first_time = true;
   mtx_lock(&omx_lock);

   if (!omx_screen) {
      if (first_time) {
         omx_render_node = debug_get_option("OMX_RENDER_NODE", NULL);
         first_time = false;
      }
      if (omx_render_node) {
         drm_fd = loader_open_device(omx_render_node);
         if (drm_fd < 0)
            goto error;

         omx_screen = vl_drm_screen_create(drm_fd);
         if (!omx_screen) {
            close(drm_fd);
            goto error;
         }
      } else {
         omx_display = XOpenDisplay(NULL);
         if (!omx_display)
            goto error;

         omx_screen = vl_dri3_screen_create(omx_display, 0);
         if (!omx_screen)
            omx_screen = vl_dri2_screen_create(omx_display, 0);
         if (!omx_screen) {
            XCloseDisplay(omx_display);
            goto error;
         }
      }
   }

   ++omx_usecount;

   mtx_unlock(&omx_lock);
   return omx_screen;

error:
   mtx_unlock(&omx_lock);
   return NULL;
}
Example #2
0
static EGLBoolean
dri2_x11_connect(struct dri2_egl_display *dri2_dpy)
{
   xcb_xfixes_query_version_reply_t *xfixes_query;
   xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
   xcb_dri2_query_version_reply_t *dri2_query;
   xcb_dri2_query_version_cookie_t dri2_query_cookie;
   xcb_dri2_connect_reply_t *connect;
   xcb_dri2_connect_cookie_t connect_cookie;
   xcb_generic_error_t *error;
   xcb_screen_iterator_t s;
   xcb_screen_t *screen;
   char *driver_name, *loader_driver_name, *device_name;
   const xcb_query_extension_reply_t *extension;

   xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id);
   xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id);

   extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id);
   if (!(extension && extension->present))
      return EGL_FALSE;

   extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri2_id);
   if (!(extension && extension->present))
      return EGL_FALSE;

   xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
						  XCB_XFIXES_MAJOR_VERSION,
						  XCB_XFIXES_MINOR_VERSION);

   dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn,
					       XCB_DRI2_MAJOR_VERSION,
					       XCB_DRI2_MINOR_VERSION);

   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
   screen = get_xcb_screen(s, dri2_dpy->screen);
   if (!screen) {
      _eglLog(_EGL_WARNING, "DRI2: failed to get xcb screen");
      return EGL_FALSE;
   }
   connect_cookie = xcb_dri2_connect_unchecked(dri2_dpy->conn, screen->root,
                                   XCB_DRI2_DRIVER_TYPE_DRI);

   xfixes_query =
      xcb_xfixes_query_version_reply (dri2_dpy->conn,
				      xfixes_query_cookie, &error);
   if (xfixes_query == NULL ||
       error != NULL || xfixes_query->major_version < 2) {
      _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version");
      free(error);
      return EGL_FALSE;
   }
   free(xfixes_query);

   dri2_query =
      xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error);
   if (dri2_query == NULL || error != NULL) {
      _eglLog(_EGL_WARNING, "DRI2: failed to query version");
      free(error);
      return EGL_FALSE;
   }
   dri2_dpy->dri2_major = dri2_query->major_version;
   dri2_dpy->dri2_minor = dri2_query->minor_version;
   free(dri2_query);

   connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL);
   if (connect == NULL ||
       connect->driver_name_length + connect->device_name_length == 0) {
      _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
      return EGL_FALSE;
   }

   device_name = xcb_dri2_connect_device_name (connect);

   dri2_dpy->device_name =
      strndup(device_name,
              xcb_dri2_connect_device_name_length(connect));

   dri2_dpy->fd = loader_open_device(dri2_dpy->device_name);
   if (dri2_dpy->fd == -1) {
      _eglLog(_EGL_WARNING,
              "DRI2: could not open %s (%s)", dri2_dpy->device_name,
              strerror(errno));
      free(dri2_dpy->device_name);
      free(connect);
      return EGL_FALSE;
   }

   if (!dri2_x11_local_authenticate(dri2_dpy)) {
      close(dri2_dpy->fd);
      free(dri2_dpy->device_name);
      free(connect);
      return EGL_FALSE;
   }

   driver_name = xcb_dri2_connect_driver_name (connect);

   /* If Mesa knows about the appropriate driver for this fd, then trust it.
    * Otherwise, default to the server's value.
    */
   loader_driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0);
   if (loader_driver_name) {
      dri2_dpy->driver_name = loader_driver_name;
   } else {
      dri2_dpy->driver_name =
         strndup(driver_name,
                 xcb_dri2_connect_driver_name_length(connect));
   }

   if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) {
      close(dri2_dpy->fd);
      free(dri2_dpy->device_name);
      free(dri2_dpy->driver_name);
      free(connect);
      return EGL_FALSE;
   }
   free(connect);

   return EGL_TRUE;
}
Example #3
0
EGLBoolean
dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
{
   struct dri2_egl_display *dri2_dpy;
   struct gbm_device *gbm;
   int fd = -1;
   int i;

   loader_set_logger(_eglLog);

   dri2_dpy = calloc(1, sizeof *dri2_dpy);
   if (!dri2_dpy)
      return _eglError(EGL_BAD_ALLOC, "eglInitialize");

   disp->DriverData = (void *) dri2_dpy;

   gbm = disp->PlatformDisplay;
   if (gbm == NULL) {
      char buf[64];
      int n = snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, 0);
      if (n != -1 && n < sizeof(buf))
         fd = loader_open_device(buf);
      if (fd < 0)
         fd = loader_open_device("/dev/dri/card0");
      dri2_dpy->own_device = 1;
      gbm = gbm_create_device(fd);
      if (gbm == NULL)
         goto cleanup;
   } else {
      fd = fcntl(gbm_device_get_fd(gbm), F_DUPFD_CLOEXEC, 3);
      if (fd < 0)
         goto cleanup;
   }

   if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0)
      goto cleanup;

   dri2_dpy->gbm_dri = gbm_dri_device(gbm);
   if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI)
      goto cleanup;

   dri2_dpy->fd = fd;
   dri2_dpy->driver_name = strdup(dri2_dpy->gbm_dri->base.driver_name);

   dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen;
   dri2_dpy->core = dri2_dpy->gbm_dri->core;
   dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2;
   dri2_dpy->fence = dri2_dpy->gbm_dri->fence;
   dri2_dpy->image = dri2_dpy->gbm_dri->image;
   dri2_dpy->flush = dri2_dpy->gbm_dri->flush;
   dri2_dpy->swrast = dri2_dpy->gbm_dri->swrast;
   dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs;

   dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image;
   dri2_dpy->gbm_dri->lookup_user_data = disp;

   dri2_dpy->gbm_dri->get_buffers = dri2_drm_get_buffers;
   dri2_dpy->gbm_dri->flush_front_buffer = dri2_drm_flush_front_buffer;
   dri2_dpy->gbm_dri->get_buffers_with_format = dri2_drm_get_buffers_with_format;
   dri2_dpy->gbm_dri->image_get_buffers = dri2_drm_image_get_buffers;
   dri2_dpy->gbm_dri->swrast_put_image2 = swrast_put_image2;
   dri2_dpy->gbm_dri->swrast_get_image = swrast_get_image;

   dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer;
   dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer;
   dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers;

   dri2_setup_screen(disp);

   for (i = 0; dri2_dpy->driver_configs[i]; i++) {
      EGLint format, attr_list[3];
      unsigned int red, alpha;

      dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
                                       __DRI_ATTRIB_RED_MASK, &red);
      dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
                                       __DRI_ATTRIB_ALPHA_MASK, &alpha);
      if (red == 0x3ff00000 && alpha == 0x00000000)
         format = GBM_FORMAT_XRGB2101010;
      else if (red == 0x3ff00000 && alpha == 0xc0000000)
         format = GBM_FORMAT_ARGB2101010;
      else if (red == 0x00ff0000 && alpha == 0x00000000)
         format = GBM_FORMAT_XRGB8888;
      else if (red == 0x00ff0000 && alpha == 0xff000000)
         format = GBM_FORMAT_ARGB8888;
      else if (red == 0xf800)
         format = GBM_FORMAT_RGB565;
      else
         continue;

      attr_list[0] = EGL_NATIVE_VISUAL_ID;
      attr_list[1] = format;
      attr_list[2] = EGL_NONE;

      dri2_add_config(disp, dri2_dpy->driver_configs[i],
                      i + 1, EGL_WINDOW_BIT, attr_list, NULL);
   }

   disp->Extensions.KHR_image_pixmap = EGL_TRUE;
   if (dri2_dpy->dri2)
      disp->Extensions.EXT_buffer_age = EGL_TRUE;

#ifdef HAVE_WAYLAND_PLATFORM
   if (dri2_dpy->image) {
       dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd);

       if (dri2_dpy->image->base.version >= 10 &&
           dri2_dpy->image->getCapabilities != NULL) {
           int capabilities;

           capabilities =
               dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen);
           disp->Extensions.WL_bind_wayland_display =
               (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0;
       } else
           disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
   }
#endif

   /* Fill vtbl last to prevent accidentally calling virtual function during
    * initialization.
    */
   dri2_dpy->vtbl = &dri2_drm_display_vtbl;

   return EGL_TRUE;

cleanup:
   if (fd >= 0)
      close(fd);

   free(dri2_dpy);
   disp->DriverData = NULL;
   return EGL_FALSE;
}
Example #4
0
EGLBoolean
dri2_initialize_surfaceless(_EGLDriver *drv, _EGLDisplay *disp)
{
   struct dri2_egl_display *dri2_dpy;
   const char* err;
   int i;
   int driver_loaded = 0;

   loader_set_logger(_eglLog);

   dri2_dpy = calloc(1, sizeof *dri2_dpy);
   if (!dri2_dpy)
      return _eglError(EGL_BAD_ALLOC, "eglInitialize");

   disp->DriverData = (void *) dri2_dpy;

   const int limit = 64;
   const int base = 128;
   for (i = 0; i < limit; ++i) {
      char *card_path;
      if (asprintf(&card_path, DRM_RENDER_DEV_NAME, DRM_DIR_NAME, base + i) < 0)
         continue;

      dri2_dpy->fd = loader_open_device(card_path);

      free(card_path);
      if (dri2_dpy->fd < 0)
         continue;

      dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0);
      if (dri2_dpy->driver_name) {
         if (dri2_load_driver(disp)) {
            driver_loaded = 1;
            break;
         }
         free(dri2_dpy->driver_name);
      }
      close(dri2_dpy->fd);
   }

   if (!driver_loaded) {
      err = "DRI2: failed to load driver";
      goto cleanup_display;
   }

   dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
   dri2_dpy->dri2_loader_extension.base.version = 3;
   dri2_dpy->dri2_loader_extension.getBuffers = NULL;
   dri2_dpy->dri2_loader_extension.flushFrontBuffer =
      surfaceless_flush_front_buffer;
   dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
      surfaceless_get_buffers_with_format;

   dri2_dpy->extensions[0] = &image_loader_extension.base;
   dri2_dpy->extensions[1] = &image_lookup_extension.base;
   dri2_dpy->extensions[2] = &use_invalidate.base;
   dri2_dpy->extensions[3] = NULL;

   if (!dri2_create_screen(disp)) {
      err = "DRI2: failed to create screen";
      goto cleanup_driver;
   }

   if (!surfaceless_add_configs_for_visuals(drv, disp)) {
      err = "DRI2: failed to add configs";
      goto cleanup_screen;
   }

   disp->Extensions.KHR_image_base = EGL_TRUE;

   /* Fill vtbl last to prevent accidentally calling virtual function during
    * initialization.
    */
   dri2_dpy->vtbl = &dri2_surfaceless_display_vtbl;

   return EGL_TRUE;

cleanup_screen:
   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);

cleanup_driver:
   dlclose(dri2_dpy->driver);
   free(dri2_dpy->driver_name);
   close(dri2_dpy->fd);
cleanup_display:
   free(dri2_dpy);

   return _eglError(EGL_NOT_INITIALIZED, err);
}
struct vl_screen *
vl_dri2_screen_create(Display *display, int screen)
{
   struct vl_dri_screen *scrn;
   const xcb_query_extension_reply_t *extension;
   xcb_dri2_query_version_cookie_t dri2_query_cookie;
   xcb_dri2_query_version_reply_t *dri2_query = NULL;
   xcb_dri2_connect_cookie_t connect_cookie;
   xcb_dri2_connect_reply_t *connect = NULL;
   xcb_dri2_authenticate_cookie_t authenticate_cookie;
   xcb_dri2_authenticate_reply_t *authenticate = NULL;
   xcb_screen_iterator_t s;
   xcb_generic_error_t *error = NULL;
   char *device_name;
   int fd, device_name_length;
   unsigned driverType;

   drm_magic_t magic;

   assert(display);

   scrn = CALLOC_STRUCT(vl_dri_screen);
   if (!scrn)
      return NULL;

   scrn->conn = XGetXCBConnection(display);
   if (!scrn->conn)
      goto free_screen;

   xcb_prefetch_extension_data(scrn->conn, &xcb_dri2_id);

   extension = xcb_get_extension_data(scrn->conn, &xcb_dri2_id);
   if (!(extension && extension->present))
      goto free_screen;

   dri2_query_cookie = xcb_dri2_query_version (scrn->conn,
                                               XCB_DRI2_MAJOR_VERSION,
                                               XCB_DRI2_MINOR_VERSION);
   dri2_query = xcb_dri2_query_version_reply (scrn->conn, dri2_query_cookie, &error);
   if (dri2_query == NULL || error != NULL || dri2_query->minor_version < 2)
      goto free_query;

   s = xcb_setup_roots_iterator(xcb_get_setup(scrn->conn));
   scrn->base.xcb_screen = get_xcb_screen(s, screen);
   if (!scrn->base.xcb_screen)
      goto free_query;

   driverType = XCB_DRI2_DRIVER_TYPE_DRI;
   {
      char *prime = getenv("DRI_PRIME");
      if (prime) {
         unsigned primeid;
         errno = 0;
         primeid = strtoul(prime, NULL, 0);
         if (errno == 0)
            driverType |=
               ((primeid & DRI2DriverPrimeMask) << DRI2DriverPrimeShift);
      }
   }

   connect_cookie = xcb_dri2_connect_unchecked(
      scrn->conn, ((xcb_screen_t *)(scrn->base.xcb_screen))->root, driverType);
   connect = xcb_dri2_connect_reply(scrn->conn, connect_cookie, NULL);
   if (connect == NULL ||
       connect->driver_name_length + connect->device_name_length == 0)
      goto free_connect;

   device_name_length = xcb_dri2_connect_device_name_length(connect);
   device_name = CALLOC(1, device_name_length + 1);
   if (!device_name)
      goto free_connect;
   memcpy(device_name, xcb_dri2_connect_device_name(connect), device_name_length);
   fd = loader_open_device(device_name);
   free(device_name);

   if (fd < 0)
      goto free_connect;

   if (drmGetMagic(fd, &magic))
      goto close_fd;

   authenticate_cookie = xcb_dri2_authenticate_unchecked(
      scrn->conn, ((xcb_screen_t *)(scrn->base.xcb_screen))->root, magic);
   authenticate = xcb_dri2_authenticate_reply(scrn->conn, authenticate_cookie, NULL);

   if (authenticate == NULL || !authenticate->authenticated)
      goto free_authenticate;

   if (pipe_loader_drm_probe_fd(&scrn->base.dev, fd))
      scrn->base.pscreen = pipe_loader_create_screen(scrn->base.dev);

   if (!scrn->base.pscreen)
      goto release_pipe;

   scrn->base.destroy = vl_dri2_screen_destroy;
   scrn->base.texture_from_drawable = vl_dri2_screen_texture_from_drawable;
   scrn->base.get_dirty_area = vl_dri2_screen_get_dirty_area;
   scrn->base.get_timestamp = vl_dri2_screen_get_timestamp;
   scrn->base.set_next_timestamp = vl_dri2_screen_set_next_timestamp;
   scrn->base.get_private = vl_dri2_screen_get_private;
   scrn->base.pscreen->flush_frontbuffer = vl_dri2_flush_frontbuffer;
   vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]);
   vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]);

   /* The pipe loader duplicates the fd */
   close(fd);
   free(authenticate);
   free(connect);
   free(dri2_query);
   free(error);

   return &scrn->base;

release_pipe:
   if (scrn->base.dev)
      pipe_loader_release(&scrn->base.dev, 1);
free_authenticate:
   free(authenticate);
close_fd:
   close(fd);
free_connect:
   free(connect);
free_query:
   free(dri2_query);
   free(error);

free_screen:
   FREE(scrn);
   return NULL;
}
Example #6
0
int loader_get_user_preferred_fd(int default_fd, int *different_device)
{
/* Arbitrary "maximum" value of drm devices. */
#define MAX_DRM_DEVICES 32
   const char *dri_prime = getenv("DRI_PRIME");
   char *default_tag, *prime = NULL;
   drmDevicePtr devices[MAX_DRM_DEVICES];
   int i, num_devices, fd;
   bool found = false;

   if (dri_prime)
      prime = strdup(dri_prime);
#ifdef USE_DRICONF
   else
      prime = loader_get_dri_config_device_id();
#endif

   if (prime == NULL) {
      *different_device = 0;
      return default_fd;
   }

   default_tag = drm_get_id_path_tag_for_fd(default_fd);
   if (default_tag == NULL)
      goto err;

   num_devices = drmGetDevices(devices, MAX_DRM_DEVICES);
   if (num_devices < 0)
      goto err;

   /* two format are supported:
    * "1": choose any other card than the card used by default.
    * id_path_tag: (for example "pci-0000_02_00_0") choose the card
    * with this id_path_tag.
    */
   if (!strcmp(prime,"1")) {
      /* Hmm... detection for 2-7 seems to be broken. Oh well ...
       * Pick the first render device that is not our own.
       */
      for (i = 0; i < num_devices; i++) {
         if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER &&
             !drm_device_matches_tag(devices[i], default_tag)) {

            found = true;
            break;
         }
      }
   } else {
      for (i = 0; i < num_devices; i++) {
         if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER &&
            drm_device_matches_tag(devices[i], prime)) {

            found = true;
            break;
         }
      }
   }

   if (!found) {
      drmFreeDevices(devices, num_devices);
      goto err;
   }

   fd = loader_open_device(devices[i]->nodes[DRM_NODE_RENDER]);
   drmFreeDevices(devices, num_devices);
   if (fd < 0)
      goto err;

   close(default_fd);

   *different_device = !!strcmp(default_tag, prime);

   free(default_tag);
   free(prime);
   return fd;

 err:
   *different_device = 0;

   free(default_tag);
   free(prime);
   return default_fd;
}