mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	output: fix attach_buffer semantics
This commit is contained in:
		
							parent
							
								
									1d222309b8
								
							
						
					
					
						commit
						afe7b207d5
					
				
					 4 changed files with 52 additions and 40 deletions
				
			
		| 
						 | 
					@ -301,11 +301,44 @@ static bool drm_connector_commit(struct wlr_output *output) {
 | 
				
			||||||
		damage = &output->pending.damage;
 | 
							damage = &output->pending.damage;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct gbm_bo *bo = swap_drm_surface_buffers(&plane->surf, damage);
 | 
						struct gbm_bo *bo;
 | 
				
			||||||
	if (drm->parent) {
 | 
						uint32_t fb_id = 0;
 | 
				
			||||||
		bo = copy_drm_surface_mgpu(&plane->mgpu_surf, bo);
 | 
						assert(output->pending.committed & WLR_OUTPUT_STATE_BUFFER);
 | 
				
			||||||
 | 
						switch (output->pending.buffer_type) {
 | 
				
			||||||
 | 
						case WLR_OUTPUT_STATE_BUFFER_RENDER:
 | 
				
			||||||
 | 
							bo = swap_drm_surface_buffers(&plane->surf, damage);
 | 
				
			||||||
 | 
							if (bo == NULL) {
 | 
				
			||||||
 | 
								wlr_log(WLR_ERROR, "swap_drm_surface_buffers failed");
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (drm->parent) {
 | 
				
			||||||
 | 
								bo = copy_drm_surface_mgpu(&plane->mgpu_surf, bo);
 | 
				
			||||||
 | 
								if (bo == NULL) {
 | 
				
			||||||
 | 
									wlr_log(WLR_ERROR, "copy_drm_surface_mgpu failed");
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							fb_id = get_fb_for_bo(bo, plane->drm_format);
 | 
				
			||||||
 | 
							if (fb_id == 0) {
 | 
				
			||||||
 | 
								wlr_log(WLR_ERROR, "get_fb_for_bo failed");
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case WLR_OUTPUT_STATE_BUFFER_SCANOUT:
 | 
				
			||||||
 | 
							bo = import_gbm_bo(&drm->renderer, &conn->pending_dmabuf);
 | 
				
			||||||
 | 
							if (bo == NULL) {
 | 
				
			||||||
 | 
								wlr_log(WLR_ERROR, "import_gbm_bo failed");
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fb_id = get_fb_for_bo(bo, gbm_bo_get_format(bo));
 | 
				
			||||||
 | 
							if (fb_id == 0) {
 | 
				
			||||||
 | 
								wlr_log(WLR_ERROR, "get_fb_for_bo failed");
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	uint32_t fb_id = get_fb_for_bo(bo, plane->drm_format);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (conn->pageflip_pending) {
 | 
						if (conn->pageflip_pending) {
 | 
				
			||||||
		wlr_log(WLR_ERROR, "Skipping pageflip on output '%s'", conn->output.name);
 | 
							wlr_log(WLR_ERROR, "Skipping pageflip on output '%s'", conn->output.name);
 | 
				
			||||||
| 
						 | 
					@ -903,30 +936,7 @@ static bool drm_connector_attach_buffer(struct wlr_output *output,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct gbm_bo *bo = import_gbm_bo(&drm->renderer, &attribs);
 | 
						memcpy(&conn->pending_dmabuf, &attribs, sizeof(attribs));
 | 
				
			||||||
	if (bo == NULL) {
 | 
					 | 
				
			||||||
		wlr_log(WLR_ERROR, "import_gbm_bo failed");
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	uint32_t fb_id = get_fb_for_bo(bo, gbm_bo_get_format(bo));
 | 
					 | 
				
			||||||
	if (fb_id == 0) {
 | 
					 | 
				
			||||||
		wlr_log(WLR_ERROR, "get_fb_for_bo failed");
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (conn->pageflip_pending) {
 | 
					 | 
				
			||||||
		wlr_log(WLR_ERROR, "Skipping pageflip on output '%s'", conn->output.name);
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) {
 | 
					 | 
				
			||||||
		wlr_log(WLR_ERROR, "crtc_pageflip failed");
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	conn->pageflip_pending = true;
 | 
					 | 
				
			||||||
	wlr_output_update_enabled(output, true);
 | 
					 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,6 +148,8 @@ struct wlr_drm_connector {
 | 
				
			||||||
	bool pageflip_pending;
 | 
						bool pageflip_pending;
 | 
				
			||||||
	struct wl_event_source *retry_pageflip;
 | 
						struct wl_event_source *retry_pageflip;
 | 
				
			||||||
	struct wl_list link;
 | 
						struct wl_list link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_dmabuf_attributes pending_dmabuf;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_drm_backend *get_drm_backend_from_backend(
 | 
					struct wlr_drm_backend *get_drm_backend_from_backend(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,12 +52,21 @@ enum wlr_output_state_field {
 | 
				
			||||||
	WLR_OUTPUT_STATE_DAMAGE = 1 << 1,
 | 
						WLR_OUTPUT_STATE_DAMAGE = 1 << 1,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum wlr_output_state_buffer_type {
 | 
				
			||||||
 | 
						WLR_OUTPUT_STATE_BUFFER_RENDER,
 | 
				
			||||||
 | 
						WLR_OUTPUT_STATE_BUFFER_SCANOUT,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Holds the double-buffered output state.
 | 
					 * Holds the double-buffered output state.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct wlr_output_state {
 | 
					struct wlr_output_state {
 | 
				
			||||||
	uint32_t committed; // enum wlr_output_state_field
 | 
						uint32_t committed; // enum wlr_output_state_field
 | 
				
			||||||
	pixman_region32_t damage; // output-buffer-local coordinates
 | 
						pixman_region32_t damage; // output-buffer-local coordinates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// only valid if WLR_OUTPUT_STATE_BUFFER
 | 
				
			||||||
 | 
						enum wlr_output_state_buffer_type buffer_type;
 | 
				
			||||||
 | 
						struct wlr_buffer *buffer; // if WLR_OUTPUT_STATE_BUFFER_SCANOUT
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_output_impl;
 | 
					struct wlr_output_impl;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -404,6 +404,7 @@ bool wlr_output_attach_render(struct wlr_output *output, int *buffer_age) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	output->pending.committed |= WLR_OUTPUT_STATE_BUFFER;
 | 
						output->pending.committed |= WLR_OUTPUT_STATE_BUFFER;
 | 
				
			||||||
 | 
						output->pending.buffer_type = WLR_OUTPUT_STATE_BUFFER_RENDER;
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -480,15 +481,6 @@ bool wlr_output_commit(struct wlr_output *output) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool wlr_output_attach_buffer(struct wlr_output *output,
 | 
					bool wlr_output_attach_buffer(struct wlr_output *output,
 | 
				
			||||||
		struct wlr_buffer *buffer) {
 | 
							struct wlr_buffer *buffer) {
 | 
				
			||||||
	if (output->frame_pending) {
 | 
					 | 
				
			||||||
		wlr_log(WLR_ERROR, "Tried to swap buffers when a frame is pending");
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (output->idle_frame != NULL) {
 | 
					 | 
				
			||||||
		wl_event_source_remove(output->idle_frame);
 | 
					 | 
				
			||||||
		output->idle_frame = NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!output->impl->attach_buffer) {
 | 
						if (!output->impl->attach_buffer) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -496,9 +488,8 @@ bool wlr_output_attach_buffer(struct wlr_output *output,
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	output->frame_pending = true;
 | 
						output->pending.committed |= WLR_OUTPUT_STATE_BUFFER;
 | 
				
			||||||
	output->needs_frame = false;
 | 
						output->pending.buffer_type = WLR_OUTPUT_STATE_BUFFER_SCANOUT;
 | 
				
			||||||
	pixman_region32_clear(&output->damage);
 | 
					 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue