mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	Merge pull request #724 from agx/linux-dmabuf-mp
Linux-dmabuf with n_planes > 1
This commit is contained in:
		
						commit
						7cc042f54c
					
				
					 4 changed files with 108 additions and 66 deletions
				
			
		
							
								
								
									
										85
									
								
								render/egl.c
									
										
									
									
									
								
							
							
						
						
									
										85
									
								
								render/egl.c
									
										
									
									
									
								
							| 
						 | 
					@ -325,15 +325,6 @@ bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EGLImage wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
 | 
					EGLImage wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
 | 
				
			||||||
		struct wlr_dmabuf_buffer_attribs *attributes) {
 | 
							struct wlr_dmabuf_buffer_attribs *attributes) {
 | 
				
			||||||
	int atti = 0;
 | 
					 | 
				
			||||||
	EGLint attribs[20];
 | 
					 | 
				
			||||||
	attribs[atti++] = EGL_WIDTH;
 | 
					 | 
				
			||||||
	attribs[atti++] = attributes->width;
 | 
					 | 
				
			||||||
	attribs[atti++] = EGL_HEIGHT;
 | 
					 | 
				
			||||||
	attribs[atti++] = attributes->height;
 | 
					 | 
				
			||||||
	attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
 | 
					 | 
				
			||||||
	attribs[atti++] = attributes->format;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bool has_modifier = false;
 | 
						bool has_modifier = false;
 | 
				
			||||||
	if (attributes->modifier[0] != DRM_FORMAT_MOD_INVALID) {
 | 
						if (attributes->modifier[0] != DRM_FORMAT_MOD_INVALID) {
 | 
				
			||||||
		if (!egl->egl_exts.dmabuf_import_modifiers) {
 | 
							if (!egl->egl_exts.dmabuf_import_modifiers) {
 | 
				
			||||||
| 
						 | 
					@ -342,25 +333,66 @@ EGLImage wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
 | 
				
			||||||
		has_modifier = true;
 | 
							has_modifier = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* TODO: YUV planes have up four planes but we only support a
 | 
						unsigned int atti = 0;
 | 
				
			||||||
	   single EGLImage for now */
 | 
						EGLint attribs[50];
 | 
				
			||||||
	if (attributes->n_planes > 1) {
 | 
						attribs[atti++] = EGL_WIDTH;
 | 
				
			||||||
		return NULL;
 | 
						attribs[atti++] = attributes->width;
 | 
				
			||||||
	}
 | 
						attribs[atti++] = EGL_HEIGHT;
 | 
				
			||||||
 | 
						attribs[atti++] = attributes->height;
 | 
				
			||||||
 | 
						attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
 | 
				
			||||||
 | 
						attribs[atti++] = attributes->format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
 | 
						struct {
 | 
				
			||||||
	attribs[atti++] = attributes->fd[0];
 | 
							EGLint fd;
 | 
				
			||||||
	attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
 | 
							EGLint offset;
 | 
				
			||||||
	attribs[atti++] = attributes->offset[0];
 | 
							EGLint pitch;
 | 
				
			||||||
	attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
 | 
							EGLint mod_lo;
 | 
				
			||||||
	attribs[atti++] = attributes->stride[0];
 | 
							EGLint mod_hi;
 | 
				
			||||||
	if (has_modifier) {
 | 
						} attr_names[WLR_LINUX_DMABUF_MAX_PLANES] = {
 | 
				
			||||||
		attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
 | 
							{
 | 
				
			||||||
		attribs[atti++] = attributes->modifier[0] & 0xFFFFFFFF;
 | 
								EGL_DMA_BUF_PLANE0_FD_EXT,
 | 
				
			||||||
		attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
 | 
								EGL_DMA_BUF_PLANE0_OFFSET_EXT,
 | 
				
			||||||
		attribs[atti++] = attributes->modifier[0] >> 32;
 | 
								EGL_DMA_BUF_PLANE0_PITCH_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT
 | 
				
			||||||
 | 
							}, {
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE1_FD_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE1_OFFSET_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE1_PITCH_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT
 | 
				
			||||||
 | 
							}, {
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE2_FD_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE2_OFFSET_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE2_PITCH_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT
 | 
				
			||||||
 | 
							}, {
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE3_FD_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE3_OFFSET_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE3_PITCH_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT,
 | 
				
			||||||
 | 
								EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (int i=0; i < attributes->n_planes; i++) {
 | 
				
			||||||
 | 
							attribs[atti++] = attr_names[i].fd;
 | 
				
			||||||
 | 
							attribs[atti++] = attributes->fd[i];
 | 
				
			||||||
 | 
							attribs[atti++] = attr_names[i].offset;
 | 
				
			||||||
 | 
							attribs[atti++] = attributes->offset[i];
 | 
				
			||||||
 | 
							attribs[atti++] = attr_names[i].pitch;
 | 
				
			||||||
 | 
							attribs[atti++] = attributes->stride[i];
 | 
				
			||||||
 | 
							if (has_modifier) {
 | 
				
			||||||
 | 
								attribs[atti++] = attr_names[i].mod_lo;
 | 
				
			||||||
 | 
								attribs[atti++] = attributes->modifier[i] & 0xFFFFFFFF;
 | 
				
			||||||
 | 
								attribs[atti++] = attr_names[i].mod_hi;
 | 
				
			||||||
 | 
								attribs[atti++] = attributes->modifier[i] >> 32;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	attribs[atti++] = EGL_NONE;
 | 
						attribs[atti++] = EGL_NONE;
 | 
				
			||||||
 | 
						assert(atti < sizeof(attribs)/sizeof(attribs[0]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return eglCreateImageKHR(egl->display, EGL_NO_CONTEXT,
 | 
						return eglCreateImageKHR(egl->display, EGL_NO_CONTEXT,
 | 
				
			||||||
		EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
 | 
							EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -371,7 +403,8 @@ EGLImage wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
 | 
				
			||||||
bool wlr_egl_check_import_dmabuf(struct wlr_egl *egl,
 | 
					bool wlr_egl_check_import_dmabuf(struct wlr_egl *egl,
 | 
				
			||||||
		struct wlr_dmabuf_buffer *dmabuf) {
 | 
							struct wlr_dmabuf_buffer *dmabuf) {
 | 
				
			||||||
	switch (dmabuf->attributes.format & ~DRM_FORMAT_BIG_ENDIAN) {
 | 
						switch (dmabuf->attributes.format & ~DRM_FORMAT_BIG_ENDIAN) {
 | 
				
			||||||
		/* YUV based formats not yet supported */
 | 
							/* TODO: YUV based formats not yet supported, require multiple
 | 
				
			||||||
 | 
							 * wlr_create_image_from_dmabuf */
 | 
				
			||||||
	case WL_SHM_FORMAT_YUYV:
 | 
						case WL_SHM_FORMAT_YUYV:
 | 
				
			||||||
	case WL_SHM_FORMAT_YVYU:
 | 
						case WL_SHM_FORMAT_YVYU:
 | 
				
			||||||
	case WL_SHM_FORMAT_UYVY:
 | 
						case WL_SHM_FORMAT_UYVY:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -275,9 +275,15 @@ static bool gles2_texture_upload_dmabuf(struct wlr_texture *wlr_texture,
 | 
				
			||||||
		wlr_texture->inverted_y = true;
 | 
							wlr_texture->inverted_y = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	GLenum target = GL_TEXTURE_2D;
 | 
						GLenum target;
 | 
				
			||||||
	const struct gles2_pixel_format *pf =
 | 
						const struct gles2_pixel_format *pf;
 | 
				
			||||||
		gles2_format_from_wl(WL_SHM_FORMAT_ARGB8888);
 | 
						if (dmabuf->attributes.n_planes > 1) {
 | 
				
			||||||
 | 
							target = GL_TEXTURE_EXTERNAL_OES;
 | 
				
			||||||
 | 
							pf = &external_pixel_format;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							target = GL_TEXTURE_2D;
 | 
				
			||||||
 | 
							pf = gles2_format_from_wl(WL_SHM_FORMAT_ARGB8888);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	GLES2_DEBUG_PUSH;
 | 
						GLES2_DEBUG_PUSH;
 | 
				
			||||||
	gles2_texture_ensure(tex, target);
 | 
						gles2_texture_ensure(tex, target);
 | 
				
			||||||
	glBindTexture(target, tex->tex_id);
 | 
						glBindTexture(target, tex->tex_id);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,19 +139,18 @@ static void params_create_common(struct wl_client *client,
 | 
				
			||||||
		goto err_out;
 | 
							goto err_out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* TODO: support more planes */
 | 
					 | 
				
			||||||
	if (buffer->attributes.n_planes != 1) {
 | 
					 | 
				
			||||||
		wl_resource_post_error(params_resource,
 | 
					 | 
				
			||||||
			ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
 | 
					 | 
				
			||||||
			"only single plane buffers supported not %d",
 | 
					 | 
				
			||||||
			buffer->attributes.n_planes);
 | 
					 | 
				
			||||||
		goto err_out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (buffer->attributes.fd[0] == -1) {
 | 
						if (buffer->attributes.fd[0] == -1) {
 | 
				
			||||||
		wl_resource_post_error(params_resource,
 | 
							wl_resource_post_error(params_resource,
 | 
				
			||||||
			ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
 | 
								ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
 | 
				
			||||||
			"no dmabuf has been added for plane");
 | 
								"no dmabuf has been added for plane 0");
 | 
				
			||||||
 | 
							goto err_out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((buffer->attributes.fd[3] >= 0 || buffer->attributes.fd[2] >= 0) &&
 | 
				
			||||||
 | 
								(buffer->attributes.fd[2] == -1 || buffer->attributes.fd[1] == -1)) {
 | 
				
			||||||
 | 
							wl_resource_post_error (params_resource,
 | 
				
			||||||
 | 
								ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
 | 
				
			||||||
 | 
								"gap in dmabuf planes");
 | 
				
			||||||
		goto err_out;
 | 
							goto err_out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -167,43 +166,48 @@ static void params_create_common(struct wl_client *client,
 | 
				
			||||||
		goto err_out;
 | 
							goto err_out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((uint64_t)buffer->attributes.offset[0] + buffer->attributes.stride[0] > UINT32_MAX) {
 | 
						for (int i = 0; i < buffer->attributes.n_planes; i++) {
 | 
				
			||||||
		wl_resource_post_error(params_resource,
 | 
							if ((uint64_t)buffer->attributes.offset[i]
 | 
				
			||||||
			ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
 | 
									+ buffer->attributes.stride[i] > UINT32_MAX) {
 | 
				
			||||||
			"size overflow for plane");
 | 
					 | 
				
			||||||
		goto err_out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((uint64_t)buffer->attributes.offset[0] +
 | 
					 | 
				
			||||||
			(uint64_t)buffer->attributes.stride[0] * height > UINT32_MAX) {
 | 
					 | 
				
			||||||
		wl_resource_post_error(params_resource,
 | 
					 | 
				
			||||||
			ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
 | 
					 | 
				
			||||||
			"size overflow for plane");
 | 
					 | 
				
			||||||
		goto err_out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	off_t size = lseek(buffer->attributes.fd[0], 0, SEEK_END);
 | 
					 | 
				
			||||||
	if (size != -1) { /* Skip checks if kernel does no support seek on buffer */
 | 
					 | 
				
			||||||
		if (buffer->attributes.offset[0] >= size) {
 | 
					 | 
				
			||||||
			wl_resource_post_error(params_resource,
 | 
								wl_resource_post_error(params_resource,
 | 
				
			||||||
				ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
 | 
									ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
 | 
				
			||||||
				"invalid offset %i for plane",
 | 
									"size overflow for plane %d", i);
 | 
				
			||||||
				buffer->attributes.offset[0]);
 | 
					 | 
				
			||||||
			goto err_out;
 | 
								goto err_out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (buffer->attributes.offset[0] + buffer->attributes.stride[0] > size) {
 | 
							if ((uint64_t)buffer->attributes.offset[i]
 | 
				
			||||||
 | 
									+ (uint64_t)buffer->attributes.stride[i] * height > UINT32_MAX) {
 | 
				
			||||||
			wl_resource_post_error(params_resource,
 | 
								wl_resource_post_error(params_resource,
 | 
				
			||||||
				ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
 | 
									ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
 | 
				
			||||||
				"invalid stride %i for plane",
 | 
									"size overflow for plane %d", i);
 | 
				
			||||||
				buffer->attributes.stride[0]);
 | 
					 | 
				
			||||||
			goto err_out;
 | 
								goto err_out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (buffer->attributes.offset[0] + buffer->attributes.stride[0] * height > size) {
 | 
							off_t size = lseek(buffer->attributes.fd[i], 0, SEEK_END);
 | 
				
			||||||
 | 
							if (size == -1) { /* Skip checks if kernel does no support seek on buffer */
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (buffer->attributes.offset[i] >= size) {
 | 
				
			||||||
			wl_resource_post_error(params_resource,
 | 
								wl_resource_post_error(params_resource,
 | 
				
			||||||
				ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
 | 
									ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
 | 
				
			||||||
				"invalid buffer stride or height for plane");
 | 
									"invalid offset %i for plane %d",
 | 
				
			||||||
 | 
									buffer->attributes.offset[i], i);
 | 
				
			||||||
 | 
								goto err_out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (buffer->attributes.offset[i] + buffer->attributes.stride[i]	> size) {
 | 
				
			||||||
 | 
								wl_resource_post_error(params_resource,
 | 
				
			||||||
 | 
									ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
 | 
				
			||||||
 | 
									"invalid stride %i for plane %d",
 | 
				
			||||||
 | 
									buffer->attributes.stride[i], i);
 | 
				
			||||||
 | 
								goto err_out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (i == 0 && /* planes > 0 might be subsampled according to fourcc format */
 | 
				
			||||||
 | 
								buffer->attributes.offset[i] + buffer->attributes.stride[i] * height > size) {
 | 
				
			||||||
 | 
								wl_resource_post_error(params_resource,
 | 
				
			||||||
 | 
									ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
 | 
				
			||||||
 | 
									"invalid buffer stride or height for plane %d", i);
 | 
				
			||||||
			goto err_out;
 | 
								goto err_out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -325,8 +325,7 @@ static void wlr_surface_apply_damage(struct wlr_surface *surface,
 | 
				
			||||||
					surface->current->buffer)) {
 | 
										surface->current->buffer)) {
 | 
				
			||||||
			wlr_texture_upload_drm(surface->texture, surface->current->buffer);
 | 
								wlr_texture_upload_drm(surface->texture, surface->current->buffer);
 | 
				
			||||||
			goto release;
 | 
								goto release;
 | 
				
			||||||
		} else if (wlr_dmabuf_resource_is_buffer(
 | 
							} else if (wlr_dmabuf_resource_is_buffer(surface->current->buffer)) {
 | 
				
			||||||
					   surface->current->buffer)) {
 | 
					 | 
				
			||||||
			wlr_texture_upload_dmabuf(surface->texture, surface->current->buffer);
 | 
								wlr_texture_upload_dmabuf(surface->texture, surface->current->buffer);
 | 
				
			||||||
			goto release;
 | 
								goto release;
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue