Exemple #1
0
static void *
evgl_eng_native_window_create(void *data)
{
   Render_Engine *re;
   struct gbm_surface *surface;
   Evas_Engine_Info_GL_Drm *info;

   re = (Render_Engine *)data;
   if (!re)
     {
        ERR("Invalid Render Engine Data!");
        return NULL;
     }

   info = eng_get_ob(re)->info;
   if (!info)
     {
        ERR("Invalid Evas Engine GL_DRM Info!");
        return NULL;
     }

   surface = gbm_surface_create(info->info.gbm,
                                eng_get_ob(re)->w, eng_get_ob(re)->h,
                                info->info.format, info->info.flags);
   if (!surface)
     {
        ERR("Could not create gl drm window: %m");
        return NULL;
     }

   return (void *)surface;
}
static CoglBool
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
                            CoglError **error)
{
  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
  CoglContext *context = framebuffer->context;
  CoglDisplay *display = context->display;
  CoglDisplayEGL *egl_display = display->winsys;
  CoglDisplayKMS *kms_display = egl_display->platform;
  CoglRenderer *renderer = display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;
  CoglRendererKMS *kms_renderer = egl_renderer->platform;
  CoglOnscreenEGL *egl_onscreen;
  CoglOnscreenKMS *kms_onscreen;

  _COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE);

  onscreen->winsys = g_slice_new0 (CoglOnscreenEGL);
  egl_onscreen = onscreen->winsys;

  kms_onscreen = g_slice_new0 (CoglOnscreenKMS);
  egl_onscreen->platform = kms_onscreen;

  kms_onscreen->surface =
    gbm_surface_create (kms_renderer->gbm,
                        kms_display->width,
                        kms_display->height,
                        GBM_BO_FORMAT_XRGB8888,
                        GBM_BO_USE_SCANOUT |
                        GBM_BO_USE_RENDERING);

  if (!kms_onscreen->surface)
    {
      _cogl_set_error (error, COGL_WINSYS_ERROR,
                   COGL_WINSYS_ERROR_CREATE_ONSCREEN,
                   "Failed to allocate surface");
      return FALSE;
    }

  egl_onscreen->egl_surface =
    eglCreateWindowSurface (egl_renderer->edpy,
                            egl_display->egl_config,
                            (NativeWindowType) kms_onscreen->surface,
                            NULL);
  if (egl_onscreen->egl_surface == EGL_NO_SURFACE)
    {
      _cogl_set_error (error, COGL_WINSYS_ERROR,
                   COGL_WINSYS_ERROR_CREATE_ONSCREEN,
                   "Failed to allocate surface");
      return FALSE;
    }

  _cogl_framebuffer_winsys_update_size (framebuffer,
                                        kms_display->width,
                                        kms_display->height);

  return TRUE;
}
RenderingBackendGBM::Surface::Surface(const RenderingBackendGBM& renderingBackend, uint32_t width, uint32_t height, uint32_t targetHandle, RenderingBackendGBM::Surface::Client& client)
    : m_client(client)
{
    m_size = { width, height };
    auto boSize = m_size;
    if (!targetHandle)
        boSize = { 2048, 2048 };

    m_surface = gbm_surface_create(renderingBackend.m_gbm.device, boSize.first, boSize.second, GBM_FORMAT_ARGB8888, 0);
}
Exemple #4
0
gbm_surface *QEglFSKmsGbmScreen::createSurface()
{
    if (!m_gbm_surface) {
        qCDebug(qLcEglfsKmsDebug) << "Creating window for screen" << name();
        m_gbm_surface = gbm_surface_create(static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice(),
                                           rawGeometry().width(),
                                           rawGeometry().height(),
                                           GBM_FORMAT_XRGB8888,
                                           GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
    }
    return m_gbm_surface;
}
EGLNativeWindowType QEglFSKmsIntegration::createNativeOffscreenWindow(const QSurfaceFormat &format)
{
    Q_UNUSED(format);
    Q_ASSERT(m_device);

    qCDebug(qLcEglfsKmsDebug) << "Creating native off screen window";
    gbm_surface *surface = gbm_surface_create(m_device->device(),
                                              1, 1,
                                              GBM_FORMAT_XRGB8888,
                                              GBM_BO_USE_RENDERING);

    return reinterpret_cast<EGLNativeWindowType>(surface);
}
Exemple #6
0
void QKmsScreen::initializeScreenMode()
{
    //Determine optimal mode for screen
    drmModeRes *resources = drmModeGetResources(m_device->fd());
    if (!resources)
        qFatal("drmModeGetResources failed");

    drmModeConnector *connector = drmModeGetConnector(m_device->fd(), m_connectorId);
    drmModeModeInfo *mode = 0;
    for (int i = 0; i < connector->count_modes; ++i) {
        if (connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) {
            mode = &connector->modes[i];
            break;
        }
    }
    if (!mode)
        mode = &builtin_1024x768;

    drmModeEncoder *encoder = drmModeGetEncoder(m_device->fd(), connector->encoders[0]);
    if (encoder == 0)
        qFatal("No encoder for connector.");

    int i;
    for (i = 0; i < resources->count_crtcs; i++) {
        if (encoder->possible_crtcs & (1 << i))
            break;
    }
    if (i == resources->count_crtcs)
        qFatal("No usable crtc for encoder.");

    m_oldCrtc = drmModeGetCrtc(m_device->fd(), encoder->crtc_id);

    m_crtcId = resources->crtcs[i];
    m_mode = *mode;
    m_geometry = QRect(0, 0, m_mode.hdisplay, m_mode.vdisplay);
    qDebug() << "kms initialized with geometry" << m_geometry;
    m_depth = 32;
    m_format = QImage::Format_RGB32;
    m_physicalSize = QSizeF(connector->mmWidth, connector->mmHeight);

    m_gbmSurface = gbm_surface_create(m_device->gbmDevice(),
                                      m_mode.hdisplay, m_mode.vdisplay,
                                      GBM_BO_FORMAT_XRGB8888,
                                      GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);

    qDebug() << "created gbm surface" << m_gbmSurface << m_mode.hdisplay << m_mode.vdisplay;
    //Cleanup
    drmModeFreeEncoder(encoder);
    drmModeFreeConnector(connector);
    drmModeFreeResources(resources);
}
Exemple #7
0
mgg::GBMSurfaceUPtr mggh::GBMHelper::create_scanout_surface(uint32_t width, uint32_t height)
{
    auto surface_raw = gbm_surface_create(device, width, height,
                                          GBM_BO_FORMAT_XRGB8888,
                                          GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);

    auto gbm_surface_deleter = [](gbm_surface *p) { if (p) gbm_surface_destroy(p); };
    GBMSurfaceUPtr surface{surface_raw, gbm_surface_deleter};

    if (!surface)
        BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create GBM scanout surface"));

    return surface;
}
Exemple #8
0
int init_gbm(void)
{
	gbm.dev = gbm_create_device(drm.fd);

	gbm.surface = gbm_surface_create(gbm.dev,
			drm.mode->hdisplay, drm.mode->vdisplay,
			GBM_FORMAT_XRGB8888,
			GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
	if (!gbm.surface) {
		printf("failed to create gbm surface\n");
		return -1;
	}

	return 0;
}
static CoglBool
_cogl_winsys_egl_context_created (CoglDisplay *display,
                                  CoglError **error)
{
  CoglDisplayEGL *egl_display = display->winsys;
  CoglDisplayKMS *kms_display = egl_display->platform;
  CoglRenderer *renderer = display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;
  CoglRendererKMS *kms_renderer = egl_renderer->platform;

  kms_display->dummy_gbm_surface = gbm_surface_create (kms_renderer->gbm,
                                                       16, 16,
                                                       GBM_FORMAT_XRGB8888,
                                                       GBM_BO_USE_RENDERING);
  if (!kms_display->dummy_gbm_surface)
    {
      _cogl_set_error (error, COGL_WINSYS_ERROR,
                   COGL_WINSYS_ERROR_CREATE_CONTEXT,
                   "Failed to create dummy GBM surface");
      return FALSE;
    }

  egl_display->dummy_surface =
    eglCreateWindowSurface (egl_renderer->edpy,
                            egl_display->egl_config,
                            (NativeWindowType) kms_display->dummy_gbm_surface,
                            NULL);
  if (egl_display->dummy_surface == EGL_NO_SURFACE)
    {
      _cogl_set_error (error, COGL_WINSYS_ERROR,
                   COGL_WINSYS_ERROR_CREATE_CONTEXT,
                   "Failed to create dummy EGL surface");
      return FALSE;
    }

  if (!_cogl_winsys_egl_make_current (display,
                                      egl_display->dummy_surface,
                                      egl_display->dummy_surface,
                                      egl_display->egl_context))
    {
      _cogl_set_error (error, COGL_WINSYS_ERROR,
                   COGL_WINSYS_ERROR_CREATE_CONTEXT,
                   "Failed to make context current");
      return FALSE;
    }

  return TRUE;
}
std::unique_ptr<GLContextEGL> PlatformDisplayGBM::createOffscreenContext(GLContext* sharingContext)
{
    class OffscreenContextData : public GLContext::Data {
    public:
        virtual ~OffscreenContextData()
        {
            gbm_surface_destroy(surface);
        }

        struct gbm_surface* surface;
    };

    auto contextData = std::make_unique<OffscreenContextData>();
    contextData->surface = gbm_surface_create(m_gbm.device, 1, 1, GBM_FORMAT_ARGB8888, 0);

    auto* surface = contextData->surface;
    return GLContextEGL::createWindowContext(surface, sharingContext, WTF::move(contextData));
}
Exemple #11
0
bool
NativeStateDRM::init_gbm()
{
    dev_ = gbm_create_device(fd_);
    if (!dev_) {
        Log::error("Failed to create GBM device\n");
        return false;
    }

    surface_ = gbm_surface_create(dev_, mode_->hdisplay, mode_->vdisplay,
                                  GBM_FORMAT_XRGB8888,
                                  GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
    if (!surface_) {
        Log::error("Failed to create GBM surface\n");
        return false;
    }

    return true;
}
Exemple #12
0
bool CGBMUtils::InitGbm(struct gbm *gbm, int hdisplay, int vdisplay)
{
  gbm->width = hdisplay;
  gbm->height = vdisplay;

  gbm->surface = gbm_surface_create(gbm->dev,
                                    gbm->width,
                                    gbm->height,
                                    GBM_FORMAT_ARGB8888,
                                    GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);

  if(!gbm->surface)
  {
    CLog::Log(LOGERROR, "CGBMUtils::%s - failed to create surface", __FUNCTION__);
    return false;
  }

  CLog::Log(LOGDEBUG, "CGBMUtils::%s - created surface with size %dx%d", __FUNCTION__,
                                                                         gbm->width,
                                                                         gbm->height);

  return true;
}
Exemple #13
0
static bool init_gbm(struct MPGLContext *ctx)
{
    struct priv *p = ctx->priv;
    MP_VERBOSE(ctx->vo, "Creating GBM device\n");
    p->gbm.device = gbm_create_device(p->kms->fd);
    if (!p->gbm.device) {
        MP_ERR(ctx->vo, "Failed to create GBM device.\n");
        return false;
    }

    MP_VERBOSE(ctx->vo, "Initializing GBM surface (%d x %d)\n",
               p->kms->mode.hdisplay, p->kms->mode.vdisplay);
    p->gbm.surface = gbm_surface_create(
                         p->gbm.device,
                         p->kms->mode.hdisplay,
                         p->kms->mode.vdisplay,
                         GBM_BO_FORMAT_XRGB8888,
                         GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
    if (!p->gbm.surface) {
        MP_ERR(ctx->vo, "Failed to create GBM surface.\n");
        return false;
    }
    return true;
}
Exemple #14
0
static bool gfx_ctx_drm_egl_set_video_mode(void *data,
      unsigned width, unsigned height,
      bool fullscreen)
{
   static const EGLint egl_attribs_gl[] = {
      DRM_EGL_ATTRIBS_BASE,
      EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
      EGL_NONE,
   };

   static const EGLint egl_attribs_gles[] = {
      DRM_EGL_ATTRIBS_BASE,
      EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
      EGL_NONE,
   };

#ifdef EGL_KHR_create_context
   static const EGLint egl_attribs_gles3[] = {
      DRM_EGL_ATTRIBS_BASE,
      EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
      EGL_NONE,
   };
#endif

   static const EGLint egl_attribs_vg[] = {
      DRM_EGL_ATTRIBS_BASE,
      EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
      EGL_NONE,
   };

   const EGLint *attrib_ptr;
   EGLint major, minor, n, egl_attribs[16], *attr;
   float refresh_mod;
   int i, ret = 0;
   struct sigaction sa = {{0}};
   struct drm_fb *fb = NULL;
   gfx_ctx_drm_egl_data_t *drm = (gfx_ctx_drm_egl_data_t*)
      driver.video_context_data;

   if (!drm)
      return false;

   sa.sa_handler = sighandler;
   sa.sa_flags   = SA_RESTART;
   sigemptyset(&sa.sa_mask);
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);

   switch (g_api)
   {
      case GFX_CTX_OPENGL_API:
         attrib_ptr = egl_attribs_gl;
         break;
      case GFX_CTX_OPENGL_ES_API:
#ifdef EGL_KHR_create_context
         if (g_major >= 3)
            attrib_ptr = egl_attribs_gles3;
         else
#endif
         attrib_ptr = egl_attribs_gles;
         break;
      case GFX_CTX_OPENVG_API:
         attrib_ptr = egl_attribs_vg;
         break;
      default:
         attrib_ptr = NULL;
   }

   /* If we use black frame insertion, 
    * we fake a 60 Hz monitor for 120 Hz one, etc, so try to match that. */
   refresh_mod = g_settings.video.black_frame_insertion ? 0.5f : 1.0f;

   /* Find desired video mode, and use that.
    * If not fullscreen, we get desired windowed size, 
    * which is not appropriate. */
   if ((width == 0 && height == 0) || !fullscreen)
      drm->g_drm_mode = &drm->g_connector->modes[0];
   else
   {
      /* Try to match g_settings.video.refresh_rate as closely as possible.
       * Lower resolutions tend to have multiple supported 
       * refresh rates as well.
       */
      float minimum_fps_diff = 0.0f;

      /* Find best match. */
      for (i = 0; i < drm->g_connector->count_modes; i++)
      {
         if (width != drm->g_connector->modes[i].hdisplay || 
               height != drm->g_connector->modes[i].vdisplay)
            continue;

         float diff = fabsf(refresh_mod * 
               drm->g_connector->modes[i].vrefresh - g_settings.video.refresh_rate);
         if (!drm->g_drm_mode || diff < minimum_fps_diff)
         {
            drm->g_drm_mode = &drm->g_connector->modes[i];
            minimum_fps_diff = diff;
         }
      }
   }

   if (!drm->g_drm_mode)
   {
      RARCH_ERR("[KMS/EGL]: Did not find suitable video mode for %u x %u.\n", width, height);
      goto error;
   }

   drm->g_fb_width  = drm->g_drm_mode->hdisplay;
   drm->g_fb_height = drm->g_drm_mode->vdisplay;

   /* Create GBM surface. */
   drm->g_gbm_surface = gbm_surface_create(
         drm->g_gbm_dev,
         drm->g_fb_width,
         drm->g_fb_height,
         GBM_FORMAT_XRGB8888,
         GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);

   if (!drm->g_gbm_surface)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't create GBM surface.\n");
      goto error;
   }

   drm->g_egl_dpy = eglGetDisplay((EGLNativeDisplayType)drm->g_gbm_dev);
   if (!drm->g_egl_dpy)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't get EGL display.\n");
      goto error;
   }

   if (!eglInitialize(drm->g_egl_dpy, &major, &minor))
      goto error;

   if (!eglChooseConfig(drm->g_egl_dpy, attrib_ptr, &drm->g_config, 1, &n) || n != 1)
      goto error;

   attr = egl_fill_attribs(egl_attribs);

   drm->g_egl_ctx = eglCreateContext(drm->g_egl_dpy, drm->g_config, EGL_NO_CONTEXT,
         attr != egl_attribs ? egl_attribs : NULL);

   if (drm->g_egl_ctx == EGL_NO_CONTEXT)
      goto error;

   if (drm->g_use_hw_ctx)
   {
      drm->g_egl_hw_ctx = eglCreateContext(drm->g_egl_dpy, drm->g_config, drm->g_egl_ctx,
            attr != egl_attribs ? egl_attribs : NULL);
      RARCH_LOG("[KMS/EGL]: Created shared context: %p.\n", (void*)drm->g_egl_hw_ctx);

      if (drm->g_egl_hw_ctx == EGL_NO_CONTEXT)
         goto error;
   }

   drm->g_egl_surf = eglCreateWindowSurface(drm->g_egl_dpy,
         drm->g_config, (EGLNativeWindowType)drm->g_gbm_surface, NULL);
   if (!drm->g_egl_surf)
      goto error;

   if (!eglMakeCurrent(drm->g_egl_dpy,
            drm->g_egl_surf, drm->g_egl_surf, drm->g_egl_ctx))
      goto error;

   glClear(GL_COLOR_BUFFER_BIT);
   eglSwapBuffers(drm->g_egl_dpy, drm->g_egl_surf);

   drm->g_bo = gbm_surface_lock_front_buffer(drm->g_gbm_surface);
   fb = drm_fb_get_from_bo(drm, drm->g_bo);

   ret = drmModeSetCrtc(drm->g_drm_fd,
         drm->g_crtc_id, fb->fb_id, 0, 0, &drm->g_connector_id, 1, drm->g_drm_mode);
   if (ret < 0)
      goto error;

   return true;

error:
   gfx_ctx_drm_egl_destroy_resources(drm);

   if (drm)
      free(drm);

   return false;
}
Exemple #15
0
static bool gfx_ctx_init(void)
{
   if (g_inited)
      return false;

   static const char *modules[] = {
      "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", NULL
   };

   for (int i = 0; modules[i]; i++)
   {
      RARCH_LOG("[KMS/EGL]: Trying to load module %s ...\n", modules[i]);
      g_drm_fd = drmOpen(modules[i], NULL);
      if (g_drm_fd >= 0)
      {
         RARCH_LOG("[KMS/EGL]: Found module %s.\n", modules[i]);
         break;
      }
   }

   if (g_drm_fd < 0)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't open DRM device.\n");
      goto error;
   }

   g_resources = drmModeGetResources(g_drm_fd);
   if (!g_resources)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't get device resources.\n");
      goto error;
   }

   for (int i = 0; i < g_resources->count_connectors; i++)
   {
      g_connector = drmModeGetConnector(g_drm_fd, g_resources->connectors[i]);
      if (g_connector->connection == DRM_MODE_CONNECTED)
         break;

      drmModeFreeConnector(g_connector);
      g_connector = NULL;
   }

   // TODO: Figure out what index for crtcs to use ...
   g_orig_crtc = drmModeGetCrtc(g_drm_fd, g_resources->crtcs[0]);
   if (!g_orig_crtc)
      RARCH_WARN("[KMS/EGL]: Cannot find original CRTC.\n");

   if (!g_connector)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't get device connector.\n");
      goto error;
   }

   for (int i = 0, area = 0; i < g_connector->count_modes; i++)
   {
      drmModeModeInfo *current_mode = &g_connector->modes[i];
      int current_area = current_mode->hdisplay * current_mode->vdisplay;
      if (current_area > area)
      {
         g_drm_mode = current_mode;
         area       = current_area;
      }
   }

   if (!g_drm_mode)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't find DRM mode.\n");
      goto error;
   }

	for (int i = 0; i < g_resources->count_encoders; i++)
   {
		g_encoder = drmModeGetEncoder(g_drm_fd, g_resources->encoders[i]);
		if (g_encoder->encoder_id == g_connector->encoder_id)
			break;

		drmModeFreeEncoder(g_encoder);
		g_encoder = NULL;
	}

	if (!g_encoder)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't find DRM encoder.\n");
      goto error;
   }

   g_crtc_id      = g_encoder->crtc_id;
   g_connector_id = g_connector->connector_id;

   g_fb_width  = g_drm_mode->hdisplay;
   g_fb_height = g_drm_mode->vdisplay;

   g_gbm_dev     = gbm_create_device(g_drm_fd);
   g_gbm_surface = gbm_surface_create(g_gbm_dev,
         g_fb_width, g_fb_height,
         GBM_FORMAT_XRGB8888,
         GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);

   if (!g_gbm_surface)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't create GBM surface.\n");
      goto error;
   }

   return true;

