/** * Check that a framebuffer's attachments match the window's size. * * Called via st_framebuffer_iface::validate() * * \param statts array of framebuffer attachments * \param count number of framebuffer attachments in statts[] * \param out returns resources for each of the attachments */ static boolean xmesa_st_framebuffer_validate(struct st_context_iface *stctx, struct st_framebuffer_iface *stfbi, const enum st_attachment_type *statts, unsigned count, struct pipe_resource **out) { struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); unsigned statt_mask, new_mask, i; boolean resized; boolean ret; /* build mask of ST_ATTACHMENT bits */ statt_mask = 0x0; for (i = 0; i < count; i++) statt_mask |= 1 << statts[i]; /* record newly allocated textures */ new_mask = statt_mask & ~xstfb->texture_mask; /* If xmesa_strict_invalidate is not set, we will not yet have * called XGetGeometry(). Do so here: */ if (!xmesa_strict_invalidate) xmesa_check_buffer_size(xstfb->buffer); resized = (xstfb->buffer->width != xstfb->texture_width || xstfb->buffer->height != xstfb->texture_height); /* revalidate textures */ if (resized || new_mask) { ret = xmesa_st_framebuffer_validate_textures(stfbi, xstfb->buffer->width, xstfb->buffer->height, statt_mask); if (!ret) return ret; if (!resized) { enum st_attachment_type back, front; back = ST_ATTACHMENT_BACK_LEFT; front = ST_ATTACHMENT_FRONT_LEFT; /* copy the contents if front is newly allocated and back is not */ if ((statt_mask & (1 << back)) && (new_mask & (1 << front)) && !(new_mask & (1 << back))) { xmesa_st_framebuffer_copy_textures(stfbi, back, front, 0, 0, xstfb->texture_width, xstfb->texture_height); } } } for (i = 0; i < count; i++) { out[i] = NULL; pipe_resource_reference(&out[i], xstfb->textures[statts[i]]); } return TRUE; }
PUBLIC void XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer, const int *attrib_list) { struct st_context_iface *st = stapi->get_current(stapi); struct st_framebuffer_iface* stfbi = drawable->stfb; struct pipe_resource *res; int x, y, w, h; enum st_attachment_type st_attachment = xmesa_attachment_type(buffer); x = 0; y = 0; w = drawable->width; h = drawable->height; /* We need to validate our attachments before using them, * in case the texture doesn't exist yet. */ xmesa_st_framebuffer_validate_textures(stfbi, w, h, 1 << st_attachment); res = xmesa_get_attachment(stfbi, st_attachment); if (res) { struct pipe_context* pipe = xmesa_get_context(stfbi); enum pipe_format internal_format = res->format; struct pipe_transfer *tex_xfer; char *map; int line, ximage_stride; XImage *img; internal_format = choose_pixel_format(drawable->xm_visual); tex_xfer = pipe_get_transfer(pipe, res, 0, 0, /* level, layer */ PIPE_TRANSFER_WRITE, x, y, w, h); if (!tex_xfer) return; /* Grab the XImage that we want to turn into a texture. */ img = XGetImage(dpy, drawable->ws.drawable, x, y, w, h, AllPlanes, ZPixmap); if (!img) { pipe_transfer_destroy(pipe, tex_xfer); return; } map = pipe_transfer_map(pipe, tex_xfer); if (!map) { pipe_transfer_destroy(pipe, tex_xfer); return; } /* The pipe transfer has a pitch rounded up to the nearest 64 pixels. We assume 32 bit pixels. */ ximage_stride = w * 4; for (line = 0; line < h; line++) memcpy(&map[line * tex_xfer->stride], &img->data[line * ximage_stride], ximage_stride); pipe_transfer_unmap(pipe, tex_xfer); pipe_transfer_destroy(pipe, tex_xfer); st->teximage(st, ST_TEXTURE_2D, 0, /* level */ internal_format, res, FALSE /* no mipmap */); } }