Framebuffer::Framebuffer(Card& card, uint32_t id) : DrmObject(card, id, DRM_MODE_OBJECT_FB) { auto fb = drmModeGetFB(card.fd(), id); m_width = fb->width; m_height = fb->height; drmModeFreeFB(fb); card.m_framebuffers.push_back(this); }
static void printFramebuffers(int fd, uint32_t* ids, uint32_t count) { int i; for (i = 0; i < count; i++) { drmModeFB *fb; fb = drmModeGetFB(fd, ids[i]); fprintf(stdout, " Framebuffer %u:\n", fb->fb_id); fprintf(stdout, " Handle: %u\n", fb->handle); fprintf(stdout, " Dimensions: %u x %u\n", fb->width, fb->height); fprintf(stdout, " Depth: %u\n", fb->depth); fprintf(stdout, " BPP: %u\n", fb->bpp); fprintf(stdout, " Pitch: %u\n", fb->pitch); fprintf(stdout, "\n"); drmModeFreeFB(fb); } }
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; }
bool IntelHWComposerDrm::detectDrmModeInfo() { ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: detecting drm mode info...\n", __func__); if (mDrmFd < 0) { ALOGE("%s: invalid drm FD\n", __func__); return false; } /*try to get drm resources*/ drmModeResPtr resources = drmModeGetResources(mDrmFd); if (!resources || !resources->connectors) { ALOGE("%s: fail to get drm resources. %s\n", __func__, strerror(errno)); return false; } /*get mipi0 info*/ drmModeConnectorPtr connector = NULL; drmModeEncoderPtr encoder = NULL; drmModeCrtcPtr crtc = NULL; drmModeConnectorPtr connectors[OUTPUT_MAX]; drmModeModeInfoPtr mode = NULL; drmModeFBPtr fbInfo = NULL; for (int i = 0; i < resources->count_connectors; i++) { connector = drmModeGetConnector(mDrmFd, resources->connectors[i]); if (!connector) { ALOGW("%s: fail to get drm connector\n", __func__); continue; } int outputIndex = -1; if (connector->connector_type == DRM_MODE_CONNECTOR_MIPI || connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: got MIPI/LVDS connector\n", __func__); if (connector->connector_type_id == 1) outputIndex = OUTPUT_MIPI0; else if (connector->connector_type_id == 2) outputIndex = OUTPUT_MIPI1; else { ALOGW("%s: unknown connector type\n", __func__); outputIndex = OUTPUT_MIPI0; } } else if (connector->connector_type == DRM_MODE_CONNECTOR_DVID) { ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: got HDMI connector\n", __func__); outputIndex = OUTPUT_HDMI; } /*update connection status*/ setOutputConnection(outputIndex, connector->connection); /*get related encoder*/ encoder = drmModeGetEncoder(mDrmFd, connector->encoder_id); if (!encoder) { ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: fail to get drm encoder\n", __func__); drmModeFreeConnector(connector); setOutputConnection(outputIndex, DRM_MODE_DISCONNECTED); continue; } /*get related crtc*/ crtc = drmModeGetCrtc(mDrmFd, encoder->crtc_id); if (!crtc) { ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: fail to get drm crtc\n", __func__); drmModeFreeEncoder(encoder); drmModeFreeConnector(connector); setOutputConnection(outputIndex, DRM_MODE_DISCONNECTED); continue; } /*set crtc mode*/ setOutputMode(outputIndex, &crtc->mode, crtc->mode_valid); // get fb info fbInfo = drmModeGetFB(mDrmFd, crtc->buffer_id); if (!fbInfo) { ALOGD("%s: fail to get fb info\n", __func__); drmModeFreeCrtc(crtc); drmModeFreeEncoder(encoder); drmModeFreeConnector(connector); setOutputConnection(outputIndex, DRM_MODE_DISCONNECTED); continue; } setOutputFBInfo(outputIndex, fbInfo); /*free all crtc/connector/encoder*/ drmModeFreeFB(fbInfo); drmModeFreeCrtc(crtc); drmModeFreeEncoder(encoder); drmModeFreeConnector(connector); } drmModeFreeResources(resources); drmModeConnection mipi0 = getOutputConnection(OUTPUT_MIPI0); drmModeConnection mipi1 = getOutputConnection(OUTPUT_MIPI1); drmModeConnection hdmi = getOutputConnection(OUTPUT_HDMI); detectMDSModeChange(); ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: mipi/lvds %s, mipi1 %s, hdmi %s, displayMode %d\n", __func__, ((mipi0 == DRM_MODE_CONNECTED) ? "connected" : "disconnected"), ((mipi1 == DRM_MODE_CONNECTED) ? "connected" : "disconnected"), ((hdmi == DRM_MODE_CONNECTED) ? "connected" : "disconnected"), getDisplayMode()); return true; }
static int kmsgrab_read_packet(AVFormatContext *avctx, AVPacket *pkt) { KMSGrabContext *ctx = avctx->priv_data; drmModePlane *plane; drmModeFB *fb; AVDRMFrameDescriptor *desc; AVFrame *frame; int64_t now; int err, fd; now = av_gettime(); if (ctx->frame_last) { int64_t delay; while (1) { delay = ctx->frame_last + ctx->frame_delay - now; if (delay <= 0) break; av_usleep(delay); now = av_gettime(); } } ctx->frame_last = now; plane = drmModeGetPlane(ctx->hwctx->fd, ctx->plane_id); if (!plane) { av_log(avctx, AV_LOG_ERROR, "Failed to get plane " "%"PRIu32".\n", ctx->plane_id); return AVERROR(EIO); } if (!plane->fb_id) { av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" no longer has " "an associated framebuffer.\n", ctx->plane_id); return AVERROR(EIO); } fb = drmModeGetFB(ctx->hwctx->fd, plane->fb_id); if (!fb) { av_log(avctx, AV_LOG_ERROR, "Failed to get framebuffer " "%"PRIu32".\n", plane->fb_id); return AVERROR(EIO); } if (fb->width != ctx->width || fb->height != ctx->height) { av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer " "dimensions changed: now %"PRIu32"x%"PRIu32".\n", ctx->plane_id, fb->width, fb->height); return AVERROR(EIO); } if (!fb->handle) { av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer.\n"); return AVERROR(EIO); } err = drmPrimeHandleToFD(ctx->hwctx->fd, fb->handle, O_RDONLY, &fd); if (err < 0) { err = errno; av_log(avctx, AV_LOG_ERROR, "Failed to get PRIME fd from " "framebuffer handle: %s.\n", strerror(errno)); return AVERROR(err); } desc = av_mallocz(sizeof(*desc)); if (!desc) return AVERROR(ENOMEM); *desc = (AVDRMFrameDescriptor) { .nb_objects = 1, .objects[0] = { .fd = fd, .size = fb->height * fb->pitch, .format_modifier = ctx->drm_format_modifier, }, .nb_layers = 1, .layers[0] = { .format = ctx->drm_format, .nb_planes = 1, .planes[0] = { .object_index = 0, .offset = 0, .pitch = fb->pitch, }, }, };
static gboolean configure_mode_setting (GstKMSSink * self, GstVideoInfo * vinfo) { gboolean ret; drmModeConnector *conn; int err; drmModeFB *fb; gint i; drmModeModeInfo *mode; guint32 fb_id; GstKMSMemory *kmsmem; ret = FALSE; conn = NULL; fb = NULL; mode = NULL; kmsmem = NULL; if (self->conn_id < 0) goto bail; GST_INFO_OBJECT (self, "configuring mode setting"); kmsmem = (GstKMSMemory *) gst_kms_allocator_bo_alloc (self->allocator, vinfo); if (!kmsmem) goto bo_failed; fb_id = kmsmem->fb_id; conn = drmModeGetConnector (self->fd, self->conn_id); if (!conn) goto connector_failed; fb = drmModeGetFB (self->fd, fb_id); if (!fb) goto framebuffer_failed; for (i = 0; i < conn->count_modes; i++) { if (conn->modes[i].vdisplay == fb->height && conn->modes[i].hdisplay == fb->width) { mode = &conn->modes[i]; break; } } if (!mode) goto mode_failed; err = drmModeSetCrtc (self->fd, self->crtc_id, fb_id, 0, 0, (uint32_t *) & self->conn_id, 1, mode); if (err) goto modesetting_failed; self->tmp_kmsmem = (GstMemory *) kmsmem; ret = TRUE; bail: if (fb) drmModeFreeFB (fb); if (conn) drmModeFreeConnector (conn); return ret; /* ERRORS */ bo_failed: { GST_ERROR_OBJECT (self, "failed to allocate buffer object for mode setting"); goto bail; } connector_failed: { GST_ERROR_OBJECT (self, "Could not find a valid monitor connector"); goto bail; } framebuffer_failed: { GST_ERROR_OBJECT (self, "drmModeGetFB failed: %s (%d)", strerror (errno), errno); goto bail; } mode_failed: { GST_ERROR_OBJECT (self, "cannot find appropriate mode"); goto bail; } modesetting_failed: { GST_ERROR_OBJECT (self, "Failed to set mode: %s", strerror (errno)); goto bail; } }
int main(int argc, char **argv) { int fd = drmOpen("radeon", NULL); assert(fd >= 0); // expose all planes including primary and cursor planes assert(!drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)); drmModeResPtr res = drmModeGetResources(fd); assert(res); int i, j; drmModeConnectorPtr connector = NULL; for (i = 0; i < res->count_connectors; i++) { connector = drmModeGetConnector(fd, res->connectors[i]); assert(connector); if (connector->connection == DRM_MODE_CONNECTED) break; drmFree(connector); } drmModeEncoderPtr encoder = drmModeGetEncoder(fd, connector->encoder_id); assert(encoder); drmModeCrtcPtr crtc = drmModeGetCrtc(fd, encoder->crtc_id); assert(crtc); drmModeFBPtr fb = drmModeGetFB(fd, crtc->buffer_id); assert(fb); drmModePlaneResPtr plane_res = drmModeGetPlaneResources(fd); assert(plane_res); drmModePlanePtr plane = NULL; for (i = 0; i < plane_res->count_planes; i++) { plane = drmModeGetPlane(fd, plane_res->planes[i]); assert(plane); if (plane->fb_id == fb->fb_id) break; drmFree(plane); } uint64_t has_dumb; assert(!drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb)); assert(has_dumb); struct drm_mode_create_dumb creq; memset(&creq, 0, sizeof(creq)); creq.width = fb->width; creq.height = fb->height; creq.bpp = fb->bpp; assert(!drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq)); printf("width=%d height=%d bpp=%d pitch=%d size=%d\n", creq.width, creq.height, creq.bpp, creq.pitch, creq.size); uint32_t my_fb; assert(!drmModeAddFB(fd, creq.width, creq.height, 24, creq.bpp, creq.pitch, creq.handle, &my_fb)); struct drm_mode_map_dumb mreq; memset(&mreq, 0, sizeof(mreq)); mreq.handle = creq.handle; assert(!drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq)); uint32_t *map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset); assert(map != MAP_FAILED); memset(map, 0, creq.size); for (i = 100; i < 500; i++) for (j = 200; j < 460; j++) map[i * (creq.pitch >> 2) + j] = 0x12345678; assert(!drmModeSetCrtc(fd, crtc->crtc_id, my_fb, 0, 0, &connector->connector_id, 1, &crtc->mode)); sleep(10); assert(!drmModeSetCrtc(fd, crtc->crtc_id, fb->fb_id, 0, 0, &connector->connector_id, 1, &crtc->mode)); assert(!drmModeRmFB(fd, my_fb)); struct drm_mode_destroy_dumb dreq; memset(&dreq, 0, sizeof(dreq)); dreq.handle = creq.handle; assert(!drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq)); drmFree(plane); drmFree(plane_res); drmFree(fb); drmFree(crtc); drmFree(encoder); drmFree(connector); drmFree(res); drmClose(fd); return 0; }