error:
   gfx_ctx_destroy();
   return false;
}
Exemple #16
0
static bool gfx_ctx_init(void)
{
   if (g_inited)
      return false;

   g_drm_fd = open("/dev/dri/card0", O_RDWR);
   if (g_drm_fd < 0)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't open DRM device.\n");
      goto error;
   }

   g_resources = drmModeGetResources(g_drm_fd);
   if (!g_resources)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't get device resources.\n");
      goto error;
   }

   for (int i = 0; i < g_resources->count_connectors; i++)
   {
      g_connector = drmModeGetConnector(g_drm_fd, g_resources->connectors[i]);

      if (!g_connector)
         continue;
      if (g_connector->connection == DRM_MODE_CONNECTED && g_connector->count_modes > 0)
         break;

      drmModeFreeConnector(g_connector);
      g_connector = NULL;
   }

   if (!g_connector)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't get device connector.\n");
      goto error;
   }

   for (int i = 0; i < g_resources->count_encoders; i++)
   {
      g_encoder = drmModeGetEncoder(g_drm_fd, g_resources->encoders[i]);

      if (!g_encoder)
         continue;
      if (g_encoder->encoder_id == g_connector->encoder_id)
         break;

      drmModeFreeEncoder(g_encoder);
      g_encoder = NULL;
   }

   if (!g_encoder)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't find DRM encoder.\n");
      goto error;
   }

   g_drm_mode = &g_connector->modes[0];

   g_crtc_id   = g_encoder->crtc_id;
   g_orig_crtc = drmModeGetCrtc(g_drm_fd, g_crtc_id);
   if (!g_orig_crtc)
      RARCH_WARN("[KMS/EGL]: Cannot find original CRTC.\n");

   g_connector_id = g_connector->connector_id;

   g_fb_width  = g_drm_mode->hdisplay;
   g_fb_height = g_drm_mode->vdisplay;

   g_gbm_dev     = gbm_create_device(g_drm_fd);
   g_gbm_surface = gbm_surface_create(g_gbm_dev,
         g_fb_width, g_fb_height,
         GBM_FORMAT_XRGB8888,
         GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);

   if (!g_gbm_surface)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't create GBM surface.\n");
      goto error;
   }

   return true;

