static boolean dri2_surface_flush_frontbuffer(struct native_surface *nsurf) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; struct native_display *ndpy = &dri2dpy->base; struct pipe_context *pipe = ndpy_get_copy_context(ndpy); /* flush buffer */ pipe->flush_resource(pipe, dri2surf->textures[NATIVE_ATTACHMENT_FRONT_LEFT]); pipe->flush(pipe, NULL, 0); /* copy to real front buffer */ if (dri2surf->have_fake) x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 0, 0, dri2surf->width, dri2surf->height, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); /* force buffers to be updated in next validation call */ if (!dri2_surface_receive_events(&dri2surf->base)) { dri2surf->server_stamp++; dri2dpy->event_handler->invalid_surface(&dri2dpy->base, &dri2surf->base, dri2surf->server_stamp); } return TRUE; }
static boolean dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height) { struct dri2_surface *dri2surf = dri2_surface(nsurf); if (dri2surf->server_stamp != dri2surf->client_stamp || (dri2surf->valid_mask & attachment_mask) != attachment_mask) { if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask)) return FALSE; } if (seq_num) *seq_num = dri2surf->client_stamp; if (textures) { int att; for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { if (native_attachment_mask_test(attachment_mask, att)) { struct pipe_resource *ptex = dri2surf->textures[att]; textures[att] = NULL; pipe_resource_reference(&textures[att], ptex); } } } if (width) *width = dri2surf->width; if (height) *height = dri2surf->height; return TRUE; }
/** * Update the buffers of the surface. This is a slow function due to the * round-trip to the server. */ static boolean dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) { struct dri2_surface *dri2surf = dri2_surface(nsurf); dri2_surface_get_buffers(&dri2surf->base, buffer_mask); return ((dri2surf->valid_mask & buffer_mask) == buffer_mask); }
static void dri2_surface_wait(struct native_surface *nsurf) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; if (dri2surf->have_fake) { x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 0, 0, dri2surf->width, dri2surf->height, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); } }
static boolean dri2_surface_swap_buffers(struct native_surface *nsurf, int num_rects, const int *rects) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; struct native_display *ndpy = &dri2dpy->base; struct pipe_context *pipe = ndpy_get_copy_context(ndpy); /* copy to front buffer */ if (dri2surf->have_back) { pipe->flush_resource(pipe, dri2surf->textures[NATIVE_ATTACHMENT_BACK_LEFT]); pipe->flush(pipe, NULL, 0); if (num_rects > 0) x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable, num_rects, rects, DRI2BufferBackLeft, DRI2BufferFrontLeft); else x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 0, 0, dri2surf->width, dri2surf->height, DRI2BufferBackLeft, DRI2BufferFrontLeft); } /* and update fake front buffer */ if (dri2surf->have_fake) { if (num_rects > 0) x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable, num_rects, rects, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); else x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 0, 0, dri2surf->width, dri2surf->height, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); } /* force buffers to be updated in next validation call */ if (!dri2_surface_receive_events(&dri2surf->base)) { dri2surf->server_stamp++; dri2dpy->event_handler->invalid_surface(&dri2dpy->base, &dri2surf->base, dri2surf->server_stamp); } return TRUE; }
static void dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable, void *user_data) { struct native_display *ndpy = (struct native_display* ) user_data; struct dri2_display *dri2dpy = dri2_display(ndpy); struct native_surface *nsurf; struct dri2_surface *dri2surf; nsurf = (struct native_surface *) util_hash_table_get(dri2dpy->surfaces, (void *) drawable); if (!nsurf) return; dri2surf = dri2_surface(nsurf); dri2surf->server_stamp++; dri2dpy->event_handler->invalid_surface(&dri2dpy->base, &dri2surf->base, dri2surf->server_stamp); }
static boolean dri2_surface_flush_frontbuffer(struct native_surface *nsurf) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; /* copy to real front buffer */ if (dri2surf->have_fake) x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 0, 0, dri2surf->width, dri2surf->height, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); /* force buffers to be updated in next validation call */ if (!dri2_surface_receive_events(&dri2surf->base)) { dri2surf->server_stamp++; dri2dpy->event_handler->invalid_surface(&dri2dpy->base, &dri2surf->base, dri2surf->server_stamp); } return TRUE; }
static boolean dri2_surface_swap_buffers(struct native_surface *nsurf, int num_rects, const int *rects) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; /* copy to front buffer */ if (dri2surf->have_back) { if (num_rects > 0) x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable, num_rects, rects, DRI2BufferBackLeft, DRI2BufferFrontLeft); else x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 0, 0, dri2surf->width, dri2surf->height, DRI2BufferBackLeft, DRI2BufferFrontLeft); } /* and update fake front buffer */ if (dri2surf->have_fake) { if (num_rects > 0) x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable, num_rects, rects, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); else x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 0, 0, dri2surf->width, dri2surf->height, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); } /* force buffers to be updated in next validation call */ if (!dri2_surface_receive_events(&dri2surf->base)) { dri2surf->server_stamp++; dri2dpy->event_handler->invalid_surface(&dri2dpy->base, &dri2surf->base, dri2surf->server_stamp); } return TRUE; }
static void dri2_surface_destroy(struct native_surface *nsurf) { struct dri2_surface *dri2surf = dri2_surface(nsurf); int i; FREE(dri2surf->last_xbufs); for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { struct pipe_resource *ptex = dri2surf->textures[i]; pipe_resource_reference(&ptex, NULL); } if (dri2surf->drawable) { x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr, dri2surf->drawable, FALSE); util_hash_table_remove(dri2surf->dri2dpy->surfaces, (void *) dri2surf->drawable); } FREE(dri2surf); }
/** * Return TRUE if the surface receives DRI2_InvalidateBuffers events. */ static INLINE boolean dri2_surface_receive_events(struct native_surface *nsurf) { struct dri2_surface *dri2surf = dri2_surface(nsurf); return (dri2surf->dri2dpy->dri_minor >= 3); }
/** * Get the buffers from the server. */ static void dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS * 2]; int num_ins, num_outs, att; struct x11_drawable_buffer *xbufs; uint bpp = util_format_get_blocksizebits(dri2surf->color_format); boolean with_format = FALSE; /* never ask for depth/stencil */ /* We must get the front on servers which doesn't support with format * due to a silly bug in core dri2. You can't copy to/from a buffer * that you haven't requested and you recive BadValue errors */ if (dri2surf->dri2dpy->dri_minor < 1) { with_format = FALSE; buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT); } /* prepare the attachments */ num_ins = 0; for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { if (native_attachment_mask_test(buffer_mask, att)) { unsigned int dri2att; switch (att) { case NATIVE_ATTACHMENT_FRONT_LEFT: dri2att = DRI2BufferFrontLeft; break; case NATIVE_ATTACHMENT_BACK_LEFT: dri2att = DRI2BufferBackLeft; break; case NATIVE_ATTACHMENT_FRONT_RIGHT: dri2att = DRI2BufferFrontRight; break; case NATIVE_ATTACHMENT_BACK_RIGHT: dri2att = DRI2BufferBackRight; break; default: assert(0); dri2att = 0; break; } dri2atts[num_ins++] = dri2att; if (with_format) dri2atts[num_ins++] = bpp; } } if (with_format) num_ins /= 2; xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable, &dri2surf->width, &dri2surf->height, dri2atts, with_format, num_ins, &num_outs); /* we should be able to do better... */ if (xbufs && dri2surf->last_num_xbufs == num_outs && memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) { FREE(xbufs); dri2surf->client_stamp = dri2surf->server_stamp; return; } dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs); dri2surf->server_stamp++; dri2surf->client_stamp = dri2surf->server_stamp; FREE(dri2surf->last_xbufs); dri2surf->last_xbufs = xbufs; dri2surf->last_num_xbufs = num_outs; }
/** * Process the buffers returned by the server. */ static void dri2_surface_process_drawable_buffers(struct native_surface *nsurf, struct x11_drawable_buffer *xbufs, int num_xbufs) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; struct pipe_resource templ; struct winsys_handle whandle; uint valid_mask; int i; /* free the old textures */ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) pipe_resource_reference(&dri2surf->textures[i], NULL); dri2surf->valid_mask = 0x0; dri2surf->have_back = FALSE; dri2surf->have_fake = FALSE; if (!xbufs) return; memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_2D; templ.last_level = 0; templ.width0 = dri2surf->width; templ.height0 = dri2surf->height; templ.depth0 = 1; templ.array_size = 1; templ.format = dri2surf->color_format; templ.bind = PIPE_BIND_RENDER_TARGET; valid_mask = 0x0; for (i = 0; i < num_xbufs; i++) { struct x11_drawable_buffer *xbuf = &xbufs[i]; const char *desc; enum native_attachment natt; switch (xbuf->attachment) { case DRI2BufferFrontLeft: natt = NATIVE_ATTACHMENT_FRONT_LEFT; desc = "DRI2 Front Buffer"; break; case DRI2BufferFakeFrontLeft: natt = NATIVE_ATTACHMENT_FRONT_LEFT; desc = "DRI2 Fake Front Buffer"; dri2surf->have_fake = TRUE; break; case DRI2BufferBackLeft: natt = NATIVE_ATTACHMENT_BACK_LEFT; desc = "DRI2 Back Buffer"; dri2surf->have_back = TRUE; break; default: desc = NULL; break; } if (!desc || dri2surf->textures[natt]) { if (!desc) _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment); else _eglLog(_EGL_WARNING, "both real and fake front buffers are listed"); continue; } memset(&whandle, 0, sizeof(whandle)); whandle.stride = xbuf->pitch; whandle.handle = xbuf->name; dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle( dri2dpy->base.screen, &templ, &whandle); if (dri2surf->textures[natt]) valid_mask |= 1 << natt; } dri2surf->valid_mask = valid_mask; }