void DumbFramebuffer::Create() { int r; const FormatInfo& format_info = format_info_array.at(m_format); m_num_planes = format_info.num_planes; for (int i = 0; i < format_info.num_planes; ++i) { const FormatPlaneInfo& pi = format_info.planes[i]; FramebufferPlane& plane = m_planes[i]; /* create dumb buffer */ struct drm_mode_create_dumb creq = drm_mode_create_dumb(); creq.width = width() / pi.xsub; creq.height = height() / pi.ysub; creq.bpp = pi.bitspp; r = drmIoctl(card().fd(), DRM_IOCTL_MODE_CREATE_DUMB, &creq); if (r) throw std::invalid_argument("foo"); plane.handle = creq.handle; plane.stride = creq.pitch; plane.size = creq.height * creq.pitch; /* printf("buf %d: %dx%d, bitspp %d, stride %d, size %d\n", i, creq.width, creq.height, pi->bitspp, plane->stride, plane->size); */ /* prepare buffer for memory mapping */ struct drm_mode_map_dumb mreq = drm_mode_map_dumb(); mreq.handle = plane.handle; r = drmIoctl(card().fd(), DRM_IOCTL_MODE_MAP_DUMB, &mreq); if (r) throw std::invalid_argument("foo"); /* perform actual memory mapping */ m_planes[i].map = (uint8_t *)mmap(0, plane.size, PROT_READ | PROT_WRITE, MAP_SHARED, card().fd(), mreq.offset); if (plane.map == MAP_FAILED) throw std::invalid_argument("foo"); /* clear the framebuffer to 0 */ memset(plane.map, 0, plane.size); } /* create framebuffer object for the dumb-buffer */ uint32_t bo_handles[4] = { m_planes[0].handle, m_planes[1].handle }; uint32_t pitches[4] = { m_planes[0].stride, m_planes[1].stride }; uint32_t offsets[4] = { 0 }; uint32_t id; r = drmModeAddFB2(card().fd(), width(), height(), (uint32_t)format(), bo_handles, pitches, offsets, &id, 0); if (r) throw std::invalid_argument("foo"); set_id(id); }
ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, uint32_t handles[], uint32_t pitches[], uint32_t offsets[]) : Framebuffer(card, width, height) { uint32_t id; int r = drmModeAddFB2(card.fd(), width, height, (uint32_t)format, handles, pitches, offsets, &id, 0); if (r) throw std::invalid_argument(string("Failed to create ExtFramebuffer: ") + strerror(r)); set_id(id); }
int NvImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) { memset(bo, 0, sizeof(hwc_drm_bo_t)); NvBuffer_t *buf = GrallocGetNvBuffer(handle); if (buf) { atomic_fetch_add(&buf->ref, 1); *bo = buf->bo; return 0; } buf = new NvBuffer_t(); if (!buf) { ALOGE("Failed to allocate new NvBuffer_t"); return -ENOMEM; } buf->bo.priv = buf; buf->importer = this; // We initialize the reference count to 2 since NvGralloc is still using this // buffer (will be cleared in the NvGrallocRelease), and the other // reference is for HWC (this ImportBuffer call). atomic_init(&buf->ref, 2); int ret = gralloc_->perform(gralloc_, GRALLOC_MODULE_PERFORM_DRM_IMPORT, drm_->fd(), handle, &buf->bo); if (ret) { ALOGE("GRALLOC_MODULE_PERFORM_DRM_IMPORT failed %d", ret); delete buf; return ret; } ret = drmModeAddFB2(drm_->fd(), buf->bo.width, buf->bo.height, buf->bo.format, buf->bo.gem_handles, buf->bo.pitches, buf->bo.offsets, &buf->bo.fb_id, 0); if (ret) { ALOGE("Failed to add fb %d", ret); ReleaseBufferImpl(&buf->bo); delete buf; return ret; } ret = GrallocSetNvBuffer(handle, buf); if (ret) { /* This will happen is persist.tegra.gpu_mapping_cache is 0/off, * or if NV gralloc runs out of "priv slots" (currently 3 per buffer, * only one of which should be used by drm_hwcomposer). */ ALOGE("Failed to register free callback for imported buffer %d", ret); ReleaseBufferImpl(&buf->bo); delete buf; return ret; } *bo = buf->bo; return 0; }
/** * igt_create_fb_with_bo_size: * @fd: open i915 drm file descriptor * @width: width of the framebuffer in pixel * @height: height of the framebuffer in pixel * @format: drm fourcc pixel format code * @tiling: tiling layout of the framebuffer (as framebuffer modifier) * @fb: pointer to an #igt_fb structure * @bo_size: size of the backing bo (0 for minimum needed size) * * This function allocates a gem buffer object suitable to back a framebuffer * with the requested properties and then wraps it up in a drm framebuffer * object of the requested size. All metadata is stored in @fb. * * The backing storage of the framebuffer is filled with all zeros, i.e. black * for rgb pixel formats. * * Returns: * The kms id of the created framebuffer. */ unsigned int igt_create_fb_with_bo_size(int fd, int width, int height, uint32_t format, uint64_t tiling, struct igt_fb *fb, unsigned bo_size) { uint32_t fb_id; int bpp; memset(fb, 0, sizeof(*fb)); bpp = igt_drm_format_to_bpp(format); igt_debug("%s(width=%d, height=%d, format=0x%x [bpp=%d], tiling=0x%"PRIx64", size=%d)\n", __func__, width, height, format, bpp, tiling, bo_size); do_or_die(create_bo_for_fb(fd, width, height, bpp, tiling, bo_size, &fb->gem_handle, &fb->size, &fb->stride)); igt_debug("%s(handle=%d, pitch=%d)\n", __func__, fb->gem_handle, fb->stride); if (tiling != LOCAL_DRM_FORMAT_MOD_NONE && tiling != LOCAL_I915_FORMAT_MOD_X_TILED) { do_or_die(__kms_addfb(fd, fb->gem_handle, width, height, fb->stride, format, tiling, LOCAL_DRM_MODE_FB_MODIFIERS, &fb_id)); } else { uint32_t handles[4]; uint32_t pitches[4]; uint32_t offsets[4]; memset(handles, 0, sizeof(handles)); memset(pitches, 0, sizeof(pitches)); memset(offsets, 0, sizeof(offsets)); handles[0] = fb->gem_handle; pitches[0] = fb->stride; do_or_die(drmModeAddFB2(fd, width, height, format, handles, pitches, offsets, &fb_id, 0)); } fb->width = width; fb->height = height; fb->tiling = tiling; fb->drm_format = format; fb->fb_id = fb_id; return fb_id; }
drm_fb * CDRMUtils::DrmFbGetFromBo(struct gbm_bo *bo) { { struct drm_fb *fb = static_cast<drm_fb *>(gbm_bo_get_user_data(bo)); if(fb) { return fb; } } struct drm_fb *fb = new drm_fb; fb->bo = bo; uint32_t width, height, handles[4] = {0}, strides[4] = {0}, offsets[4] = {0}; width = gbm_bo_get_width(bo); height = gbm_bo_get_height(bo); handles[0] = gbm_bo_get_handle(bo).u32; strides[0] = gbm_bo_get_stride(bo); memset(offsets, 0, 16); auto ret = drmModeAddFB2(m_fd, width, height, m_primary_plane->format, handles, strides, offsets, &fb->fb_id, 0); if(ret) { delete (fb); CLog::Log(LOGDEBUG, "CDRMUtils::%s - failed to add framebuffer", __FUNCTION__); return nullptr; } gbm_bo_set_user_data(bo, fb, DrmFbDestroyCallback); return fb; }
drm_overlay_fb * drm_clone_fb(int drm_fd, drm_overlay_fb *fb) { uint32_t fb_id = HANDLE_INVALID; drm_overlay_fb *clone; uint32_t bo_handles[4]; uint32_t pitches[4]; uint32_t offsets[4]; int err; clone = malloc(sizeof(*clone)); if (!clone) return NULL; memcpy(clone, fb, sizeof(*fb)); bo_handles[0] = clone->bo_y_id; bo_handles[1] = clone->bo_cb_id; bo_handles[2] = clone->bo_cr_id; bo_handles[3] = 0; pitches[0] = clone->pitch_y; pitches[1] = clone->pitch_cb; pitches[2] = clone->pitch_cr; pitches[3] = 0; offsets[0] = clone->offset_y; offsets[1] = clone->offset_cb; offsets[2] = clone->offset_cr; offsets[3] = 0; err = drmModeAddFB2(drm_fd, clone->width, clone->height, clone->format, bo_handles, pitches, offsets, &fb_id, 0); if (err) { ErrorMsg("Failed to create DRM framebuffer: %s\n", strerror(-err)); free(clone); return NULL; } clone->fb_id = fb_id; drm_tegra_bo_ref(clone->bo); drm_tegra_bo_ref(clone->bo_cb); drm_tegra_bo_ref(clone->bo_cr); return clone; }
int add_fb_sp_bo(struct sp_bo *bo, uint32_t format) { int ret; uint32_t handles[4], pitches[4], offsets[4]; handles[0] = bo->handle; pitches[0] = bo->pitch; offsets[0] = 0; ret = drmModeAddFB2(bo->dev->fd, bo->width, bo->height, format, handles, pitches, offsets, &bo->fb_id, bo->flags); if (ret) { printf("failed to create fb ret=%d\n", ret); return ret; } return 0; }
uint32_t DisplayOzone::Buffer::getDRMFB() { if (!mHasDRMFB) { int fd = gbm_device_get_fd(mDisplay->mGBM); uint32_t handles[4] = {gbm_bo_get_handle(mBO).u32}; uint32_t pitches[4] = {gbm_bo_get_stride(mBO)}; uint32_t offsets[4] = {0}; if (drmModeAddFB2(fd, mWidth, mHeight, mDRMFormatFB, handles, pitches, offsets, &mDRMFB, 0)) { std::cerr << "drmModeAddFB2 failed" << std::endl; } else { mHasDRMFB = true; } } return mDRMFB; }
void OmapFramebuffer::Create() { const PixelFormatInfo& format_info = get_pixel_format_info(m_format); m_num_planes = format_info.num_planes; for (int i = 0; i < format_info.num_planes; ++i) { const PixelFormatPlaneInfo& pi = format_info.planes[i]; FramebufferPlane& plane = m_planes[i]; uint32_t flags = OMAP_BO_SCANOUT | OMAP_BO_WC; uint32_t size = width() * height() * pi.bitspp / 8; struct omap_bo* bo = omap_bo_new(m_omap_card.dev(), size, flags); if (!bo) throw invalid_argument(string("omap_bo_new failed: ") + strerror(errno)); uint32_t stride = width() * pi.bitspp / 8; plane.omap_bo = bo; plane.handle = omap_bo_handle(bo); plane.stride = stride; plane.size = omap_bo_size(bo); plane.offset = 0; plane.map = 0; plane.prime_fd = -1; } /* create framebuffer object for the dumb-buffer */ uint32_t bo_handles[4] = { m_planes[0].handle, m_planes[1].handle }; uint32_t pitches[4] = { m_planes[0].stride, m_planes[1].stride }; uint32_t offsets[4] = { m_planes[0].offset, m_planes[1].offset }; uint32_t id; int r = drmModeAddFB2(card().fd(), width(), height(), (uint32_t)format(), bo_handles, pitches, offsets, &id, 0); if (r) throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno)); set_id(id); }
static int fb_alloc_buffer(struct private_module_t *module, struct private_buffer_t *buffer, const drmModeModeInfo *mode) { unsigned int bo_attrs[] = { KMS_WIDTH, mode->hdisplay, KMS_HEIGHT, mode->vdisplay, KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8, KMS_TERMINATE_PROP_LIST, }; uint32_t handles[4] = { 0 }; uint32_t pitches[4] = { 0 }; uint32_t offsets[4] = { 0 }; int err; err = kms_bo_create(module->kms, bo_attrs, &buffer->bo); if (err < 0) goto done; err = kms_bo_map(buffer->bo, &buffer->vaddr); if (err < 0) goto done; kms_bo_get_prop(buffer->bo, KMS_HANDLE, &buffer->handle); handles[0] = buffer->handle; pitches[0] = mode->hdisplay * 2; err = drmModeAddFB2(module->fd, mode->hdisplay, mode->vdisplay, FB_FORMAT, handles, pitches, offsets, &buffer->fb, 0); done: if (err < 0) fb_free_buffer(module, buffer); return err; }
ExtFramebuffer::ExtFramebuffer(Card& card, uint32_t width, uint32_t height, PixelFormat format, int fds[4], uint32_t pitches[4], uint32_t offsets[4]) : Framebuffer(card, width, height) { int r; const PixelFormatInfo& format_info = get_pixel_format_info(format); uint32_t handles[4] = { 0 }; for (int i = 0; i < format_info.num_planes; ++i) { r = drmPrimeFDToHandle(card.fd(), fds[i], &handles[i]); if (r) throw invalid_argument(string("drmPrimeFDToHandle: ") + strerror(errno)); } uint32_t id; r = drmModeAddFB2(card.fd(), width, height, (uint32_t)format, handles, pitches, offsets, &id, 0); if (r) throw invalid_argument(string("drmModeAddFB2 failed: ") + strerror(errno)); set_id(id); }
int main(int argc, char **argv) { struct exynos_device *dev; struct exynos_bo *bo, *src; struct connector con; unsigned int fb_id; uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0}; drmModeRes *resources; int ret, fd, c; memset(&con, 0, sizeof(struct connector)); if (argc != 3) { usage(argv[0]); return -EINVAL; } while ((c = getopt(argc, argv, optstr)) != -1) { switch (c) { case 's': con.crtc = -1; if (sscanf(optarg, "%d:0x%64s", &con.id, con.mode_str) != 2 && sscanf(optarg, "%d@%d:%64s", &con.id, &con.crtc, con.mode_str) != 3) usage(argv[0]); break; default: usage(argv[0]); return -EINVAL; } } fd = drmOpen(DRM_MODULE_NAME, NULL); if (fd < 0) { fprintf(stderr, "failed to open.\n"); return fd; } dev = exynos_device_create(fd); if (!dev) { drmClose(dev->fd); return -EFAULT; } resources = drmModeGetResources(dev->fd); if (!resources) { fprintf(stderr, "drmModeGetResources failed: %s\n", strerror(errno)); ret = -EFAULT; goto err_drm_close; } connector_find_mode(dev->fd, &con, resources); drmModeFreeResources(resources); if (!con.mode) { fprintf(stderr, "failed to find usable connector\n"); ret = -EFAULT; goto err_drm_close; } screen_width = con.mode->hdisplay; screen_height = con.mode->vdisplay; if (screen_width == 0 || screen_height == 0) { fprintf(stderr, "failed to find sane resolution on connector\n"); ret = -EFAULT; goto err_drm_close; } printf("screen width = %d, screen height = %d\n", screen_width, screen_height); bo = exynos_create_buffer(dev, screen_width * screen_height * 4, 0); if (!bo) { ret = -EFAULT; goto err_drm_close; } handles[0] = bo->handle; pitches[0] = screen_width * 4; offsets[0] = 0; ret = drmModeAddFB2(dev->fd, screen_width, screen_height, DRM_FORMAT_RGBA8888, handles, pitches, offsets, &fb_id, 0); if (ret < 0) goto err_destroy_buffer; con.plane_zpos = -1; memset(bo->vaddr, 0xff, screen_width * screen_height * 4); ret = drm_set_crtc(dev, &con, fb_id); if (ret < 0) goto err_rm_fb; ret = test_case.solid_fill(dev, bo); if (ret < 0) { fprintf(stderr, "failed to solid fill operation.\n"); goto err_rm_fb; } wait_for_user_input(0); src = exynos_create_buffer(dev, screen_width * screen_height * 4, 0); if (!src) { ret = -EFAULT; goto err_rm_fb; } ret = test_case.copy(dev, src, bo, G2D_IMGBUF_GEM); if (ret < 0) { fprintf(stderr, "failed to test copy operation.\n"); goto err_free_src; } wait_for_user_input(0); ret = test_case.copy_with_scale(dev, src, bo, G2D_IMGBUF_GEM); if (ret < 0) { fprintf(stderr, "failed to test copy and scale operation.\n"); goto err_free_src; } wait_for_user_input(0); ret = test_case.checkerboard(dev, src, bo, G2D_IMGBUF_GEM); if (ret < 0) { fprintf(stderr, "failed to issue checkerboard test.\n"); goto err_free_src; } wait_for_user_input(1); /* * The blend test uses the userptr functionality of exynos-drm, which * is currently not safe to use. If the kernel hasn't been build with * exynos-iommu support, then the blend test is going to produce (kernel) * memory corruption, eventually leading to a system crash. * * Disable the test for now, until the kernel code has been sanitized. */ #if 0 ret = test_case.blend(dev, src, bo, G2D_IMGBUF_USERPTR); if (ret < 0) fprintf(stderr, "failed to test blend operation.\n"); getchar(); #endif err_free_src: if (src) exynos_destroy_buffer(src); err_rm_fb: drmModeRmFB(dev->fd, fb_id); err_destroy_buffer: exynos_destroy_buffer(bo); err_drm_close: drmClose(dev->fd); exynos_device_destroy(dev); return 0; }
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 drm_overlay_fb * drm_create_fb_internal(struct drm_tegra *drm, int drm_fd, uint32_t drm_format, uint32_t width, uint32_t height, uint32_t *bo_handles, uint32_t *pitches, uint32_t *offsets, Bool dont_map) { struct drm_tegra_bo *bo = NULL; struct drm_tegra_bo *bo_cb = NULL; struct drm_tegra_bo *bo_cr = NULL; drm_overlay_fb *fb = NULL; uint32_t fb_id = HANDLE_INVALID; Bool from_handle; int err; if (width == 0 || height == 0) return NULL; if (!pitches) { pitches = alloca(sizeof(uint32_t) * 4); pitches[0] = fb_pitch_aligned(drm_format, width); pitches[1] = fb_pitch_c_aligned(drm_format, width); pitches[2] = fb_pitch_c_aligned(drm_format, width); pitches[3] = 0; } if (!offsets) { offsets = alloca(sizeof(uint32_t) * 4); offsets[0] = 0; offsets[1] = 0; offsets[2] = 0; offsets[3] = 0; } from_handle = !!(bo_handles); if (from_handle) { err = drm_tegra_bo_wrap(&bo, drm, bo_handles[0], 0, pitches[0] * height); if (err) goto error_cleanup; drm_tegra_bo_forbid_caching(bo); if (format_planar(drm_format)) { err = drm_tegra_bo_wrap(&bo_cb, drm, bo_handles[1], 0, pitches[1] * height / 2); if (err) goto error_cleanup; drm_tegra_bo_forbid_caching(bo_cb); err = drm_tegra_bo_wrap(&bo_cr, drm, bo_handles[2], 0, pitches[2] * height / 2); if (err) goto error_cleanup; drm_tegra_bo_forbid_caching(bo_cr); } goto create_framebuffer; } bo_handles = alloca(sizeof(uint32_t) * 4); bo_handles[1] = HANDLE_INVALID; bo_handles[2] = HANDLE_INVALID; bo_handles[3] = HANDLE_INVALID; /* Allocate PLANE[0] */ err = drm_tegra_bo_new(&bo, drm, 0, offsets[0] + fb_size_aligned(drm_format, width, height)); if (err) goto error_cleanup; drm_tegra_bo_get_handle(bo, &bo_handles[0]); if (!format_planar(drm_format)) goto create_framebuffer; /* Allocate PLANE[1] */ err = drm_tegra_bo_new(&bo_cb, drm, 0, offsets[1] + fb_size_c_aligned(drm_format, width, height)); if (err) goto error_cleanup; drm_tegra_bo_get_handle(bo_cb, &bo_handles[1]); /* Allocate PLANE[2] */ err = drm_tegra_bo_new(&bo_cr, drm, 0, offsets[2] + fb_size_c_aligned(drm_format, width, height)); if (err) goto error_cleanup; drm_tegra_bo_get_handle(bo_cr, &bo_handles[2]); create_framebuffer: err = drmModeAddFB2(drm_fd, width, height, drm_format, bo_handles, pitches, offsets, &fb_id, 0); if (err) { ErrorMsg("Failed to create DRM framebuffer: %s\n", strerror(-err)); goto error_cleanup; } fb = calloc(1, sizeof(*fb)); if (!fb) goto error_cleanup; fb->fb_id = fb_id; fb->format = drm_format; fb->width = width; fb->height = height; fb->width_c = fb_width_c(drm_format, width); fb->height_c = fb_height_c(drm_format, height); fb->bpp = fb_bpp(drm_format); fb->bpp_c = fb_bpp_c(drm_format); fb->bo_y_id = bo_handles[0]; fb->bo_cb_id = bo_handles[1]; fb->bo_cr_id = bo_handles[2]; fb->bo_y = bo; fb->bo_cb = bo_cb; fb->bo_cr = bo_cr; fb->pitch_y = pitches[0]; fb->pitch_cb = pitches[1]; fb->pitch_cr = pitches[2]; fb->offset_y = offsets[0]; fb->offset_cb = offsets[1]; fb->offset_cr = offsets[2]; fb->width_pad = (fb_pitch_aligned(drm_format, width) - fb_pitch(drm_format, width)) * fb_height_aligned(drm_format, height); fb->height_pad = (fb_height_aligned(drm_format, height) - height) * fb_pitch_aligned(drm_format, width); fb->height_offset = (fb_height_aligned(drm_format, height) - height) * fb->bpp / 8; fb->width_c_pad = (fb_pitch_c_aligned(drm_format, width) - fb_pitch_c(drm_format, width)) * fb_height_c_aligned(drm_format, height); fb->height_c_pad = (fb_height_c_aligned(drm_format, height) - fb->height_c) * fb_pitch_c_aligned(drm_format, width); fb->height_c_offset = (fb_height_c_aligned(drm_format, height) - fb->height_c) * fb->bpp_c / 8; if (dont_map) return fb; err = drm_tegra_bo_map(fb->bo_y, (void **)&fb->bo_y_mmap); if (err) goto error_cleanup; fb->bo_y_mmap += fb->offset_y; if (!format_planar(drm_format)) return fb; err = drm_tegra_bo_map(fb->bo_cb, (void **)&fb->bo_cb_mmap); if (err) goto error_cleanup; err = drm_tegra_bo_map(fb->bo_cr, (void **)&fb->bo_cr_mmap); if (err) goto error_cleanup; fb->bo_cb_mmap += fb->offset_cb; fb->bo_cr_mmap += fb->offset_cr; return fb; error_cleanup: if (from_handle) return NULL; if (fb_id != HANDLE_INVALID) drmModeRmFB(drm_fd, fb_id); drm_tegra_bo_unref(bo); drm_tegra_bo_unref(bo_cb); drm_tegra_bo_unref(bo_cr); free(fb); return NULL; }
bool CreateFramebuffer(int width, int height, Framebuffer& framebuffer) { framebuffer.bo = gbm_bo_create(gbm_, width, height, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); if (!framebuffer.bo) { fprintf(stderr, "failed to create a gbm buffer.\n"); return false; } framebuffer.fd = gbm_bo_get_fd(framebuffer.bo); if (framebuffer.fd < 0) { fprintf(stderr, "failed to get fb for bo: %d", framebuffer.fd); return false; } uint32_t handle = gbm_bo_get_handle(framebuffer.bo).u32; uint32_t stride = gbm_bo_get_stride(framebuffer.bo); uint32_t offset = 0; drmModeAddFB2(drm_->GetFD(), width, height, GBM_FORMAT_XRGB8888, &handle, &stride, &offset, &framebuffer.fb_id, 0); if (!framebuffer.fb_id) { fprintf(stderr, "failed to create framebuffer from buffer object.\n"); return false; } const EGLint khr_image_attrs[] = {EGL_DMA_BUF_PLANE0_FD_EXT, framebuffer.fd, EGL_WIDTH, width, EGL_HEIGHT, height, EGL_LINUX_DRM_FOURCC_EXT, GBM_FORMAT_XRGB8888, EGL_DMA_BUF_PLANE0_PITCH_EXT, static_cast<const int>(stride), EGL_DMA_BUF_PLANE0_OFFSET_EXT, static_cast<const int>(offset), EGL_NONE}; framebuffer.image = egl_.CreateImageKHR(egl_.display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr /* no client buffer */, khr_image_attrs); if (framebuffer.image == EGL_NO_IMAGE_KHR) { fprintf(stderr, "failed to make image from buffer object: %s\n", EglGetError()); return false; } glGenTextures(1, &framebuffer.gl_tex); glBindTexture(GL_TEXTURE_2D, framebuffer.gl_tex); egl_.EGLImageTargetTexture2DOES(GL_TEXTURE_2D, framebuffer.image); glBindTexture(GL_TEXTURE_2D, 0); glGenFramebuffers(1, &framebuffer.gl_fb); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.gl_fb); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebuffer.gl_tex, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { fprintf(stderr, "failed framebuffer check for created target buffer: %x\n", glCheckFramebufferStatus(GL_FRAMEBUFFER)); glDeleteFramebuffers(1, &framebuffer.gl_fb); glDeleteTextures(1, &framebuffer.gl_tex); return false; } return true; }
static int exynos_alloc(struct hook_data *data) { struct exynos_device *device; struct exynos_bo *bo; struct exynos_page *pages; struct drm_prime_handle req = { 0 }; unsigned i; const unsigned flags = 0; device = exynos_device_create(data->drm_fd); if (device == NULL) { fprintf(stderr, "[exynos_init] error: failed to create device from fd\n"); return -1; } pages = calloc(data->num_pages, sizeof(struct exynos_page)); if (pages == NULL) { fprintf(stderr, "[exynos_init] error: failed to allocate pages\n"); goto fail_alloc; } for (i = 0; i < data->num_pages; ++i) { bo = exynos_bo_create(device, data->size, flags); if (bo == NULL) { fprintf(stderr, "[exynos_init] error: failed to create buffer object\n"); goto fail; } req.handle = bo->handle; if (drmIoctl(data->drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &req) < 0) { fprintf(stderr, "[exynos_init] error: failed to get fd from bo\n"); exynos_bo_destroy(bo); goto fail; } /* Don't map the BO, since we don't access it through userspace. */ pages[i].bo = bo; pages[i].fd = req.fd; pages[i].base = data; pages[i].used = false; pages[i].clear = true; } if (vconf.use_screen == 1) { const uint32_t pixel_format = (data->bpp == 2) ? DRM_FORMAT_RGB565 : DRM_FORMAT_XRGB8888; uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0}; pitches[0] = data->pitch; offsets[0] = 0; for (i = 0; i < data->num_pages; ++i) { handles[0] = pages[i].bo->handle; if (drmModeAddFB2(data->drm_fd, data->width, data->height, pixel_format, handles, pitches, offsets, &pages[i].buf_id, flags)) { fprintf(stderr, "[exynos_init] error: failed to add bo %u to fb\n", i); goto fail; } } } if (vconf.use_screen == 1) { /* Setup CRTC: display the last allocated page. */ if (drmModeSetCrtc(data->drm_fd, data->drm->crtc_id, pages[data->num_pages - 1].buf_id, 0, 0, &data->drm->connector_id, 1, data->drm->mode)) { fprintf(stderr, "[exynos_init] error: drmModeSetCrtc failed\n"); goto fail; } } data->pages = pages; data->device = device; return 0; fail: clean_up_pages(pages, data->num_pages); fail_alloc: exynos_device_destroy(device); return -1; }