error:
   gfx_ctx_destroy();
   return false;
}
Exemple #17
0
/*!***********************************************************************
 @Function		OsInitOS
 @description	Saves instance handle and creates main window
				In this function, we save the instance handle in a global variable and
				create and display the main program window.
*************************************************************************/
bool PVRShellInit::OsInitOS()
{
	bool bFound;

	/*
		In the future we could be fancy here by getting the drm device from udev.
		For the time being, we've added a command-line option so the use can pass
		it in. By default just use card0.
	*/
	if((m_i32DrmFile = open(DRIDEVNAME, O_RDWR)) < 0) 
	{
		m_pShell->PVRShellOutputDebug("failed to open drm device %s : %s\n", DRIDEVNAME, strerror(errno));
		return false;
	}

	m_psDrmResources = drmModeGetResources(m_i32DrmFile);
	
	if (!m_psDrmResources) 
	{
		m_pShell->PVRShellOutputDebug("drmModeGetResources failed: %s\n", strerror(errno));
		return false;
	}

	// find a connected connector
	bFound = false;
	
	for (int i = 0; i < m_psDrmResources->count_connectors; ++i) 
	{
		m_psDrmConnector = drmModeGetConnector(m_i32DrmFile, m_psDrmResources->connectors[i]);

		if (m_psDrmConnector->connection != DRM_MODE_CONNECTED) 
		{
			drmModeFreeConnector(m_psDrmConnector);
			continue;
		}

		if (m_ui32DrmDisplayId == 0) 
		{
			bFound = true;
			break;
		}

		if (m_ui32DrmDisplayId == m_psDrmConnector->connector_id) 
		{
			bFound = true;
			break;
		}
	}

	if (bFound == false) 
	{
		m_pShell->PVRShellOutputDebug("No Connector found for requested device\n");
		return false;
	}

	m_ui32DrmConnectorId = m_psDrmConnector->connector_id;
	m_psDrmMode = &m_psDrmConnector->modes[0];

	bFound = false;

	for (int j = 0; j < m_psDrmResources->count_encoders; ++j) 
	{
		m_psDrmEncoder = drmModeGetEncoder(m_i32DrmFile, m_psDrmResources->encoders[j]);
		
		if (m_psDrmEncoder->encoder_id == m_psDrmConnector->encoder_id) 
		{
			bFound = true;
			break;
		}

		drmModeFreeEncoder(m_psDrmEncoder);
	}

	if(!bFound) 
	{
		m_pShell->PVRShellOutputDebug("No Encoder found for requested Connector\n");
		return false;
	}

	m_ui32DrmEncoderId = m_psDrmEncoder->encoder_id;
	m_ui32DrmCrtcId = m_psDrmEncoder->crtc_id;

	for (int j=0; j<m_psDrmResources->count_crtcs; ++j) 
	{
		m_psDrmCrtc = drmModeGetCrtc(m_i32DrmFile, m_psDrmResources->crtcs[j]);
		
		if (m_psDrmCrtc->crtc_id == m_ui32DrmCrtcId) 
		{
			break;
		}

		drmModeFreeCrtc(m_psDrmCrtc);
	}


	m_pShell->m_pShellData->nShellDimX = m_psDrmMode->hdisplay;
	m_pShell->m_pShellData->nShellDimY = m_psDrmMode->vdisplay;

	m_psGbmDev = gbm_create_device(m_i32DrmFile);
	m_psGbmSurface = gbm_surface_create(m_psGbmDev,
			m_pShell->m_pShellData->nShellDimX,
			m_pShell->m_pShellData->nShellDimY,
			GBM_FORMAT_XRGB8888,
			GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);

	if (!m_psGbmSurface) 
	{
		m_pShell->PVRShellOutputDebug("failed to create gbm surface\n");
		return false;
	}

	m_ui32NativeDisplay = (unsigned int)m_psGbmDev;
	m_ui32NativeWindow = (unsigned int)m_psGbmSurface;
	m_ui32CurrentFb = 0;
	return true;
}
Exemple #18
0
static bool gfx_ctx_drm_set_video_mode(void *data,
      unsigned width, unsigned height,
      bool fullscreen)
{
   float refresh_mod;
   int i, ret                  = 0;
   struct drm_fb *fb           = NULL;
   settings_t *settings        = config_get_ptr();
   gfx_ctx_drm_data_t *drm     = (gfx_ctx_drm_data_t*)data;

   if (!drm)
      return false;

   frontend_driver_install_signal_handler();

   /* If we use black frame insertion, 
    * we fake a 60 Hz monitor for 120 Hz one, 
    * etc, so try to match that. */
   refresh_mod = settings->video.black_frame_insertion 
      ? 0.5f : 1.0f;

   /* Find desired video mode, and use that.
    * If not fullscreen, we get desired windowed size, 
    * which is not appropriate. */
   if ((width == 0 && height == 0) || !fullscreen)
      g_drm_mode = &g_drm_connector->modes[0];
   else
   {
      /* Try to match settings->video.refresh_rate 
       * as closely as possible.
       *
       * Lower resolutions tend to have multiple supported 
       * refresh rates as well.
       */
      float minimum_fps_diff = 0.0f;

      /* Find best match. */
      for (i = 0; i < g_drm_connector->count_modes; i++)
      {
         float diff;
         if (width != g_drm_connector->modes[i].hdisplay || 
               height != g_drm_connector->modes[i].vdisplay)
            continue;

         diff = fabsf(refresh_mod * g_drm_connector->modes[i].vrefresh
               - settings->video.refresh_rate);

         if (!g_drm_mode || diff < minimum_fps_diff)
         {
            g_drm_mode = &g_drm_connector->modes[i];
            minimum_fps_diff = diff;
         }
      }
   }

   if (!g_drm_mode)
   {
      RARCH_ERR("[KMS/EGL]: Did not find suitable video mode for %u x %u.\n",
            width, height);
      goto error;
   }

   drm->fb_width    = g_drm_mode->hdisplay;
   drm->fb_height   = g_drm_mode->vdisplay;

   /* Create GBM surface. */
   g_gbm_surface = gbm_surface_create(
         g_gbm_dev,
         drm->fb_width,
         drm->fb_height,
         GBM_FORMAT_XRGB8888,
         GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);

   if (!g_gbm_surface)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't create GBM surface.\n");
      goto error;
   }


   switch (drm_api)
   {
      case GFX_CTX_OPENGL_API:
      case GFX_CTX_OPENGL_ES_API:
      case GFX_CTX_OPENVG_API:
#ifdef HAVE_EGL
         if (!gfx_ctx_drm_egl_set_video_mode(drm))
            goto error;
#endif
         break;
      case GFX_CTX_NONE:
      default:
         break;
   }

   g_bo = gbm_surface_lock_front_buffer(g_gbm_surface);
   fb   = drm_fb_get_from_bo(g_bo);

   ret  = drmModeSetCrtc(g_drm_fd,
         g_crtc_id, fb->fb_id, 0, 0, &g_connector_id, 1, g_drm_mode);
   if (ret < 0)
      goto error;

   return true;

