int armsoc_bo_add_fb(struct armsoc_bo *bo) { int ret, depth = bo->depth; assert(bo->refcnt > 0); assert(bo->fb_id == 0); if (bo->bpp == 32 && bo->depth == 32 && !bo->dev->alpha_supported) depth = 24; ret = drmModeAddFB(bo->dev->fd, bo->width, bo->height, depth, bo->bpp, bo->pitch, bo->handle, &bo->fb_id); if (ret < 0 && bo->bpp == 32 && bo->depth == 32 && bo->dev->alpha_supported) { /* The DRM driver may not support an alpha channel but * it is possible to continue by ignoring the alpha, so * if an attempt to create a depth 32, bpp 32 framebuffer * fails we retry with depth 24, bpp 32 */ xf86DrvMsg(-1, X_WARNING, "depth 32 FB unsupported : falling back to depth 24\n"); bo->dev->alpha_supported = FALSE; ret = drmModeAddFB(bo->dev->fd, bo->width, bo->height, 24, bo->bpp, bo->pitch, bo->handle, &bo->fb_id); } if (ret < 0) { bo->fb_id = 0; return ret; } return 0; }
struct SDrmFbWrapper *PVRShellInitOS::DrmFbGetFromBo(struct gbm_bo *bo) { struct SDrmFbWrapper *fb = (struct SDrmFbWrapper *)gbm_bo_get_user_data(bo); uint32_t width, height, stride, handle; int ret; if (fb) { return fb; } fb = new struct SDrmFbWrapper; fb->psGbmBo = bo; fb->i32Fd = m_i32DrmFile; width = gbm_bo_get_width(bo); height = gbm_bo_get_height(bo); stride = gbm_bo_get_stride(bo); handle = gbm_bo_get_handle(bo).u32; ret = drmModeAddFB(m_i32DrmFile, width, height, 24, 32, stride, handle, &fb->ui32FbId); if (ret) { delete fb; return NULL; } gbm_bo_set_user_data(bo, fb, pfnCallbackDrmFbDestroy); return fb; }
static struct drm_fb *drm_fb_get_from_bo(struct gbm_bo *bo) { struct drm_fb *fb = (struct drm_fb*)gbm_bo_get_user_data(bo); if (fb) return fb; fb = (struct drm_fb*)calloc(1, sizeof(*fb)); fb->bo = bo; unsigned width = gbm_bo_get_width(bo); unsigned height = gbm_bo_get_height(bo); unsigned stride = gbm_bo_get_stride(bo); unsigned handle = gbm_bo_get_handle(bo).u32; int ret = drmModeAddFB(g_drm_fd, width, height, 24, 32, stride, handle, &fb->fb_id); if (ret < 0) { RARCH_ERR("[KMS/EGL]: Failed to create FB: %s\n", strerror(errno)); free(fb); return NULL; } gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback); return fb; }
NativeStateDRM::DRMFBState* NativeStateDRM::fb_get_from_bo(gbm_bo* bo) { DRMFBState* fb = reinterpret_cast<DRMFBState*>(gbm_bo_get_user_data(bo)); if (fb) { return fb; } unsigned int width = gbm_bo_get_width(bo); unsigned int height = gbm_bo_get_height(bo); unsigned int stride = gbm_bo_get_stride(bo); unsigned int handle = gbm_bo_get_handle(bo).u32; unsigned int fb_id(0); int status = drmModeAddFB(fd_, width, height, 24, 32, stride, handle, &fb_id); if (status < 0) { Log::error("Failed to create FB: %d\n", status); return 0; } fb = new DRMFBState(); fb->fd = fd_; fb->bo = bo; fb->fb_id = fb_id; gbm_bo_set_user_data(bo, fb, fb_destroy_callback); return fb; }
QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject(gbm_bo *bo) { { FrameBuffer *fb = static_cast<FrameBuffer *>(gbm_bo_get_user_data(bo)); if (fb) return fb; } uint32_t width = gbm_bo_get_width(bo); uint32_t height = gbm_bo_get_height(bo); uint32_t stride = gbm_bo_get_stride(bo); uint32_t handle = gbm_bo_get_handle(bo).u32; QScopedPointer<FrameBuffer> fb(new FrameBuffer); int ret = drmModeAddFB(device()->fd(), width, height, 24, 32, stride, handle, &fb->fb); if (ret) { qWarning("Failed to create KMS FB!"); return Q_NULLPTR; } gbm_bo_set_user_data(bo, fb.data(), bufferDestroyedHandler); return fb.take(); }
struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo) { struct drm_fb *fb = gbm_bo_get_user_data(bo); uint32_t width, height, stride, handle; int ret; if (fb) return fb; fb = calloc(1, sizeof *fb); fb->bo = bo; width = gbm_bo_get_width(bo); height = gbm_bo_get_height(bo); stride = gbm_bo_get_stride(bo); handle = gbm_bo_get_handle(bo).u32; ret = drmModeAddFB(drm.fd, width, height, 24, 32, stride, handle, &fb->fb_id); if (ret) { printf("failed to create fb: %s\n", strerror(errno)); free(fb); return NULL; } gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback); return fb; }
static void * drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) { ScrnInfoPtr scrn = crtc->scrn; drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; unsigned long rotate_pitch; uint32_t tiling; int ret; drmmode_crtc->rotate_bo = intel_allocate_framebuffer(scrn, width, height, drmmode->cpp, &rotate_pitch, &tiling); if (!drmmode_crtc->rotate_bo) { xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "Couldn't allocate shadow memory for rotated CRTC\n"); return NULL; } ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth, crtc->scrn->bitsPerPixel, rotate_pitch, drmmode_crtc->rotate_bo->handle, &drmmode_crtc->rotate_fb_id); if (ret) { ErrorF("failed to add rotate fb\n"); drm_intel_bo_unreference(drmmode_crtc->rotate_bo); return NULL; } drmmode_crtc->rotate_pitch = rotate_pitch; return drmmode_crtc->rotate_bo; }
static struct drm_fb *drm_fb_get_from_bo( gfx_ctx_drm_egl_data_t *drm, struct gbm_bo *bo) { int ret; unsigned width, height, stride, handle; struct drm_fb *fb = (struct drm_fb*)gbm_bo_get_user_data(bo); if (fb) return fb; fb = (struct drm_fb*)calloc(1, sizeof(*fb)); fb->bo = bo; width = gbm_bo_get_width(bo); height = gbm_bo_get_height(bo); stride = gbm_bo_get_stride(bo); handle = gbm_bo_get_handle(bo).u32; RARCH_LOG("[KMS/EGL]: New FB: %ux%u (stride: %u).\n", width, height, stride); ret = drmModeAddFB(drm->g_drm_fd, width, height, 24, 32, stride, handle, &fb->fb_id); if (ret < 0) { RARCH_ERR("[KMS/EGL]: Failed to create FB: %s\n", strerror(errno)); free(fb); return NULL; } gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback); return fb; }
static int test2(void) { drm_intel_bo *test_intel_bo; uint32_t fb_id; drmModeClip clip; int prime_fd; uint32_t udl_handle; int ret; test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096); drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); ret = drmPrimeFDToHandle(udl_fd, prime_fd, &udl_handle); if (ret) goto out; ret = drmModeAddFB(udl_fd, 640, 480, 16, 16, 640, udl_handle, &fb_id); if (ret) goto out; clip.x1 = 0; clip.y1 = 0; clip.x2 = 10; clip.y2 = 10; ret = drmModeDirtyFB(udl_fd, fb_id, &clip, 1); if (ret) { return ret; } out: dumb_bo_destroy(udl_fd, udl_handle); drm_intel_bo_unreference(test_intel_bo); return ret; }
static uint32_t create_buffer (ply_renderer_driver_t *driver, unsigned long width, unsigned long height, unsigned long *row_stride) { ply_renderer_buffer_t *buffer; buffer = ply_renderer_buffer_new (driver, width, height); if (buffer == NULL) { ply_trace ("Could not allocate GEM object for frame buffer: %m"); return 0; } if (drmModeAddFB (driver->device_fd, width, height, 24, 32, buffer->row_stride, buffer->handle, &buffer->id) != 0) { ply_trace ("Could not set up GEM object as frame buffer: %m"); ply_renderer_buffer_free (driver, buffer); return 0; } *row_stride = buffer->row_stride; buffer->added_fb = true; ply_hashtable_insert (driver->buffers, (void *) (uintptr_t) buffer->id, buffer); return buffer->id; }
/** * Add textures as DRM framebuffers. */ static boolean drm_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) { struct drm_surface *drmsurf = drm_surface(nsurf); struct drm_display *drmdpy = drmsurf->drmdpy; int num_framebuffers = (need_back) ? 2 : 1; int i, err; for (i = 0; i < num_framebuffers; i++) { struct drm_framebuffer *fb; enum native_attachment natt; struct winsys_handle whandle; uint block_bits; if (i == 0) { fb = &drmsurf->front_fb; natt = NATIVE_ATTACHMENT_FRONT_LEFT; } else { fb = &drmsurf->back_fb; natt = NATIVE_ATTACHMENT_BACK_LEFT; } if (!fb->texture) { /* make sure the texture has been allocated */ resource_surface_add_resources(drmsurf->rsurf, 1 << natt); fb->texture = resource_surface_get_single_resource(drmsurf->rsurf, natt); if (!fb->texture) return FALSE; } /* already initialized */ if (fb->buffer_id) continue; /* TODO detect the real value */ fb->is_passive = TRUE; memset(&whandle, 0, sizeof(whandle)); whandle.type = DRM_API_HANDLE_TYPE_KMS; if (!drmdpy->base.screen->resource_get_handle(drmdpy->base.screen, fb->texture, &whandle)) return FALSE; block_bits = util_format_get_blocksizebits(drmsurf->color_format); err = drmModeAddFB(drmdpy->fd, drmsurf->width, drmsurf->height, block_bits, block_bits, whandle.stride, whandle.handle, &fb->buffer_id); if (err) { fb->buffer_id = 0; return FALSE; } } return TRUE; }
ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, uint8_t depth, uint8_t bpp, uint32_t stride, uint32_t handle) :Framebuffer(card, width, height) { uint32_t id; int r = drmModeAddFB(card.fd(), width, height, depth, bpp, stride, handle, &id); if (r) throw invalid_argument("fob"); set_id(id); }
/* * Add a fb object for a bo. */ int gralloc_drm_bo_add_fb(struct gralloc_drm_bo_t *bo) { uint8_t bpp; if (bo->fb_id) return 0; bpp = gralloc_drm_get_bpp(bo->handle->format) * 8; return drmModeAddFB(bo->drm->fd, bo->handle->width, bo->handle->height, bpp, bpp, bo->handle->stride, bo->fb_handle, (uint32_t *) &bo->fb_id); }
static void swap(struct gbm_winsys *winsys) { struct gbm_dev *dev = winsys->dev; struct gbm_context *context = winsys->context; struct gbm_bo *bo; uint32_t handle, stride; uint32_t width, height; uint32_t fb_id; eglSwapBuffers(context->edpy, context->egl_surface); bo = gbm_surface_lock_front_buffer(context->gbm_surface); width = gbm_bo_get_width(bo); height = gbm_bo_get_height(bo); stride = gbm_bo_get_stride(bo); handle = gbm_bo_get_handle(bo).u32; if (drmModeAddFB(dev->fd, width, height, 24, /* depth */ 32, /* bpp */ stride, handle, &fb_id)) { fprintf(stderr, "Failed to create new back buffer handle: %m\n"); } else { if (dev->saved_crtc == NULL && set_initial_crtc(dev, fb_id)) return; if (drmModePageFlip(dev->fd, dev->crtc, fb_id, DRM_MODE_PAGE_FLIP_EVENT, dev)) { fprintf(stderr, "Failed to page flip: %m\n"); return; } dev->pending_swap = 1; wait_swap(dev); free_current_bo(context); context->current_bo = bo; context->current_fb_id = fb_id; } }
int armsoc_bo_add_fb(struct armsoc_bo *bo) { int ret; assert(bo->refcnt > 0); assert(bo->fb_id == 0); ret = drmModeAddFB(bo->dev->fd, bo->width, bo->height, bo->depth, bo->bpp, bo->pitch, bo->handle, &bo->fb_id); if (ret < 0) { bo->fb_id = 0; return ret; } return 0; }
void QKmsScreen::performPageFlip() { if (!m_next_bo) return; uint32_t width = gbm_bo_get_width(m_next_bo); uint32_t height = gbm_bo_get_height(m_next_bo); uint32_t stride = gbm_bo_get_stride(m_next_bo); uint32_t handle = gbm_bo_get_handle(m_next_bo).u32; uint32_t fb_id; int ret = drmModeAddFB(m_device->fd(), width, height, 24, 32, stride, handle, &fb_id); if (ret) { qFatal("kms: Failed to create fb: fd %d, w %d, h %d, stride %d, handle %d, ret %d", m_device->fd(), width, height, stride, handle, ret); } if (!m_modeSet) { //Set the Mode of the screen. int ret = drmModeSetCrtc(m_device->fd(), m_crtcId, fb_id, 0, 0, &m_connectorId, 1, &m_mode); if (ret) qFatal("failed to set mode"); m_modeSet = true; // Initialize cursor static int hideCursor = qgetenv("QT_QPA_KMS_HIDECURSOR").toInt(); if (!hideCursor) { QCursor cursor(Qt::ArrowCursor); m_cursor->changeCursor(&cursor, 0); } } int pageFlipStatus = drmModePageFlip(m_device->fd(), m_crtcId, fb_id, DRM_MODE_PAGE_FLIP_EVENT, this); if (pageFlipStatus) { qWarning("Pageflip status: %d", pageFlipStatus); gbm_surface_release_buffer(m_gbmSurface, m_next_bo); m_next_bo = 0; } }
static void update_framebuffer_from_bo( const struct MPGLContext *ctx, struct gbm_bo *bo) { struct priv *p = ctx->priv; p->fb.bo = bo; p->fb.fd = p->kms->fd; p->fb.width = gbm_bo_get_width(bo); p->fb.height = gbm_bo_get_height(bo); int stride = gbm_bo_get_stride(bo); int handle = gbm_bo_get_handle(bo).u32; int ret = drmModeAddFB(p->kms->fd, p->fb.width, p->fb.height, 24, 32, stride, handle, &p->fb.id); if (ret) { MP_ERR(ctx->vo, "Failed to create framebuffer: %s\n", mp_strerror(errno)); } gbm_bo_set_user_data(bo, &p->fb, framebuffer_destroy_callback); }
bool IntelHWComposerDrm::setupDrmFb(int disp, uint32_t fb_handler, drmModeModeInfoPtr mode) { if (mDrmFd < 0) { ALOGE("%s: invalid drm FD\n", __func__); return false; } if (!mode) { ALOGW("%s: invalid mode !\n", __func__); return false; } int width = mode->hdisplay; int height = mode->vdisplay; int stride = align_to(width*4, 64); uint32_t fb_id = 0; // Drm add FB int ret = drmModeAddFB(mDrmFd, width, height, 24, 32, stride, (uint32_t)(fb_handler), &fb_id); if (ret) { ALOGE("%s: Failed to add fb !", __func__); return false; } // add to local output structure drmModeFBPtr fbInfo = drmModeGetFB(mDrmFd, fb_id); if (!fbInfo) { ALOGE("%s: Failed to get fbInfo! ", __func__); return false; } setOutputFBInfo(disp, fbInfo); drmModeFreeFB(fbInfo); return true; }
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; }
static void _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen) { CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context; CoglDisplayEGL *egl_display = context->display->winsys; CoglDisplayKMS *kms_display = egl_display->platform; CoglRenderer *renderer = context->display->renderer; CoglRendererEGL *egl_renderer = renderer->winsys; CoglRendererKMS *kms_renderer = egl_renderer->platform; CoglOnscreenEGL *egl_onscreen = onscreen->winsys; CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform; uint32_t handle, stride; CoglFlipKMS *flip; GList *l; /* If we already have a pending swap then block until it completes */ while (kms_onscreen->next_fb_id != 0) handle_drm_event (kms_renderer); /* First chain-up. This will call eglSwapBuffers */ parent_vtable->onscreen_swap_buffers (onscreen); /* Now we need to set the CRTC to whatever is the front buffer */ kms_onscreen->next_bo = gbm_surface_lock_front_buffer (kms_onscreen->surface); #if (COGL_VERSION_ENCODE (COGL_GBM_MAJOR, COGL_GBM_MINOR, COGL_GBM_MICRO) >= \ COGL_VERSION_ENCODE (8, 1, 0)) stride = gbm_bo_get_stride (kms_onscreen->next_bo); #else stride = gbm_bo_get_pitch (kms_onscreen->next_bo); #endif handle = gbm_bo_get_handle (kms_onscreen->next_bo).u32; if (drmModeAddFB (kms_renderer->fd, kms_display->width, kms_display->height, 24, /* depth */ 32, /* bpp */ stride, handle, &kms_onscreen->next_fb_id)) { g_warning ("Failed to create new back buffer handle: %m"); gbm_surface_release_buffer (kms_onscreen->surface, kms_onscreen->next_bo); kms_onscreen->next_bo = NULL; kms_onscreen->next_fb_id = 0; return; } /* If this is the first framebuffer to be presented then we now setup the * crtc modes... */ if (kms_display->pending_set_crtc) { setup_crtc_modes (context->display, kms_onscreen->next_fb_id); kms_display->pending_set_crtc = FALSE; } flip = g_slice_new0 (CoglFlipKMS); flip->onscreen = onscreen; for (l = kms_display->outputs; l; l = l->next) { CoglOutputKMS *output = l->data; if (drmModePageFlip (kms_renderer->fd, output->encoder->crtc_id, kms_onscreen->next_fb_id, DRM_MODE_PAGE_FLIP_EVENT, flip)) { g_warning ("Failed to flip: %m"); continue; } flip->pending++; } if (flip->pending == 0) { drmModeRmFB (kms_renderer->fd, kms_onscreen->next_fb_id); gbm_surface_release_buffer (kms_onscreen->surface, kms_onscreen->next_bo); kms_onscreen->next_bo = NULL; kms_onscreen->next_fb_id = 0; g_slice_free (CoglFlipKMS, flip); flip = NULL; } else { /* Ensure the onscreen remains valid while it has any pending flips... */ cogl_object_ref (flip->onscreen); } }
static DFBResult mesaAllocateBuffer( CoreSurfacePool *pool, void *pool_data, void *pool_local, CoreSurfaceBuffer *buffer, CoreSurfaceAllocation *allocation, void *alloc_data ) { int ret; CoreSurface *surface; MesaPoolData *data = pool_data; MesaPoolLocalData *local = pool_local; MesaAllocationData *alloc = alloc_data; MesaData *mesa; (void)data; (void)local; D_DEBUG_AT( Mesa_Surfaces, "%s( %p )\n", __FUNCTION__, buffer ); D_MAGIC_ASSERT( pool, CoreSurfacePool ); D_MAGIC_ASSERT( data, MesaPoolData ); D_MAGIC_ASSERT( local, MesaPoolLocalData ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); mesa = local->mesa; D_ASSERT( mesa != NULL ); surface = buffer->surface; D_MAGIC_ASSERT( surface, CoreSurface ); EGLContext context = eglGetCurrentContext(); eglMakeCurrent( mesa->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, mesa->ctx ); GLint texture, fbo, rbo; glGetIntegerv( GL_TEXTURE_BINDING_2D, &texture ); glGetIntegerv( GL_FRAMEBUFFER_BINDING, &fbo ); glGetIntegerv( GL_RENDERBUFFER_BINDING, &rbo ); alloc->bo = gbm_bo_create( mesa->gbm, surface->config.size.w, surface->config.size.h, GBM_BO_FORMAT_ARGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING ); alloc->handle = gbm_bo_get_handle( alloc->bo ).u32; alloc->pitch = gbm_bo_get_stride( alloc->bo ); alloc->image = eglCreateImageKHR( mesa->dpy, NULL, EGL_NATIVE_PIXMAP_KHR, alloc->bo, NULL ); alloc->size = alloc->pitch * surface->config.size.h; D_DEBUG_AT( Mesa_Surfaces, " -> pitch %d, size %d\n", alloc->pitch, alloc->size ); allocation->size = alloc->size; /* * Color Render Buffer */ glGenRenderbuffers( 1, &alloc->color_rb ); glBindRenderbuffer( GL_RENDERBUFFER, alloc->color_rb ); glEGLImageTargetRenderbufferStorageOES( GL_RENDERBUFFER, alloc->image ); /* * Framebuffer */ glGenFramebuffers( 1, &alloc->fbo ); glBindFramebuffer( GL_FRAMEBUFFER, alloc->fbo ); glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, alloc->color_rb ); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { D_ERROR( "DirectFB/Mesa: Framebuffer not complete\n" ); } /* * Texture */ glGenTextures( 1, &alloc->texture ); glBindTexture( GL_TEXTURE_2D, alloc->texture ); glEGLImageTargetTexture2DOES( GL_TEXTURE_2D, alloc->image ); /* * Restore */ glBindRenderbuffer( GL_RENDERBUFFER, rbo ); glBindFramebuffer( GL_FRAMEBUFFER, fbo ); glBindTexture( GL_TEXTURE_2D, texture ); eglMakeCurrent( mesa->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, context ); /* * Mode Framebuffer */ ret = drmModeAddFB( local->mesa->fd, surface->config.size.w, surface->config.size.h, 24, 32, alloc->pitch, alloc->handle, &alloc->fb_id ); if (ret) { D_ERROR( "DirectFB/Mesa: drmModeAddFB() failed!\n" ); // return DFB_FAILURE; } D_MAGIC_SET( alloc, MesaAllocationData ); return DFB_OK; }
void QKmsBufferManager::setupBuffersForMode(const drmModeModeInfo &mode, int numBuffers) { eglMakeCurrent(m_screen->device()->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, m_screen->device()->eglContext()); m_screen->bindFramebuffer(); if (m_frameBufferObject) { clearBuffers(); } else { //Setup Framebuffer Object glGenFramebuffers(1, &m_frameBufferObject); glBindFramebuffer(GL_FRAMEBUFFER, m_frameBufferObject); } //Setup shared Depth/Stencil buffer glGenRenderbuffers(1, &m_depthAndStencilBufferObject); glBindRenderbuffer(GL_RENDERBUFFER, m_depthAndStencilBufferObject); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, mode.hdisplay, mode.vdisplay); //Setup "numBuffer" many rendering targets for (int i = 0; i < numBuffers; i++) { QKmsFramebuffer *buffer = new QKmsFramebuffer(); glGenRenderbuffers(1, &buffer->renderBuffer); glBindRenderbuffer(GL_RENDERBUFFER, buffer->renderBuffer); buffer->graphicsBufferObject = gbm_bo_create(m_screen->device()->gbmDevice(), mode.hdisplay, mode.vdisplay, GBM_BO_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); buffer->eglImage = eglCreateImageKHR(m_screen->device()->eglDisplay(), 0, EGL_NATIVE_PIXMAP_KHR, buffer->graphicsBufferObject, 0); glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, buffer->eglImage); quint32 stride = gbm_bo_get_pitch(buffer->graphicsBufferObject); quint32 handle = gbm_bo_get_handle(buffer->graphicsBufferObject).u32; int status = drmModeAddFB(m_screen->device()->fd(), mode.hdisplay, mode.vdisplay, 32, 32, stride, handle, &buffer->framebufferId); //Todo: IF this returns true, then this is one less buffer that we use //Not so fatal, but not handled at the moment. if (status) qFatal("failed to add framebuffer"); m_framebuffers.append(buffer); } //Attach the Depth and Stencil buffer glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthAndStencilBufferObject); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthAndStencilBufferObject); //Attach renderbuffer as Color Attachment. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, this->renderTargetBuffer()); }
int main(int argc, char *argv[]) { uint64_t has_dumb; int ret, fd, opt, i; void *map; struct drm_mode_destroy_dumb dreq; struct drm_mode_create_dumb creq; struct drm_mode_map_dumb mreq; drmModePlaneRes *resources; drmModePlane *plane = NULL; uint32_t handle, stride, size; uint32_t plane_id, crtc_id; uint32_t width, height; uint32_t posx, posy; uint32_t fb; /* parse command line */ while ((opt = getopt(argc, argv, "x:y:w:v:c:p:h")) != -1) { switch (opt) { case 'x': posx = atoi(optarg); break; case 'y': posy = atoi(optarg); break; case 'w': width = atoi(optarg); break; case 'v': height = atoi(optarg); break; case 'p': plane_id = atoi(optarg); break; case 'c': crtc_id = atoi(optarg); break; case 'h': default: printf("usage: -h] -c <connector> -e <encoder> -m <mode>\n"); printf("\t-h: this help message\n"); printf("\t-c <crtc> crtc id, default is 0\n"); printf("\t-p <plane> plane id, default is 0\n"); printf("\t-x <posx> plane top left corner xpos, default is 0'\n"); printf("\t-y <posy> plane top left corner ypos, default is 0'\n"); printf("\t-w <width> plane width, default is 0'\n"); printf("\t-v <height> plane height, default is 0'\n"); exit(0); } } /* open drm device */ fd = open(device_name, O_RDWR | O_CLOEXEC); if (fd < 0) { perror("cannot open drm device"); exit(-1); } drmSetMaster(fd); /* check dumb buffer support */ if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0) { perror("DRM_CAP_DUMB_BUFFER ioctl"); ret = -EFAULT; goto err_close; } if (!has_dumb) { fprintf(stderr, "driver does not support dumb buffers\n"); ret = -EFAULT; goto err_close; } /* get plane */ resources = drmModeGetPlaneResources(fd); if (!resources || resources->count_planes == 0) { fprintf(stderr, "drmModeGetPlaneResources failed\n"); ret = -ENODEV; goto err_close; } for (i = 0; i < resources->count_planes; i++) { drmModePlane *p = drmModeGetPlane(fd, resources->planes[i]); if (!p) continue; if (p->plane_id == plane_id) { plane = p; break; } drmModeFreePlane(plane); } if (!plane) { fprintf(stderr, "couldn't find specified plane\n"); ret = -ENODEV; goto err_close; } /* create dumb buffer object */ memset(&creq, 0, sizeof(creq)); creq.height = height; creq.width = width; creq.bpp = 32; ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq); if (ret) { fprintf(stderr, "failed drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB)\n"); goto err_close; } handle = creq.handle; stride = creq.pitch; size = creq.size; /* create framebuffer for dumb buffer object */ ret = drmModeAddFB(fd, width, height, 24, 32, stride, handle, &fb); if (ret) { fprintf(stderr, "cannot add drm framebuffer for dumb buffer object\n"); goto err_destroy_dumb; } /* map dumb buffer object */ memset(&mreq, 0, sizeof(mreq)); mreq.handle = handle; ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq); if (ret) { fprintf(stderr, "failed drmIoctl(DRM_IOCTL_MODE_MAP_DUMB)\n"); goto err_destroy_fb; } map = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset); if (map == MAP_FAILED) { fprintf(stderr, "cannot mmap dumb buffer\n"); goto err_destroy_fb; } /* setup new plane */ ret = drmModeSetPlane(fd, plane_id, crtc_id, fb, 0, posx, posy, width, height, 0, 0, width << 16, height << 16); if (ret) { fprintf(stderr, "cannot set plane\n"); goto err_unmap; } /* draw on the screen */ draw_test_image((uint32_t *) map, width, height); getchar(); draw_fancy_image((uint32_t *) map, width, height); getchar(); drmModeSetPlane(fd, plane_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); err_unmap: if (map) munmap(map, size); err_destroy_fb: drmModeRmFB(fd, fb); err_destroy_dumb: memset(&dreq, 0, sizeof(dreq)); dreq.handle = handle; ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq); if (ret) { fprintf(stderr, "cannot destroy dumb buffer\n"); } err_close: close(fd); return ret; }
static Bool nouveau_present_flip_exec(ScrnInfoPtr scrn, uint64_t event_id, int sync, uint64_t target_msc, PixmapPtr pixmap, Bool vsync) { ScreenPtr screen = scrn->pScreen; struct nouveau_pixmap *priv = NULL; NVPtr pNv = NVPTR(scrn); uint32_t next_fb; CARD16 stride; CARD32 size; void *token; int ret; #ifdef HAVE_GLAMOR if (pNv->AccelMethod == GLAMOR && !(priv = nouveau_glamor_pixmap_get(pixmap))) { int fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size); if (fd < 0) return FALSE; priv = calloc(1, sizeof(*priv)); if (!priv) return FALSE; ret = nouveau_bo_prime_handle_ref(pNv->dev, fd, &priv->bo); if (ret) { free(priv); return FALSE; } nouveau_glamor_pixmap_set(pixmap, priv); } else #endif if (!priv) priv = nouveau_pixmap(pixmap); ret = drmModeAddFB(pNv->dev->fd, pixmap->drawable.width, pixmap->drawable.height, pixmap->drawable.depth, pixmap->drawable.bitsPerPixel, pixmap->devKind, priv->bo->handle, &next_fb); if (ret == 0) { struct nouveau_present_flip *flip = drmmode_event_queue(scrn, event_id, sizeof(*flip), nouveau_present_flip, &token); if (flip) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int last = 0, i; drmmode_swap(scrn, next_fb, &flip->old); flip->fd = pNv->dev->fd; flip->msc = target_msc; for (i = 0; i < config->num_crtc; i++) { if (config->crtc[i]->enabled) last = i; } for (i = 0; i < config->num_crtc; i++) { int type = vsync ? 0 : DRM_MODE_PAGE_FLIP_ASYNC; int crtc = drmmode_crtc(config->crtc[i]); void *user = NULL; if (!config->crtc[i]->enabled) continue; if (token && ((crtc == sync) || (i == last))) { type |= DRM_MODE_PAGE_FLIP_EVENT; user = token; } ret = drmModePageFlip(pNv->dev->fd, crtc, next_fb, type, user); if (ret == 0 && user) { token = NULL; } } if (token == NULL) { return TRUE; } drmmode_swap(scrn, flip->old, &next_fb); drmmode_event_abort(scrn, event_id, false); } drmModeRmFB(pNv->dev->fd, next_fb); } return FALSE; }
static void ricochet(int tiled, int sprite_w, int sprite_h, int out_w, int out_h, int dump_info) { int ret; int gfx_fd; int keep_moving; const int num_surfaces = 3; uint32_t sprite_handles[num_surfaces]; uint32_t sprite_fb_id[num_surfaces]; int *sprite_x = NULL; int *sprite_y = NULL; uint32_t sprite_stride; uint32_t sprite_size; uint32_t handles[4], pitches[4], offsets[4]; /* we only use [0] */ uint32_t prim_width, prim_height, prim_handle, prim_stride, prim_size, prim_fb_id; struct drm_intel_sprite_colorkey set; struct connector curr_connector; drmModeRes *gfx_resources; struct termios orig_term, curr_term; int c_index; int sprite_index; unsigned int *sprite_plane_id = NULL; uint32_t plane_flags = 0; int *delta_x = NULL, *delta_y = NULL; struct timeval stTimeVal; long long currTime, prevFlipTime, prevMoveTime, deltaFlipTime, deltaMoveTime, SleepTime; char key; int sprite_plane_count = 0; int i; // Open up I915 graphics device gfx_fd = drmOpen("i915", NULL); if (gfx_fd < 0) { printf("Failed to load i915 driver: %s\n", strerror(errno)); return; } // Obtain pointer to struct containing graphics resources gfx_resources = drmModeGetResources(gfx_fd); if (!gfx_resources) { printf("drmModeGetResources failed: %s\n", strerror(errno)); return; } if (dump_info != 0) { dump_connectors(gfx_fd, gfx_resources); dump_crtcs(gfx_fd, gfx_resources); dump_planes(gfx_fd, gfx_resources); } // Save previous terminal settings if (tcgetattr( 0, &orig_term) != 0) { printf("tcgetattr failure: %s\n", strerror(errno)); return; } // Set up input to return characters immediately curr_term = orig_term; curr_term.c_lflag &= ~(ICANON | ECHO | ECHONL); curr_term.c_cc[VMIN] = 0; // No minimum number of characters curr_term.c_cc[VTIME] = 0 ; // Return immediately, even if // nothing has been entered. if (tcsetattr( 0, TCSANOW, &curr_term) != 0) { printf("tcgetattr failure: %s\n", strerror(errno)); return; } // Cycle through all connectors and display the flying sprite // where there are displays attached and the hardware will support it. for (c_index = 0; c_index < gfx_resources->count_connectors; c_index++) { curr_connector.id = gfx_resources->connectors[c_index]; // Find the native (preferred) display mode connector_find_preferred_mode(gfx_fd, gfx_resources, &curr_connector); if (curr_connector.mode_valid == 0) { printf("No valid preferred mode detected\n"); goto out; } // Determine if sprite hardware is available on pipe // associated with this connector. sprite_plane_count = connector_find_plane(gfx_fd, &curr_connector, &sprite_plane_id); if (!sprite_plane_count) { printf("Failed to find sprite plane on crtc\n"); goto out; } // Width and height of preferred mode prim_width = curr_connector.mode.hdisplay; prim_height = curr_connector.mode.vdisplay; // Allocate and fill memory for primary surface ret = prepare_primary_surface( gfx_fd, prim_width, prim_height, &prim_handle, &prim_stride, &prim_size, tiled); if (ret != 0) { printf("Failed to add primary fb (%dx%d): %s\n", prim_width, prim_height, strerror(errno)); goto out; } // Add the primary surface framebuffer ret = drmModeAddFB(gfx_fd, prim_width, prim_height, 24, 32, prim_stride, prim_handle, &prim_fb_id); gem_close(gfx_fd, prim_handle); if (ret != 0) { printf("Failed to add primary fb (%dx%d): %s\n", prim_width, prim_height, strerror(errno)); goto out; } // Allocate and fill sprite surfaces ret = prepare_sprite_surfaces(gfx_fd, sprite_w, sprite_h, num_surfaces, &sprite_handles[0], &sprite_stride, &sprite_size, tiled); if (ret != 0) { printf("Preparation of sprite surfaces failed %dx%d\n", sprite_w, sprite_h); goto out; } // Add the sprite framebuffers for (sprite_index = 0; sprite_index < num_surfaces; sprite_index++) { handles[0] = sprite_handles[sprite_index]; handles[1] = handles[0]; handles[2] = handles[0]; handles[3] = handles[0]; pitches[0] = sprite_stride; pitches[1] = sprite_stride; pitches[2] = sprite_stride; pitches[3] = sprite_stride; memset(offsets, 0, sizeof(offsets)); ret = drmModeAddFB2(gfx_fd, sprite_w, sprite_h, DRM_FORMAT_XRGB8888, handles, pitches, offsets, &sprite_fb_id[sprite_index], plane_flags); gem_close(gfx_fd, sprite_handles[sprite_index]); if (ret) { printf("Failed to add sprite fb (%dx%d): %s\n", sprite_w, sprite_h, strerror(errno)); sprite_index--; while (sprite_index >= 0) { drmModeRmFB(gfx_fd, sprite_fb_id[sprite_index]); sprite_index--; } goto out; } } if (dump_info != 0) { printf("Displayed Mode Connector struct:\n" " .id = %d\n" " .mode_valid = %d\n" " .crtc = %d\n" " .pipe = %d\n" " drmModeModeInfo ...\n" " .name = %s\n" " .type = %d\n" " .flags = %08x\n" " drmModeEncoder ...\n" " .encoder_id = %d\n" " .encoder_type = %d (%s)\n" " .crtc_id = %d\n" " .possible_crtcs = %d\n" " .possible_clones = %d\n" " drmModeConnector ...\n" " .connector_id = %d\n" " .encoder_id = %d\n" " .connector_type = %d (%s)\n" " .connector_type_id = %d\n\n", curr_connector.id, curr_connector.mode_valid, curr_connector.crtc, curr_connector.pipe, curr_connector.mode.name, curr_connector.mode.type, curr_connector.mode.flags, curr_connector.encoder->encoder_id, curr_connector.encoder->encoder_type, kmstest_encoder_type_str(curr_connector.encoder->encoder_type), curr_connector.encoder->crtc_id, curr_connector.encoder->possible_crtcs, curr_connector.encoder->possible_clones, curr_connector.connector->connector_id, curr_connector.connector->encoder_id, curr_connector.connector->connector_type, kmstest_connector_type_str(curr_connector.connector->connector_type), curr_connector.connector->connector_type_id); printf("Sprite surface dimensions = %dx%d\n" "Sprite output dimensions = %dx%d\n" "Press any key to continue >\n", sprite_w, sprite_h, out_w, out_h); // Wait for a key-press while( read(0, &key, 1) == 0); // Purge unread characters tcflush(0, TCIFLUSH); } // Set up the primary display mode ret = drmModeSetCrtc(gfx_fd, curr_connector.crtc, prim_fb_id, 0, 0, &curr_connector.id, 1, &curr_connector.mode); if (ret != 0) { printf("Failed to set mode (%dx%d@%dHz): %s\n", prim_width, prim_height, curr_connector.mode.vrefresh, strerror(errno)); continue; } // Set the sprite colorkey state for(i = 0; i < sprite_plane_count; i++) { set.plane_id = sprite_plane_id[i]; set.min_value = 0; set.max_value = 0; set.flags = I915_SET_COLORKEY_NONE; ret = drmCommandWrite(gfx_fd, DRM_I915_SET_SPRITE_COLORKEY, &set, sizeof(set)); assert(ret == 0); } // Set up sprite output dimensions, initial position, etc. if (out_w > prim_width / 2) out_w = prim_width / 2; if (out_h > prim_height / 2) out_h = prim_height / 2; delta_x = (int *) malloc(sprite_plane_count * sizeof(int)); delta_y = (int *) malloc(sprite_plane_count * sizeof(int)); sprite_x = (int *) malloc(sprite_plane_count * sizeof(int)); sprite_y = (int *) malloc(sprite_plane_count * sizeof(int)); /* Initializing the coordinates (x,y) of the available sprites on the * connector, equally spaced along the diagonal of the rectangle * {(0,0),(prim_width/2, prim_height/2)}. */ for(i = 0; i < sprite_plane_count; i++) { delta_x[i] = 3; delta_y[i] = 4; sprite_x[i] = i * (prim_width / (2 * sprite_plane_count)); sprite_y[i] = i * (prim_height / (2 * sprite_plane_count)); } currTime = 0; prevFlipTime = 0; // Will force immediate sprite flip prevMoveTime = 0; // Will force immediate sprite move deltaFlipTime = 500000; // Flip sprite surface every 1/2 second deltaMoveTime = 100000; // Move sprite every 100 ms sprite_index = num_surfaces - 1; keep_moving = 1; // Bounce sprite off the walls while (keep_moving) { // Obtain system time in usec. if (gettimeofday( &stTimeVal, NULL ) != 0) printf("gettimeofday error: %s\n", strerror(errno)); else currTime = ((long long)stTimeVal.tv_sec * 1000000) + stTimeVal.tv_usec; // Check if it's time to flip the sprite surface if (currTime - prevFlipTime > deltaFlipTime) { sprite_index = (sprite_index + 1) % num_surfaces; prevFlipTime = currTime; } // Move the sprite on the screen and flip // the surface if the index has changed // NB: sprite_w and sprite_h must be 16.16 fixed point, herego << 16 for(i = 0; i < sprite_plane_count; i++) { if (drmModeSetPlane(gfx_fd, sprite_plane_id[i], curr_connector.crtc, sprite_fb_id[sprite_index], plane_flags, sprite_x[i], sprite_y[i], out_w, out_h, 0, 0, sprite_w << 16, sprite_h << 16)) printf("Failed to enable sprite plane: %s\n", strerror(errno)); } // Check if it's time to move the sprite surface if (currTime - prevMoveTime > deltaMoveTime) { // Compute the next position for sprite for(i = 0; i < sprite_plane_count; i++) { sprite_x[i] += delta_x[i]; sprite_y[i] += delta_y[i]; if (sprite_x[i] < 0) { sprite_x[i] = 0; delta_x[i] = -delta_x[i]; } else if (sprite_x[i] > prim_width - out_w) { sprite_x[i] = prim_width - out_w; delta_x[i] = -delta_x[i]; } if (sprite_y[i] < 0) { sprite_y[i] = 0; delta_y[i] = -delta_y[i]; } else if (sprite_y[i] > prim_height - out_h) { sprite_y[i] = prim_height - out_h; delta_y[i] = -delta_y[i]; } } prevMoveTime = currTime; } // Fetch a key from input (non-blocking) if (read(0, &key, 1) == 1) { switch (key) { case 'q': // Kill the program case 'Q': goto out; break; case 's': // Slow down sprite movement; deltaMoveTime = (deltaMoveTime * 100) / 90; if (deltaMoveTime > 800000) { deltaMoveTime = 800000; } break; case 'S': // Speed up sprite movement; deltaMoveTime = (deltaMoveTime * 100) / 110; if (deltaMoveTime < 2000) { deltaMoveTime = 2000; } break; case 'f': // Slow down sprite flipping; deltaFlipTime = (deltaFlipTime * 100) / 90; if (deltaFlipTime > 1000000) deltaFlipTime = 1000000; break; case 'F': // Speed up sprite flipping; deltaFlipTime = (deltaFlipTime * 100) / 110; if (deltaFlipTime < 20000) deltaFlipTime = 20000; break; case 'n': // Next connector case 'N': keep_moving = 0; break; default: break; } // Purge unread characters tcflush(0, TCIFLUSH); } // Wait for min of flip or move deltas SleepTime = (deltaFlipTime < deltaMoveTime) ? deltaFlipTime : deltaMoveTime; usleep(SleepTime); } free(sprite_plane_id); free(sprite_x); free(sprite_y); free(delta_x); free(delta_y); sprite_plane_id = NULL; sprite_plane_count = 0; sprite_x = sprite_y = delta_x = delta_y = NULL; } out: // Purge unread characters tcflush(0, TCIFLUSH); // Restore previous terminal settings if (tcsetattr( 0, TCSANOW, &orig_term) != 0) { printf("tcgetattr failure: %s\n", strerror(errno)); return; } drmModeFreeResources(gfx_resources); }
static gboolean _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, GError **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; int i; _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; context->glGenRenderbuffers (2, kms_onscreen->color_rb); for (i = 0; i < 2; i++) { uint32_t handle, stride; kms_onscreen->bo[i] = gbm_bo_create (kms_renderer->gbm, kms_display->mode.hdisplay, kms_display->mode.vdisplay, GBM_BO_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); if (!kms_onscreen->bo[i]) { g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, "Failed to allocate buffer"); return FALSE; } kms_onscreen->image[i] = _cogl_egl_create_image (context, EGL_NATIVE_PIXMAP_KHR, kms_onscreen->bo[i], NULL); if (kms_onscreen->image[i] == EGL_NO_IMAGE_KHR) { g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, "Failed to create EGL image"); return FALSE; } context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, kms_onscreen->color_rb[i]); context->glEGLImageTargetRenderbufferStorage (GL_RENDERBUFFER, kms_onscreen->image[i]); context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, 0); handle = gbm_bo_get_handle (kms_onscreen->bo[i]).u32; stride = gbm_bo_get_pitch (kms_onscreen->bo[i]); if (drmModeAddFB (kms_renderer->fd, kms_display->mode.hdisplay, kms_display->mode.vdisplay, 24, 32, stride, handle, &kms_onscreen->fb_id[i]) != 0) { g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, "Failed to create framebuffer from buffer"); return FALSE; } } context->glGenFramebuffers (1, &kms_onscreen->fb); context->glBindFramebuffer (GL_FRAMEBUFFER_EXT, kms_onscreen->fb); context->glGenRenderbuffers (1, &kms_onscreen->depth_rb); context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, kms_onscreen->depth_rb); context->glRenderbufferStorage (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, kms_display->mode.hdisplay, kms_display->mode.vdisplay); context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, 0); context->glFramebufferRenderbuffer (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, kms_onscreen->depth_rb); kms_onscreen->current_frame = 0; _cogl_winsys_onscreen_swap_buffers (onscreen); _cogl_framebuffer_winsys_update_size (framebuffer, kms_display->width, kms_display->height); return TRUE; }
static int modeset_create_fb(int fd, struct modeset_buf *buf) { struct drm_mode_create_dumb creq; struct drm_mode_destroy_dumb dreq; struct drm_mode_map_dumb mreq; int ret; /* create dumb buffer */ memset(&creq, 0, sizeof(creq)); creq.width = buf->width; creq.height = buf->height; creq.bpp = 32; ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq); if (ret < 0) { fprintf(stderr, "cannot create dumb buffer (%d): %m\n", errno); return -errno; } buf->stride = creq.pitch; buf->size = creq.size; buf->handle = creq.handle; /* create framebuffer object for the dumb-buffer */ ret = drmModeAddFB(fd, buf->width, buf->height, 24, 32, buf->stride, buf->handle, &buf->fb); if (ret) { fprintf(stderr, "cannot create framebuffer (%d): %m\n", errno); ret = -errno; goto err_destroy; } /* prepare buffer for memory mapping */ memset(&mreq, 0, sizeof(mreq)); mreq.handle = buf->handle; ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq); if (ret) { fprintf(stderr, "cannot map dumb buffer (%d): %m\n", errno); ret = -errno; goto err_fb; } /* perform actual memory mapping */ buf->map = mmap(0, buf->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset); if (buf->map == MAP_FAILED) { fprintf(stderr, "cannot mmap dumb buffer (%d): %m\n", errno); ret = -errno; goto err_fb; } /* clear the framebuffer to 0 */ memset(buf->map, 0, buf->size); return 0; err_fb: drmModeRmFB(fd, buf->fb); err_destroy: memset(&dreq, 0, sizeof(dreq)); dreq.handle = buf->handle; drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq); return ret; }
static Bool ms_do_pageflip(ScreenPtr screen, PixmapPtr new_front, struct ms_present_vblank_event *event, int ref_crtc_vblank_pipe, Bool async) { #ifndef GLAMOR_HAS_GBM return FALSE; #else ScrnInfoPtr scrn = xf86ScreenToScrn(screen); modesettingPtr ms = modesettingPTR(scrn); xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); drmmode_bo new_front_bo; uint32_t flags; int i; struct ms_flipdata *flipdata; glamor_block_handler(screen); new_front_bo.gbm = glamor_gbm_bo_from_pixmap(screen, new_front); new_front_bo.dumb = NULL; if (!new_front_bo.gbm) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to get GBM bo for flip to new front.\n"); return FALSE; } flipdata = calloc(1, sizeof(struct ms_flipdata)); if (!flipdata) { drmmode_bo_destroy(&ms->drmmode, &new_front_bo); xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to allocate flipdata.\n"); return FALSE; } flipdata->event = event; flipdata->screen = screen; /* * Take a local reference on flipdata. * if the first flip fails, the sequence abort * code will free the crtc flip data, and drop * it's reference which would cause this to be * freed when we still required it. */ flipdata->flip_count++; /* Create a new handle for the back buffer */ flipdata->old_fb_id = ms->drmmode.fb_id; if (drmModeAddFB(ms->fd, scrn->virtualX, scrn->virtualY, scrn->depth, scrn->bitsPerPixel, drmmode_bo_get_pitch(&new_front_bo), drmmode_bo_get_handle(&new_front_bo), &ms->drmmode.fb_id)) { goto error_out; } drmmode_bo_destroy(&ms->drmmode, &new_front_bo); flags = DRM_MODE_PAGE_FLIP_EVENT; if (async) flags |= DRM_MODE_PAGE_FLIP_ASYNC; /* Queue flips on all enabled CRTCs. * * Note that if/when we get per-CRTC buffers, we'll have to update this. * Right now it assumes a single shared fb across all CRTCs, with the * kernel fixing up the offset of each CRTC as necessary. * * Also, flips queued on disabled or incorrectly configured displays * may never complete; this is a configuration error. */ for (i = 0; i < config->num_crtc; i++) { xf86CrtcPtr crtc = config->crtc[i]; if (!ms_crtc_on(crtc)) continue; if (!queue_flip_on_crtc(screen, crtc, flipdata, ref_crtc_vblank_pipe, flags)) { goto error_undo; } } /* * Do we have more than our local reference, * if so and no errors, then drop our local * reference and return now. */ if (flipdata->flip_count > 1) { flipdata->flip_count--; return TRUE; } error_undo: /* * Have we just got the local reference? * free the framebuffer if so since nobody successfully * submitted anything */ if (flipdata->flip_count == 1) { drmModeRmFB(ms->fd, ms->drmmode.fb_id); ms->drmmode.fb_id = flipdata->old_fb_id; } error_out: xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", strerror(errno)); /* if only the local reference - free the structure, * else drop the local reference and return */ if (flipdata->flip_count == 1) free(flipdata); else flipdata->flip_count--; return FALSE; #endif /* GLAMOR_HAS_GBM */ }
int main(int argc, char **argv) { int drmfd; int vtfd; unsigned int i, j; drmModeRes *res = NULL; drmModeEncoder *enc = NULL; drmModeConnector *conn = NULL; uint32_t fb_id, conn_id, crtc_id; long int vt_args; struct drm_mode_create_dumb fbo_create_args = {0}; struct drm_mode_map_dumb fbo_map_args = {0}; struct drm_mode_destroy_dumb fbo_close_args = {0}; uint32_t gem_handle; uint8_t *fb_virt = NULL; /* start address of dumb fb */ uint32_t fb_pitch; uint32_t fb_size; drmModeModeInfo curr_mode; /* store current mode infomation */ vtfd = open("/dev/tty1", O_RDWR | O_CLOEXEC); /* trigger a vt switch to /dev/tty1 and wait for available */ ioctl(vtfd, VT_ACTIVATE, 1); ioctl(vtfd, VT_WAITACTIVE, 1); ioctl(vtfd, KDGETMODE, &vt_args); printf("switch to %s mode on tty1\n", vt_args == KD_TEXT ? "TEXT" : "GFX"); /* from now on, we can do pixel dance on dumb fb */ drmfd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); res = drmModeGetResources(drmfd); for (i = 0; i < res->count_connectors; i++) { conn = drmModeGetConnector(drmfd, res->connectors[i]); conn_id = conn->connector_id; if (conn->connection != DRM_MODE_CONNECTED) { printf("conn:[%d] is offline\n", conn->connector_id); drmModeFreeConnector(conn); continue; } /* we choose max valid mode */ memcpy(&curr_mode, &conn->modes[0], sizeof(curr_mode)); printf("conn:[%d] is online %dx%d@%dHZ\n", conn->connector_id, curr_mode.hdisplay, curr_mode.vdisplay, curr_mode.vrefresh); enc = drmModeGetEncoder(drmfd, conn->encoder_id); crtc_id = enc->crtc_id; drmModeFreeEncoder(enc); /* create dumb fb and retrieve aperture */ fbo_create_args.width = curr_mode.hdisplay; fbo_create_args.height = curr_mode.vdisplay; fbo_create_args.bpp = 32; drmIoctl(drmfd, DRM_IOCTL_MODE_CREATE_DUMB, &fbo_create_args); gem_handle = fbo_create_args.handle; fb_size = fbo_create_args.size; fb_pitch = fbo_create_args.pitch; drmModeAddFB(drmfd, curr_mode.hdisplay, curr_mode.vdisplay, 24, 32, fb_pitch, gem_handle, &fb_id); fbo_map_args.handle = gem_handle; drmIoctl(drmfd, DRM_IOCTL_MODE_MAP_DUMB, &fbo_map_args); fb_virt = mmap(0, fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, drmfd, fbo_map_args.offset); drmModeFreeConnector(conn); } drmModeFreeResources(res); drmModeSetCrtc(drmfd, crtc_id, fb_id, 0, 0, &conn_id, 1, &curr_mode); for (i = 0; i < curr_mode.vdisplay; i++) { for (j = 0; j < curr_mode.hdisplay; j++) { //*((uint32_t *)(fb_virt + fb_pitch * i + j * 4)) = i * j; *((uint32_t *)(fb_virt + fb_pitch * i + j * 4)) = 0xFFFFFF; } } /* say hello */ draw_8x8_char(10, 10, fb_virt, fb_pitch, 'h'); draw_8x8_char(18, 10, fb_virt, fb_pitch, 'e'); draw_8x8_char(26, 10, fb_virt, fb_pitch, 'l'); draw_8x8_char(34, 10, fb_virt, fb_pitch, 'l'); draw_8x8_char(42, 10, fb_virt, fb_pitch, 'o'); draw_8x8_char(50, 10, fb_virt, fb_pitch, ' '); draw_8x8_char(58, 10, fb_virt, fb_pitch, 'r'); draw_8x8_char(66, 10, fb_virt, fb_pitch, 'e'); draw_8x8_char(74, 10, fb_virt, fb_pitch, 'd'); draw_8x8_char(82, 10, fb_virt, fb_pitch, 'h'); draw_8x8_char(90, 10, fb_virt, fb_pitch, 'a'); draw_8x8_char(98, 10, fb_virt, fb_pitch, 't'); draw_8x8_char(106, 10, fb_virt, fb_pitch, '!'); draw_8x16_char(110, 100, fb_virt, fb_pitch, 'h'); draw_8x16_char(118, 100, fb_virt, fb_pitch, 'e'); draw_8x16_char(126, 100, fb_virt, fb_pitch, 'l'); draw_8x16_char(134, 100, fb_virt, fb_pitch, 'l'); draw_8x16_char(142, 100, fb_virt, fb_pitch, 'o'); draw_8x16_char(150, 100, fb_virt, fb_pitch, ' '); draw_8x16_char(158, 100, fb_virt, fb_pitch, 'r'); draw_8x16_char(166, 100, fb_virt, fb_pitch, 'e'); draw_8x16_char(174, 100, fb_virt, fb_pitch, 'd'); draw_8x16_char(182, 100, fb_virt, fb_pitch, 'h'); draw_8x16_char(190, 100, fb_virt, fb_pitch, 'a'); draw_8x16_char(198, 100, fb_virt, fb_pitch, 't'); draw_8x16_char(206, 100, fb_virt, fb_pitch, '!'); usleep(5000000); /* unwind anything we done */ munmap(fb_virt, fb_size); drmModeRmFB(drmfd, fb_id); fbo_close_args.handle = gem_handle; drmIoctl(drmfd, DRM_IOCTL_MODE_DESTROY_DUMB, &fbo_close_args); close(drmfd); /* switch back to /dev/tty7 for convinience */ ioctl(vtfd, VT_ACTIVATE, 7); ioctl(vtfd, VT_WAITACTIVE, 7); close(vtfd); return 0; }
bool Drm::setDrmMode(int index, drmModeModeInfoPtr mode) { DrmOutput *output = &mOutputs[index]; int oldFbId = 0; int oldFbHandle = 0; // reuse current frame buffer if there is no resolution change int fbId = -1; drmModeModeInfo currentMode; memcpy(¤tMode, &output->mode, sizeof(drmModeModeInfo)); if (isSameDrmMode(mode, ¤tMode)) return true; if (currentMode.hdisplay != mode->hdisplay || currentMode.vdisplay != mode->vdisplay) { oldFbId = output->fbId; oldFbHandle = output->fbHandle; // allocate frame buffer int stride = 0; #ifdef INTEL_SUPPORT_HDMI_PRIMARY output->fbHandle = Hwcomposer::getInstance().getBufferManager()->allocFrameBuffer( DEFAULT_DRM_FB_WIDTH, DEFAULT_DRM_FB_HEIGHT, &stride); #else output->fbHandle = Hwcomposer::getInstance().getBufferManager()->allocFrameBuffer( mode->hdisplay, mode->vdisplay, &stride); #endif if (output->fbHandle == 0) { ELOGTRACE("failed to allocate frame buffer"); return false; } int ret = 0; ret = drmModeAddFB( mDrmFd, #ifdef INTEL_SUPPORT_HDMI_PRIMARY DEFAULT_DRM_FB_WIDTH, DEFAULT_DRM_FB_HEIGHT, #else mode->hdisplay, mode->vdisplay, #endif DrmConfig::getFrameBufferDepth(), DrmConfig::getFrameBufferBpp(), stride, output->fbHandle, &output->fbId); if (ret != 0) { ELOGTRACE("drmModeAddFB failed, error: %d", ret); return false; } fbId = output->fbId; } ILOGTRACE("mode set: %dx%d@%dHz", mode->hdisplay, mode->vdisplay, mode->vrefresh); int ret = drmModeSetCrtc(mDrmFd, output->crtc->crtc_id, fbId, 0, 0, &output->connector->connector_id, 1, mode); if (ret == 0) { //save mode memcpy(&output->mode, mode, sizeof(drmModeModeInfo)); } else { ELOGTRACE("drmModeSetCrtc failed. error: %d", ret); } if (oldFbId) { drmModeRmFB(mDrmFd, oldFbId); } if (oldFbHandle) { Hwcomposer::getInstance().getBufferManager()->freeFrameBuffer(oldFbHandle); } return ret == 0; }