drivers/gpu/drm/drm_dumb_buffers.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/drm_dumb_buffers.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/drm_dumb_buffers.c
Extension
.c
Size
9960 bytes
Lines
304
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (args->bpp) {
		default:
			drm_warn_once(dev,
				      "Unknown color mode %u; guessing buffer size.\n",
				      args->bpp);
			fallthrough;
		/*
		 * These constants represent various YUV formats supported by
		 * drm_gem_afbc_get_bpp().
		 */
		case 12: // DRM_FORMAT_YUV420_8BIT
		case 15: // DRM_FORMAT_YUV420_10BIT
		case 30: // DRM_FORMAT_VUY101010
			fallthrough;
		/*
		 * Used by Mesa and Gstreamer to allocate NV formats and others
		 * as RGB buffers. Technically, XRGB16161616F formats are RGB,
		 * but the dumb buffers are not supposed to be used for anything
		 * beyond 32 bits per pixels.
		 */
		case 10: // DRM_FORMAT_NV{15,20,30}, DRM_FORMAT_P010
		case 64: // DRM_FORMAT_{XRGB,XBGR,ARGB,ABGR}16161616F
			pitch = args->width * DIV_ROUND_UP(args->bpp, SZ_8);
			break;
		}
	}

	if (!pitch || pitch > U32_MAX)
		return -EINVAL;

	args->pitch = pitch;

	return drm_mode_align_dumb(args, hw_pitch_align, hw_size_align);
}
EXPORT_SYMBOL(drm_mode_size_dumb);

int drm_mode_create_dumb(struct drm_device *dev,
			 struct drm_mode_create_dumb *args,
			 struct drm_file *file_priv)
{
	u32 cpp, stride, size;

	if (!dev->driver->dumb_create)
		return -ENOSYS;
	if (!args->width || !args->height || !args->bpp)
		return -EINVAL;

	/* overflow checks for 32bit size calculations */
	if (args->bpp > U32_MAX - 8)
		return -EINVAL;
	cpp = DIV_ROUND_UP(args->bpp, 8);
	if (cpp > U32_MAX / args->width)
		return -EINVAL;
	stride = cpp * args->width;
	if (args->height > U32_MAX / stride)
		return -EINVAL;

	/* test for wrap-around */
	size = args->height * stride;
	if (PAGE_ALIGN(size) == 0)
		return -EINVAL;

	/*
	 * handle, pitch and size are output parameters. Zero them out to
	 * prevent drivers from accidentally using uninitialized data. Since
	 * not all existing userspace is clearing these fields properly we
	 * cannot reject IOCTL with garbage in them.
	 */
	args->handle = 0;
	args->pitch = 0;
	args->size = 0;

	return dev->driver->dumb_create(file_priv, dev, args);
}

int drm_mode_create_dumb_ioctl(struct drm_device *dev,
			       void *data, struct drm_file *file_priv)
{
	struct drm_mode_create_dumb *args = data;
	int err;

	err = drm_mode_create_dumb(dev, args, file_priv);
	if (err) {
		args->handle = 0;
		args->pitch = 0;
		args->size = 0;
	}
	return err;
}

Annotation

Implementation Notes