error:
   gfx_ctx_drm_destroy_resources(drm);

   if (drm)
      free(drm);

   return false;
}
Exemple #19
0
static bool gfx_ctx_set_video_mode(void *data,
      unsigned width, unsigned height,
      bool fullscreen)
{
   if (g_inited)
      return false;

   int i;
   int ret = 0;
   struct drm_fb *fb = NULL;

   struct sigaction sa = {{0}};
   sa.sa_handler = sighandler;
   sa.sa_flags   = SA_RESTART;
   sigemptyset(&sa.sa_mask);
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);

#define EGL_ATTRIBS_BASE \
   EGL_SURFACE_TYPE,    EGL_WINDOW_BIT, \
   EGL_RED_SIZE,        1, \
   EGL_GREEN_SIZE,      1, \
   EGL_BLUE_SIZE,       1, \
   EGL_ALPHA_SIZE,      0, \
   EGL_DEPTH_SIZE,      0

   static const EGLint egl_attribs_gl[] = {
      EGL_ATTRIBS_BASE,
      EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
      EGL_NONE,
   };

   static const EGLint egl_attribs_gles[] = {
      EGL_ATTRIBS_BASE,
      EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
      EGL_NONE,
   };

#ifdef EGL_KHR_create_context
   static const EGLint egl_attribs_gles3[] = {
      EGL_ATTRIBS_BASE,
      EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
      EGL_NONE,
   };
