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); }
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); }
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); }
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; }
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)); }
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; }
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; }
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; }
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; }
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; }
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; }
/*!*********************************************************************** @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; }
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; }
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); }
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; }
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; }