diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/state_trackers/xorg/xorg_dri2.c | 72 |
1 files changed, 43 insertions, 29 deletions
diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c index 301e5214e3..3fbab4dc51 100644 --- a/src/gallium/state_trackers/xorg/xorg_dri2.c +++ b/src/gallium/state_trackers/xorg/xorg_dri2.c @@ -45,6 +45,7 @@ typedef struct { PixmapPtr pPixmap; struct pipe_texture *tex; struct pipe_buffer *buf; + struct pipe_fence_handle *fence; } *BufferPrivatePtr; static DRI2BufferPtr @@ -97,17 +98,11 @@ driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count) tex = ms->screen->texture_create(ms->screen, &template); depth = tex; } else { - struct pipe_texture template; - memset(&template, 0, sizeof(template)); - template.target = PIPE_TEXTURE_2D; - template.format = PIPE_FORMAT_A8R8G8B8_UNORM; - pf_get_block(template.format, &template.block); - template.width[0] = pDraw->width; - template.height[0] = pDraw->height; - template.depth[0] = 1; - template.last_level = 0; - template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - tex = ms->screen->texture_create(ms->screen, &template); + pPixmap = (*pScreen->CreatePixmap)(pScreen, pDraw->width, + pDraw->height, + pDraw->depth, + 0); + tex = xorg_exa_get_texture(pPixmap); } if (!tex) @@ -148,11 +143,12 @@ driDestroyBuffers(DrawablePtr pDraw, DRI2BufferPtr buffers, int count) for (i = 0; i < count; i++) { private = buffers[i].driverPrivate; - if (private->pPixmap) - (*pScreen->DestroyPixmap)(private->pPixmap); - pipe_texture_reference(&private->tex, NULL); pipe_buffer_reference(&private->buf, NULL); + ms->screen->fence_reference(ms->screen, &private->fence, NULL); + + if (private->pPixmap) + (*pScreen->DestroyPixmap)(private->pPixmap); } if (buffers) { @@ -170,24 +166,42 @@ driCopyRegion(DrawablePtr pDraw, RegionPtr pRegion, modesettingPtr ms = modesettingPTR(pScrn); BufferPrivatePtr dst_priv = pDestBuffer->driverPrivate; BufferPrivatePtr src_priv = pSrcBuffer->driverPrivate; + PixmapPtr src_pixmap; + PixmapPtr dst_pixmap; + GCPtr gc; + RegionPtr copy_clip; + + src_pixmap = src_priv->pPixmap; + dst_pixmap = dst_priv->pPixmap; + if (pSrcBuffer->attachment == DRI2BufferFrontLeft) + src_pixmap = (PixmapPtr)pDraw; + if (pDestBuffer->attachment == DRI2BufferFrontLeft) + dst_pixmap = (PixmapPtr)pDraw; + gc = GetScratchGC(pDraw->depth, pScreen); + copy_clip = REGION_CREATE(pScreen, NULL, 0); + REGION_COPY(pScreen, copy_clip, pRegion); + (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0); + ValidateGC(&dst_pixmap->drawable, gc); + + /* If this is a full buffer swap, throttle on the previous one */ + if (dst_priv->fence && REGION_NUM_RECTS(pRegion) == 1) { + BoxPtr extents = REGION_EXTENTS(pScreen, pRegion); + + if (extents->x1 == 0 && extents->y1 == 0 && + extents->x2 == pDraw->width && extents->y2 == pDraw->height) { + ms->screen->fence_finish(ms->screen, dst_priv->fence, 0); + ms->screen->fence_reference(ms->screen, &dst_priv->fence, NULL); + } + } - struct pipe_surface *dst_surf = - ms->screen->get_tex_surface(ms->screen, dst_priv->tex, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); - struct pipe_surface *src_surf = - ms->screen->get_tex_surface(ms->screen, src_priv->tex, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ); + (*gc->ops->CopyArea)(&src_pixmap->drawable, &dst_pixmap->drawable, gc, + 0, 0, pDraw->width, pDraw->height, 0, 0); -#if 1 - ms->ctx->surface_copy(ms->ctx, dst_surf, 0, 0, src_surf, - 0, 0, pDraw->width, pDraw->height); -#else - util_surface_copy(ms->ctx, false, dst_surf, 0, 0, src_surf, - 0, 0, pDraw->width, pDraw->height); -#endif + FreeScratchGC(gc); - pipe_surface_reference(&dst_surf, NULL); - pipe_surface_reference(&src_surf, NULL); + ms->ctx->flush(ms->ctx, PIPE_FLUSH_SWAPBUFFERS, + pDestBuffer->attachment == DRI2BufferFrontLeft ? + &dst_priv->fence : NULL); } Bool |