#endif

   static const EGLint egl_attribs_vg[] = {
      EGL_ATTRIBS_BASE,
      EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
      EGL_NONE,
   };

   const EGLint *attrib_ptr;
   switch (g_api)
   {
      case GFX_CTX_OPENGL_API:
         attrib_ptr = egl_attribs_gl;
         break;
      case GFX_CTX_OPENGL_ES_API:
#ifdef EGL_KHR_create_context
         if (g_major >= 3)
            attrib_ptr = egl_attribs_gles3;
         else
#endif
         attrib_ptr = egl_attribs_gles;
         break;
      case GFX_CTX_OPENVG_API:
         attrib_ptr = egl_attribs_vg;
         break;
      default:
         attrib_ptr = NULL;
   }

   // Find desired video mode, and use that.
   // If not fullscreen, we get desired windowed size, which is not appropriate.
   if ((width == 0 && height == 0) || !fullscreen)
      g_drm_mode = &g_connector->modes[0];
   else
   {
      // Try to match g_settings.video.refresh_rate as closely as possible.
      // Lower resolutions tend to have multiple supported refresh rates as well.
      float minimum_fps_diff = 0.0f;

      // Find best match.
      for (i = 0; i < g_connector->count_modes; i++)
      {
         if (width != g_connector->modes[i].hdisplay || height != g_connector->modes[i].vdisplay)
            continue;

         if (!g_drm_mode)
         {
            g_drm_mode = &g_connector->modes[i];
            minimum_fps_diff = g_drm_mode->vrefresh - g_settings.video.refresh_rate;
         }
         else
         {
            float diff = g_connector->modes[i].vrefresh - g_settings.video.refresh_rate;
            if (diff < minimum_fps_diff)
            {
               g_drm_mode = &g_connector->modes[i];
               minimum_fps_diff = diff;
            }
         }
      }
   }

   if (!g_drm_mode)
   {
      RARCH_ERR("[KMS/EGL]: Did not find suitable video mode for %u x %u.\n", width, height);
      goto error;
   }

   g_fb_width = g_drm_mode->hdisplay;
   g_fb_height = g_drm_mode->vdisplay;

   // Create GBM surface.
   g_gbm_surface = gbm_surface_create(g_gbm_dev,
         g_fb_width, g_fb_height,
         GBM_FORMAT_XRGB8888,
         GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);

   if (!g_gbm_surface)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't create GBM surface.\n");
      goto error;
   }

   g_egl_dpy = eglGetDisplay((EGLNativeDisplayType)g_gbm_dev);
   if (!g_egl_dpy)
   {
      RARCH_ERR("[KMS/EGL]: Couldn't get EGL display.\n");
      goto error;
   }

   EGLint major, minor;
   if (!eglInitialize(g_egl_dpy, &major, &minor))
      goto error;

   EGLint n;
   if (!eglChooseConfig(g_egl_dpy, attrib_ptr, &g_config, 1, &n) || n != 1)
      goto error;

   EGLint egl_attribs[16];
   EGLint *attr = egl_attribs;
   attr = egl_fill_attribs(attr);

   g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT,
         attr != egl_attribs ? egl_attribs : NULL);

   if (g_egl_ctx == EGL_NO_CONTEXT)
      goto error;

   if (g_use_hw_ctx)
   {
      g_egl_hw_ctx = eglCreateContext(g_egl_dpy, g_config, g_egl_ctx,
            attr != egl_attribs ? egl_attribs : NULL);
      RARCH_LOG("[KMS/EGL]: Created shared context: %p.\n", (void*)g_egl_hw_ctx);

      if (g_egl_hw_ctx == EGL_NO_CONTEXT)
         goto error;
   }

   g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, (EGLNativeWindowType)g_gbm_surface, NULL);
   if (!g_egl_surf)
      goto error;

   if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx))
      goto error;

   glClear(GL_COLOR_BUFFER_BIT);
   eglSwapBuffers(g_egl_dpy, g_egl_surf);

   g_bo = gbm_surface_lock_front_buffer(g_gbm_surface);
   fb = drm_fb_get_from_bo(g_bo);

   ret = drmModeSetCrtc(g_drm_fd, g_crtc_id, fb->fb_id, 0, 0, &g_connector_id, 1, g_drm_mode);
   if (ret < 0)
      goto error;

   g_inited = true;
   return true;

