int virtio_gpu_mode_dumb_create(struct drm_file *file_priv, struct drm_device *dev, struct drm_mode_create_dumb *args) { struct virtio_gpu_device *vgdev = dev->dev_private; struct drm_gem_object *gobj; struct virtio_gpu_object *obj; int ret; uint32_t pitch; uint32_t resid; uint32_t format; pitch = args->width * ((args->bpp + 1) / 8); args->size = pitch * args->height; args->size = ALIGN(args->size, PAGE_SIZE); ret = virtio_gpu_gem_create(file_priv, dev, args->size, &gobj, &args->handle); if (ret) goto fail; format = virtio_gpu_translate_format(DRM_FORMAT_XRGB8888); virtio_gpu_resource_id_get(vgdev, &resid); virtio_gpu_cmd_create_resource(vgdev, resid, format, args->width, args->height); /* attach the object to the resource */ obj = gem_to_virtio_gpu_obj(gobj); ret = virtio_gpu_object_attach(vgdev, obj, resid, NULL); if (ret) goto fail; obj->dumb = true; args->pitch = pitch; return ret; fail: return ret; }
static int virtio_gpufb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct virtio_gpu_fbdev *vfbdev = container_of(helper, struct virtio_gpu_fbdev, helper); struct drm_device *dev = helper->dev; struct virtio_gpu_device *vgdev = dev->dev_private; struct fb_info *info; struct drm_framebuffer *fb; struct drm_mode_fb_cmd2 mode_cmd = {}; struct virtio_gpu_object *obj; uint32_t resid, format, size; int ret; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.pitches[0] = mode_cmd.width * 4; mode_cmd.pixel_format = drm_mode_legacy_fb_format(32, 24); format = virtio_gpu_translate_format(mode_cmd.pixel_format); if (format == 0) return -EINVAL; size = mode_cmd.pitches[0] * mode_cmd.height; obj = virtio_gpu_alloc_object(dev, size, false, true); if (IS_ERR(obj)) return PTR_ERR(obj); virtio_gpu_resource_id_get(vgdev, &resid); virtio_gpu_cmd_create_resource(vgdev, resid, format, mode_cmd.width, mode_cmd.height); ret = virtio_gpu_vmap_fb(vgdev, obj); if (ret) { DRM_ERROR("failed to vmap fb %d\n", ret); goto err_obj_vmap; } /* attach the object to the resource */ ret = virtio_gpu_object_attach(vgdev, obj, resid, NULL); if (ret) goto err_obj_attach; info = drm_fb_helper_alloc_fbi(helper); if (IS_ERR(info)) { ret = PTR_ERR(info); goto err_fb_alloc; } info->par = helper; ret = virtio_gpu_framebuffer_init(dev, &vfbdev->vgfb, &mode_cmd, &obj->gem_base); if (ret) goto err_fb_alloc; fb = &vfbdev->vgfb.base; vfbdev->helper.fb = fb; strcpy(info->fix.id, "virtiodrmfb"); info->fbops = &virtio_gpufb_ops; info->pixmap.flags = FB_PIXMAP_SYSTEM; info->screen_buffer = obj->vmap; info->screen_size = obj->gem_base.size; drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); drm_fb_helper_fill_var(info, &vfbdev->helper, sizes->fb_width, sizes->fb_height); info->fix.mmio_start = 0; info->fix.mmio_len = 0; return 0; err_fb_alloc: virtio_gpu_cmd_resource_inval_backing(vgdev, resid); err_obj_attach: err_obj_vmap: virtio_gpu_gem_free_object(&obj->gem_base); return ret; }