예제 #1
0
int virtio_gpu_gem_create(struct drm_file *file,
			  struct drm_device *dev,
			  uint64_t size,
			  struct drm_gem_object **obj_p,
			  uint32_t *handle_p)
{
	struct virtio_gpu_object *obj;
	int ret;
	u32 handle;

	obj = virtio_gpu_alloc_object(dev, size, false, false);
	if (IS_ERR(obj))
		return PTR_ERR(obj);

	ret = drm_gem_handle_create(file, &obj->gem_base, &handle);
	if (ret) {
		drm_gem_object_release(&obj->gem_base);
		return ret;
	}

	*obj_p = &obj->gem_base;

	/* drop reference from allocate - handle holds it now */
	drm_gem_object_unreference_unlocked(&obj->gem_base);

	*handle_p = handle;
	return 0;
}
예제 #2
0
파일: virtgpu_fb.c 프로젝트: Lyude/linux
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;
}
예제 #3
0
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);

    switch (mode_cmd.pixel_format) {
#ifdef __BIG_ENDIAN
    case DRM_FORMAT_XRGB8888:
        format = VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM;
        break;
    case DRM_FORMAT_ARGB8888:
        format = VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM;
        break;
    case DRM_FORMAT_BGRX8888:
        format = VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM;
        break;
    case DRM_FORMAT_BGRA8888:
        format = VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM;
        break;
    case DRM_FORMAT_RGBX8888:
        format = VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM;
        break;
    case DRM_FORMAT_RGBA8888:
        format = VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM;
        break;
    case DRM_FORMAT_XBGR8888:
        format = VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM;
        break;
    case DRM_FORMAT_ABGR8888:
        format = VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM;
        break;
#else
    case DRM_FORMAT_XRGB8888:
        format = VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM;
        break;
    case DRM_FORMAT_ARGB8888:
        format = VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM;
        break;
    case DRM_FORMAT_BGRX8888:
        format = VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM;
        break;
    case DRM_FORMAT_BGRA8888:
        format = VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM;
        break;
    case DRM_FORMAT_RGBX8888:
        format = VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM;
        break;
    case DRM_FORMAT_RGBA8888:
        format = VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM;
        break;
    case DRM_FORMAT_XBGR8888:
        format = VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM;
        break;
    case DRM_FORMAT_ABGR8888:
        format = VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM;
        break;
#endif
    default:
        DRM_ERROR("failed to find virtio gpu format for %d\n",
                  mode_cmd.pixel_format);
        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_init;

    fb = &vfbdev->vgfb.base;

    vfbdev->helper.fb = fb;

    strcpy(info->fix.id, "virtiodrmfb");
    info->flags = FBINFO_DEFAULT;
    info->fbops = &virtio_gpufb_ops;
    info->pixmap.flags = FB_PIXMAP_SYSTEM;

    info->screen_base = obj->vmap;
    info->screen_size = obj->gem_base.size;
    drm_fb_helper_fill_fix(info, fb->pitches[0], fb->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_init:
    drm_fb_helper_release_fbi(helper);
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;
}