error:
   gfx_ctx_destroy(data);
   return false;
}
RenderingBackendGBM::OffscreenSurface::OffscreenSurface(const RenderingBackendGBM& renderingBackend)
{
    m_surface = gbm_surface_create(renderingBackend.m_gbm.device, 1, 1, GBM_FORMAT_ARGB8888, 0);
}
Exemple #21
0
int main(int argc, char *argv[])
{
   EGLDisplay dpy;
   EGLContext ctx;
   EGLSurface surface;
   EGLConfig config;
   EGLint major, minor, n;
   const char *ver;
   uint32_t handle, stride;
   struct kms kms;
   int ret, fd;
   struct gbm_device *gbm;
   struct gbm_bo *bo;
   drmModeCrtcPtr saved_crtc;
   struct gbm_surface *gs;

   fd = open(device_name, O_RDWR);
   if (fd < 0) {
      /* Probably permissions error */
      fprintf(stderr, "couldn't open %s, skipping\n", device_name);
      return -1;
   }

   gbm = gbm_create_device(fd);
   if (gbm == NULL) {
      fprintf(stderr, "couldn't create gbm device\n");
      ret = -1;
      goto close_fd;
   }

   dpy = eglGetDisplay(gbm);
   if (dpy == EGL_NO_DISPLAY) {
      fprintf(stderr, "eglGetDisplay() failed\n");
      ret = -1;
      goto destroy_gbm_device;
   }
	
   if (!eglInitialize(dpy, &major, &minor)) {
      printf("eglInitialize() failed\n");
      ret = -1;
      goto egl_terminate;
   }

   ver = eglQueryString(dpy, EGL_VERSION);
   printf("EGL_VERSION = %s\n", ver);

   if (!setup_kms(fd, &kms)) {
      ret = -1;
      goto egl_terminate;
   }

   eglBindAPI(EGL_OPENGL_API);

   if (!eglChooseConfig(dpy, attribs, &config, 1, &n) || n != 1) {
      fprintf(stderr, "failed to choose argb config\n");
      goto egl_terminate;
   }
   
   ctx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL);
   if (ctx == NULL) {
      fprintf(stderr, "failed to create context\n");
      ret = -1;
      goto egl_terminate;
   }

   gs = gbm_surface_create(gbm, kms.mode.hdisplay, kms.mode.vdisplay,
			   GBM_BO_FORMAT_XRGB8888,
			   GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
   surface = eglCreateWindowSurface(dpy, config, gs, NULL);

   if (!eglMakeCurrent(dpy, surface, surface, ctx)) {
      fprintf(stderr, "failed to make context current\n");
      ret = -1;
      goto destroy_context;
   }

   render_stuff(kms.mode.hdisplay, kms.mode.vdisplay);

   eglSwapBuffers(dpy, surface);

   bo = gbm_surface_lock_front_buffer(gs);
   handle = gbm_bo_get_handle(bo).u32;
   stride = gbm_bo_get_stride(bo);

   printf("handle=%d, stride=%d\n", handle, stride);

   ret = drmModeAddFB(fd,
		      kms.mode.hdisplay, kms.mode.vdisplay,
		      24, 32, stride, handle, &kms.fb_id);
   if (ret) {
      fprintf(stderr, "failed to create fb\n");
      goto rm_fb;
   }

   saved_crtc = drmModeGetCrtc(fd, kms.encoder->crtc_id);
   if (saved_crtc == NULL)
      goto rm_fb;

   ret = drmModeSetCrtc(fd, kms.encoder->crtc_id, kms.fb_id, 0, 0,
			&kms.connector->connector_id, 1, &kms.mode);
   if (ret) {
      fprintf(stderr, "failed to set mode: %m\n");
      goto free_saved_crtc;
   }

   getchar();

   ret = drmModeSetCrtc(fd, saved_crtc->crtc_id, saved_crtc->buffer_id,
                        saved_crtc->x, saved_crtc->y,
                        &kms.connector->connector_id, 1, &saved_crtc->mode);
   if (ret) {
      fprintf(stderr, "failed to restore crtc: %m\n");
   }

free_saved_crtc:
   drmModeFreeCrtc(saved_crtc);
rm_fb:
   drmModeRmFB(fd, kms.fb_id);
   eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
destroy_context:
   eglDestroyContext(dpy, ctx);
egl_terminate:
   eglTerminate(dpy);
destroy_gbm_device:
   gbm_device_destroy(gbm);
close_fd:
   close(fd);

   return ret;
}
Exemple #22
0
int main(int argc, char *argv[])
{
	EGLDisplay dpy;
	EGLContext ctx;
	EGLConfig config;
	EGLSurface surface;
	EGLint major, minor, n;
	const char *ver;
	uint32_t handle, stride;
	int ret, fd, frames = 0;
	struct gbm_device *gbm;
	drmModeCrtcPtr saved_crtc;
	time_t start, end;
	char *data;
	char j;
	int i;
	int once;
	once = 0;

	signal (SIGINT, quit_handler);

	fd = open(device_name, O_RDWR);
	if (fd < 0) {
		/* Probably permissions error */
		fprintf(stderr, "couldn't open %s, skipping\n", device_name);
		return -1;
	}

	gbm = gbm_create_device(fd);
	if (gbm == NULL) {
		fprintf(stderr, "couldn't create gbm device\n");
		ret = -1;
		goto close_fd;
	}

	dpy = eglGetDisplay(gbm);
	if (dpy == EGL_NO_DISPLAY) {
		fprintf(stderr, "eglGetDisplay() failed\n");
		ret = -1;
		goto destroy_gbm_device;
	}

	if (!eglInitialize(dpy, &major, &minor)) {
		printf("eglInitialize() failed\n");
		ret = -1;
		goto egl_terminate;
	}

	ver = eglQueryString(dpy, EGL_VERSION);
	printf("EGL_VERSION = %s\n", ver);

	if (!setup_kms(fd, &kms)) {
		ret = -1;
		goto egl_terminate;
	}

	eglBindAPI(EGL_OPENGL_API);

	if (!eglChooseConfig(dpy, attribs, &config, 1, &n) || n != 1) {
		fprintf(stderr, "failed to choose argb config\n");
		goto egl_terminate;
	}

	ctx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL);
	if (ctx == NULL) {
		fprintf(stderr, "failed to create context\n");
		ret = -1;
		goto egl_terminate;
	}

	gs = gbm_surface_create(gbm, kms.mode.hdisplay, kms.mode.vdisplay,
		GBM_BO_FORMAT_XRGB8888,
		GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
	if (gs == NULL) {
		fprintf(stderr, "unable to create gbm surface\n");
		ret = -1;
		goto egl_terminate;
	}


	surface = eglCreateWindowSurface(dpy, config, gs, NULL);
	if (surface == EGL_NO_SURFACE) {
		fprintf(stderr, "failed to create surface\n");
		ret = -1;
		goto destroy_gbm_surface;
	}

	if (!eglMakeCurrent(dpy, surface, surface, ctx)) {
		fprintf(stderr, "failed to make context current\n");
		ret = -1;
		goto destroy_surface;
	}

	saved_crtc = drmModeGetCrtc(fd, kms.crtc_id);
	if (saved_crtc == NULL)
	{
		fprintf(stderr, "no valid graphic configuration active (VT ?)\n");
	}
	time(&start);
	do {

		drmEventContext evctx;
		fd_set rfds;

		render_stuff(kms.mode.hdisplay, kms.mode.vdisplay);
		eglSwapBuffers(dpy, surface);
		
		if (!gbm_surface_has_free_buffers(gs))
			fprintf(stderr, "out of free buffers\n");

		next_bo = gbm_surface_lock_front_buffer(gs);
		if (!next_bo)
			fprintf(stderr, "failed to lock front buffer: %m\n");

		handle = gbm_bo_get_handle(next_bo).u32;
		stride = gbm_bo_get_stride(next_bo);
		
		ret = drmModeAddFB(fd,
				 kms.mode.hdisplay, kms.mode.vdisplay,
				 24, 32, stride, handle, &next_fb_id);
		if (ret) {
			fprintf(stderr, "failed to create fb\n");
			goto out;
		}
		  
		/* make sure to setup crtc once (fix for broken drivers) */
		if(once == 0){
			once = 1;
			drmModeSetCrtc(fd, kms.crtc_id, next_fb_id,
				0, 0,
				&kms.connector->connector_id, 1, &kms.mode);
		}
		
		ret = drmModePageFlip(fd, kms.crtc_id,
					next_fb_id,
					DRM_MODE_PAGE_FLIP_EVENT, 0);
		if (ret) {
			fprintf(stderr, "failed to page flip: %m\n");
			goto out;
		}

		FD_ZERO(&rfds);
		FD_SET(fd, &rfds);

		while (select(fd + 1, &rfds, NULL, NULL, NULL) == -1)
			NULL;

		memset(&evctx, 0, sizeof evctx);
		evctx.version = DRM_EVENT_CONTEXT_VERSION;
		evctx.page_flip_handler = page_flip_handler;

		drmHandleEvent(fd, &evctx);

		frames++;
	} while (!quit);
	time(&end);

	printf("Frames per second: %.2lf\n", frames / difftime(end, start));

out:
	if(saved_crtc){
		drmModeSetCrtc(fd, saved_crtc->crtc_id, saved_crtc->buffer_id,
			saved_crtc->x, saved_crtc->y,
			&kms.connector->connector_id, 1, &saved_crtc->mode);
		}
	drmModeFreeCrtc(saved_crtc);
	if (current_fb_id)
		drmModeRmFB(fd, current_fb_id);
	if (next_fb_id)
		drmModeRmFB(fd, next_fb_id);
	eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
destroy_context:
	eglDestroyContext(dpy, ctx);
destroy_surface:
	eglDestroySurface(dpy, surface);
destroy_gbm_surface:
	gbm_surface_destroy(gs);
egl_terminate:
	eglTerminate(dpy);
destroy_gbm_device:
	gbm_device_destroy(gbm);
close_fd:
	close(fd);

	return ret;
}