swrast* (gallium, classic): add MESA_copy_sub_buffer support (v3)

This patches add MESA_copy_sub_buffer support to the dri sw loader and
then to gallium state tracker, llvmpipe, softpipe and other bits.

It reuses the dri1 driver extension interface, and it updates the swrast
loader interface for a new putimage which can take a stride.

I've tested this with gnome-shell with a cogl hacked to reenable sub copies
for llvmpipe and the one piglit test.

I could probably split this patch up as well.

v2: pass a pipe_box, to reduce the entrypoints, as per Jose's review,
add to p_screen doc comments.

v3: finish off winsys interfaces, add swrast classic support as well.

Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>

swrast: add support for copy_sub_buffer
This commit is contained in:
Dave Airlie 2013-11-28 11:08:11 +10:00
parent 40070e72d4
commit ba00f2f6f5
41 changed files with 227 additions and 59 deletions

View File

@ -437,7 +437,7 @@ struct __DRIdamageExtensionRec {
* SWRast Loader extension.
*/
#define __DRI_SWRAST_LOADER "DRI_SWRastLoader"
#define __DRI_SWRAST_LOADER_VERSION 1
#define __DRI_SWRAST_LOADER_VERSION 2
struct __DRIswrastLoaderExtensionRec {
__DRIextension base;
@ -461,6 +461,13 @@ struct __DRIswrastLoaderExtensionRec {
void (*getImage)(__DRIdrawable *readable,
int x, int y, int width, int height,
char *data, void *loaderPrivate);
/**
* Put image to drawable
*/
void (*putImage2)(__DRIdrawable *drawable, int op,
int x, int y, int width, int height, int stride,
char *data, void *loaderPrivate);
};
/**

View File

@ -115,7 +115,7 @@ static void
vl_dri2_flush_frontbuffer(struct pipe_screen *screen,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *context_private)
void *context_private, struct pipe_box *sub_box)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen*)context_private;
uint32_t msc_hi, msc_lo;

View File

@ -275,7 +275,8 @@ static void
galahad_screen_flush_frontbuffer(struct pipe_screen *_screen,
struct pipe_resource *_resource,
unsigned level, unsigned layer,
void *context_private)
void *context_private,
struct pipe_box *sub_box)
{
struct galahad_screen *glhd_screen = galahad_screen(_screen);
struct galahad_resource *glhd_resource = galahad_resource(_resource);
@ -285,7 +286,7 @@ galahad_screen_flush_frontbuffer(struct pipe_screen *_screen,
screen->flush_frontbuffer(screen,
resource,
level, layer,
context_private);
context_private, sub_box);
}
static void

View File

@ -423,7 +423,8 @@ static void
i915_flush_frontbuffer(struct pipe_screen *screen,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *winsys_drawable_handle)
void *winsys_drawable_handle,
struct pipe_box *sub_box)
{
/* XXX: Dummy right now. */
(void)screen;
@ -431,6 +432,7 @@ i915_flush_frontbuffer(struct pipe_screen *screen,
(void)level;
(void)layer;
(void)winsys_drawable_handle;
(void)sub_box;
}
static void

View File

@ -192,7 +192,8 @@ static void
identity_screen_flush_frontbuffer(struct pipe_screen *_screen,
struct pipe_resource *_resource,
unsigned level, unsigned layer,
void *context_private)
void *context_private,
struct pipe_box *sub_box)
{
struct identity_screen *id_screen = identity_screen(_screen);
struct identity_resource *id_resource = identity_resource(_resource);
@ -202,7 +203,7 @@ identity_screen_flush_frontbuffer(struct pipe_screen *_screen,
screen->flush_frontbuffer(screen,
resource,
level, layer,
context_private);
context_private, sub_box);
}
static void

View File

@ -411,7 +411,8 @@ static void
llvmpipe_flush_frontbuffer(struct pipe_screen *_screen,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *context_private)
void *context_private,
struct pipe_box *sub_box)
{
struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
struct sw_winsys *winsys = screen->winsys;
@ -419,10 +420,9 @@ llvmpipe_flush_frontbuffer(struct pipe_screen *_screen,
assert(texture->dt);
if (texture->dt)
winsys->displaytarget_display(winsys, texture->dt, context_private);
winsys->displaytarget_display(winsys, texture->dt, context_private, sub_box);
}
static void
llvmpipe_destroy_screen( struct pipe_screen *_screen )
{

View File

@ -296,7 +296,7 @@ static struct pipe_context *noop_create_context(struct pipe_screen *screen, void
static void noop_flush_frontbuffer(struct pipe_screen *_screen,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *context_private)
void *context_private, struct pipe_box *box)
{
}

View File

@ -190,7 +190,7 @@ static void
rbug_screen_flush_frontbuffer(struct pipe_screen *_screen,
struct pipe_resource *_resource,
unsigned level, unsigned layer,
void *context_private)
void *context_private, struct pipe_box *sub_box)
{
struct rbug_screen *rb_screen = rbug_screen(_screen);
struct rbug_resource *rb_resource = rbug_resource(_resource);
@ -200,7 +200,7 @@ rbug_screen_flush_frontbuffer(struct pipe_screen *_screen,
screen->flush_frontbuffer(screen,
resource,
level, layer,
context_private);
context_private, sub_box);
}
static void

View File

@ -369,7 +369,8 @@ static void
softpipe_flush_frontbuffer(struct pipe_screen *_screen,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *context_private)
void *context_private,
struct pipe_box *sub_box)
{
struct softpipe_screen *screen = softpipe_screen(_screen);
struct sw_winsys *winsys = screen->winsys;
@ -377,7 +378,7 @@ softpipe_flush_frontbuffer(struct pipe_screen *_screen,
assert(texture->dt);
if (texture->dt)
winsys->displaytarget_display(winsys, texture->dt, context_private);
winsys->displaytarget_display(winsys, texture->dt, context_private, sub_box);
}
static uint64_t

View File

@ -209,7 +209,8 @@ static void
trace_screen_flush_frontbuffer(struct pipe_screen *_screen,
struct pipe_resource *_resource,
unsigned level, unsigned layer,
void *context_private)
void *context_private,
struct pipe_box *sub_box)
{
struct trace_screen *tr_scr = trace_screen(_screen);
struct trace_resource *tr_res = trace_resource(_resource);
@ -226,7 +227,7 @@ trace_screen_flush_frontbuffer(struct pipe_screen *_screen,
trace_dump_arg(ptr, context_private);
*/
screen->flush_frontbuffer(screen, resource, level, layer, context_private);
screen->flush_frontbuffer(screen, resource, level, layer, context_private, sub_box);
trace_dump_call_end();
}

View File

@ -56,6 +56,7 @@ struct pipe_fence_handle;
struct pipe_resource;
struct pipe_surface;
struct pipe_transfer;
struct pipe_box;
/**
@ -181,13 +182,13 @@ struct pipe_screen {
* displayed, eg copy fake frontbuffer.
* \param winsys_drawable_handle an opaque handle that the calling context
* gets out-of-band
* \param subbox an optional sub region to flush
*/
void (*flush_frontbuffer)( struct pipe_screen *screen,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *winsys_drawable_handle );
void *winsys_drawable_handle,
struct pipe_box *subbox );
/** Set ptr = fence, with reference counting */
void (*fence_reference)( struct pipe_screen *screen,

View File

@ -13,6 +13,8 @@ struct drisw_loader_funcs
{
void (*put_image) (struct dri_drawable *dri_drawable,
void *data, unsigned width, unsigned height);
void (*put_image2) (struct dri_drawable *dri_drawable,
void *data, int x, int y, unsigned width, unsigned height, unsigned stride);
};
/**

View File

@ -48,7 +48,7 @@ struct winsys_handle;
struct pipe_screen;
struct pipe_context;
struct pipe_resource;
struct pipe_box;
/**
* Opaque pointer.
@ -129,7 +129,8 @@ struct sw_winsys
void
(*displaytarget_display)( struct sw_winsys *ws,
struct sw_displaytarget *dt,
void *context_private );
void *context_private,
struct pipe_box *box );
void
(*displaytarget_destroy)( struct sw_winsys *ws,

View File

@ -37,6 +37,7 @@
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_box.h"
#include "pipe/p_context.h"
#include "state_tracker/drisw_api.h"
#include "state_tracker/st_context.h"
@ -70,6 +71,18 @@ put_image(__DRIdrawable *dPriv, void *data, unsigned width, unsigned height)
data, dPriv->loaderPrivate);
}
static INLINE void
put_image2(__DRIdrawable *dPriv, void *data, int x, int y,
unsigned width, unsigned height, unsigned stride)
{
__DRIscreen *sPriv = dPriv->driScreenPriv;
const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
x, y, width, height, stride,
data, dPriv->loaderPrivate);
}
static INLINE void
get_image(__DRIdrawable *dPriv, int x, int y, int width, int height, void *data)
{
@ -99,9 +112,19 @@ drisw_put_image(struct dri_drawable *drawable,
put_image(dPriv, data, width, height);
}
static void
drisw_put_image2(struct dri_drawable *drawable,
void *data, int x, int y, unsigned width, unsigned height,
unsigned stride)
{
__DRIdrawable *dPriv = drawable->dPriv;
put_image2(dPriv, data, x, y, width, height, stride);
}
static INLINE void
drisw_present_texture(__DRIdrawable *dPriv,
struct pipe_resource *ptex)
struct pipe_resource *ptex, struct pipe_box *sub_box)
{
struct dri_drawable *drawable = dri_drawable(dPriv);
struct dri_screen *screen = dri_screen(drawable->sPriv);
@ -109,7 +132,7 @@ drisw_present_texture(__DRIdrawable *dPriv,
if (swrast_no_present)
return;
screen->base.screen->flush_frontbuffer(screen->base.screen, ptex, 0, 0, drawable);
screen->base.screen->flush_frontbuffer(screen->base.screen, ptex, 0, 0, drawable, sub_box);
}
static INLINE void
@ -126,7 +149,7 @@ static INLINE void
drisw_copy_to_front(__DRIdrawable * dPriv,
struct pipe_resource *ptex)
{
drisw_present_texture(dPriv, ptex);
drisw_present_texture(dPriv, ptex, NULL);
drisw_invalidate_drawable(dPriv);
}
@ -157,6 +180,30 @@ drisw_swap_buffers(__DRIdrawable *dPriv)
}
}
static void
drisw_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y,
int w, int h)
{
struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv);
struct dri_drawable *drawable = dri_drawable(dPriv);
struct pipe_resource *ptex;
struct pipe_box box;
if (!ctx)
return;
ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
if (ptex) {
if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL])
pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]);
ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL);
u_box_2d(x, dPriv->h - y - h, w, h, &box);
drisw_present_texture(dPriv, ptex, &box);
}
}
static void
drisw_flush_frontbuffer(struct dri_context *ctx,
struct dri_drawable *drawable,
@ -288,7 +335,8 @@ static const __DRIextension *drisw_screen_extensions[] = {
};
static struct drisw_loader_funcs drisw_lf = {
.put_image = drisw_put_image
.put_image = drisw_put_image,
.put_image2 = drisw_put_image2
};
static const __DRIconfig **
@ -359,12 +407,14 @@ const struct __DriverAPIRec driDriverAPI = {
.SwapBuffers = drisw_swap_buffers,
.MakeCurrent = dri_make_current,
.UnbindContext = dri_unbind_context,
.CopySubBuffer = drisw_copy_sub_buffer,
};
/* This is the table of extensions that the loader will dlsym() for. */
PUBLIC const __DRIextension *__driDriverExtensions[] = {
&driCoreExtension.base,
&driSWRastExtension.base,
&driCopySubBufferExtension,
&gallium_config_options.base,
NULL
};

View File

@ -244,7 +244,7 @@ resource_surface_present(struct resource_surface *rsurf,
return TRUE;
rsurf->screen->flush_frontbuffer(rsurf->screen,
pres, 0, 0, winsys_drawable_handle);
pres, 0, 0, winsys_drawable_handle, NULL);
return TRUE;
}

View File

@ -476,7 +476,7 @@ ximage_display_copy_to_pixmap(struct native_display *ndpy,
xdraw.drawable = (Drawable) pix;
xdpy->base.screen->flush_frontbuffer(xdpy->base.screen,
src, 0, 0, &xdraw);
src, 0, 0, &xdraw, NULL);
return TRUE;
}

View File

@ -74,7 +74,7 @@ xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi,
pres = xstfb->display_resource;
}
xstfb->screen->flush_frontbuffer(xstfb->screen, pres, 0, 0, &xstfb->buffer->ws);
xstfb->screen->flush_frontbuffer(xstfb->screen, pres, 0, 0, &xstfb->buffer->ws, NULL);
return TRUE;
}

View File

@ -269,7 +269,7 @@ vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue,
pipe->screen->flush_frontbuffer
(
pipe->screen, tex, 0, 0,
vl_screen_get_private(pq->device->vscreen)
vl_screen_get_private(pq->device->vscreen), NULL
);
pipe->screen->fence_reference(pipe->screen, &surf->fence, NULL);

View File

@ -447,7 +447,7 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
pipe->screen->flush_frontbuffer
(
pipe->screen, tex, 0, 0,
vl_screen_get_private(context_priv->vscreen)
vl_screen_get_private(context_priv->vscreen), NULL
);
if(dump_window == -1) {

View File

@ -504,14 +504,14 @@ GalliumContext::SwapBuffers(context_id contextID)
// We pass our destination bitmap to flush_fronbuffer which passes it
// to the private winsys display call.
fScreen->flush_frontbuffer(fScreen, surface->texture, 0, 0,
context->bitmap);
context->bitmap, NULL);
}
#if 0
// TODO... should we flush the z stencil buffer?
pipe_surface* zSurface = stContext->state.framebuffer.zsbuf;
fScreen->flush_frontbuffer(fScreen, zSurface->texture, 0, 0,
context->bitmap);
context->bitmap, NULL);
#endif
return B_OK;

View File

@ -33,7 +33,7 @@ static void draw( void )
graw_save_surface_to_file(ctx, surf, NULL);
screen->flush_frontbuffer(screen, tex, 0, 0, window);
screen->flush_frontbuffer(screen, tex, 0, 0, window, NULL);
}
static void init( void )

View File

@ -240,7 +240,7 @@ static void draw( void )
graw_save_surface_to_file(ctx, surf, NULL);
screen->flush_frontbuffer(screen, rttex, 0, 0, window);
screen->flush_frontbuffer(screen, rttex, 0, 0, window, NULL);
}
#define SIZE 16

View File

@ -211,7 +211,7 @@ static INLINE void
graw_util_flush_front(const struct graw_info *info)
{
info->screen->flush_frontbuffer(info->screen, info->color_buf[0],
0, 0, info->window);
0, 0, info->window, NULL);
}

View File

@ -347,7 +347,7 @@ static void draw( void )
graw_save_surface_to_file(ctx, surf, NULL);
screen->flush_frontbuffer(screen, rttex, 0, 0, window);
screen->flush_frontbuffer(screen, rttex, 0, 0, window, NULL);
}
#define SIZE 16

View File

@ -156,7 +156,7 @@ static void draw( void )
graw_save_surface_to_file(ctx, surf, NULL);
screen->flush_frontbuffer(screen, rttex, 0, 0, window);
screen->flush_frontbuffer(screen, rttex, 0, 0, window, NULL);
}
#define SIZE 16

View File

@ -158,7 +158,7 @@ static void draw( void )
ctx->delete_fs_state(ctx, fs);
}
screen->flush_frontbuffer(screen, tex, 0, 0, window);
screen->flush_frontbuffer(screen, tex, 0, 0, window, NULL);
ctx->destroy(ctx);
exit(0);

View File

@ -168,7 +168,7 @@ static void draw( void )
util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
ctx->flush(ctx, NULL, 0);
screen->flush_frontbuffer(screen, tex, 0, 0, window);
screen->flush_frontbuffer(screen, tex, 0, 0, window, NULL);
}

View File

@ -219,7 +219,7 @@ static void draw( void )
graw_save_surface_to_file(ctx, surf, NULL);
screen->flush_frontbuffer(screen, tex, 0, 0, window);
screen->flush_frontbuffer(screen, tex, 0, 0, window, NULL);
}

View File

@ -234,7 +234,7 @@ static void draw( void )
graw_save_surface_to_file(ctx, surf, NULL);
screen->flush_frontbuffer(screen, rttex, 0, 0, window);
screen->flush_frontbuffer(screen, rttex, 0, 0, window, NULL);
}
#define SIZE 16

View File

@ -74,7 +74,8 @@ namespace android {
static void
android_displaytarget_display(struct sw_winsys *ws,
struct sw_displaytarget *dt,
void *context_private)
void *context_private,
struct pipe_box *box)
{
}

View File

@ -166,25 +166,33 @@ dri_sw_displaytarget_get_handle(struct sw_winsys *winsys,
static void
dri_sw_displaytarget_display(struct sw_winsys *ws,
struct sw_displaytarget *dt,
void *context_private)
void *context_private,
struct pipe_box *box)
{
struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
struct dri_drawable *dri_drawable = (struct dri_drawable *)context_private;
unsigned width, height;
unsigned blsize = util_format_get_blocksize(dri_sw_dt->format);
/* Set the width to 'stride / cpp'.
*
* PutImage correctly clips to the width of the dst drawable.
*/
width = dri_sw_dt->stride / util_format_get_blocksize(dri_sw_dt->format);
width = dri_sw_dt->stride / blsize;
height = dri_sw_dt->height;
dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height);
if (box) {
void *data;
data = dri_sw_dt->data + (dri_sw_dt->stride * box->y) + box->x * blsize;
dri_sw_ws->lf->put_image2(dri_drawable, data,
box->x, box->y, box->width, box->height, dri_sw_dt->stride);
} else {
dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height);
}
}
static void
dri_destroy_sw_winsys(struct sw_winsys *winsys)
{

View File

@ -74,7 +74,8 @@ fbdev_sw_winsys(struct sw_winsys *ws)
static void
fbdev_displaytarget_display(struct sw_winsys *ws,
struct sw_displaytarget *dt,
void *winsys_private)
void *winsys_private,
struct pipe_box *box)
{
struct fbdev_sw_winsys *fbdev = fbdev_sw_winsys(ws);
struct fbdev_sw_displaytarget *src = fbdev_sw_displaytarget(dt);

View File

@ -207,7 +207,8 @@ gdi_sw_display( struct sw_winsys *winsys,
static void
gdi_sw_displaytarget_display(struct sw_winsys *winsys,
struct sw_displaytarget *dt,
void *context_private)
void *context_private,
struct pipe_box *box)
{
/* nasty:
*/

View File

@ -160,7 +160,8 @@ hgl_winsys_displaytarget_unmap(struct sw_winsys* winsys,
static void
hgl_winsys_displaytarget_display(struct sw_winsys* winsys,
struct sw_displaytarget* displayTarget, void* contextPrivate)
struct sw_displaytarget* displayTarget, void* contextPrivate,
struct pipe_box *box)
{
assert(contextPrivate);

View File

@ -114,7 +114,8 @@ null_sw_displaytarget_get_handle(struct sw_winsys *winsys,
static void
null_sw_displaytarget_display(struct sw_winsys *winsys,
struct sw_displaytarget *dt,
void *context_private)
void *context_private,
struct pipe_box *box)
{
assert(0);
}

View File

@ -75,7 +75,8 @@ wayland_sw_winsys(struct sw_winsys *ws)
static void
wayland_displaytarget_display(struct sw_winsys *ws,
struct sw_displaytarget *dt,
void *context_private)
void *context_private,
struct pipe_box *box)
{
}

View File

@ -376,7 +376,8 @@ xlib_sw_display(struct xlib_drawable *xlib_drawable,
static void
xlib_displaytarget_display(struct sw_winsys *ws,
struct sw_displaytarget *dt,
void *context_private)
void *context_private,
struct pipe_box *box)
{
struct xlib_drawable *xlib_drawable = (struct xlib_drawable *)context_private;
xlib_sw_display(xlib_drawable, dt);

View File

@ -49,6 +49,7 @@ struct drisw_screen
const __DRIcoreExtension *core;
const __DRIswrastExtension *swrast;
const __DRItexBufferExtension *texBuffer;
const __DRIcopySubBufferExtension *copySubBuffer;
const __DRIconfig **driver_configs;
@ -171,9 +172,9 @@ bytes_per_line(unsigned pitch_bits, unsigned mul)
}
static void
swrastPutImage(__DRIdrawable * draw, int op,
int x, int y, int w, int h,
char *data, void *loaderPrivate)
swrastPutImage2(__DRIdrawable * draw, int op,
int x, int y, int w, int h, int stride,
char *data, void *loaderPrivate)
{
struct drisw_drawable *pdp = loaderPrivate;
__GLXDRIdrawable *pdraw = &(pdp->base);
@ -199,13 +200,21 @@ swrastPutImage(__DRIdrawable * draw, int op,
ximage->data = data;
ximage->width = w;
ximage->height = h;
ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32);
ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
XPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h);
ximage->data = NULL;
}
static void
swrastPutImage(__DRIdrawable * draw, int op,
int x, int y, int w, int h,
char *data, void *loaderPrivate)
{
swrastPutImage2(draw, op, x, y, w, h, 0, data, loaderPrivate);
}
static void
swrastGetImage(__DRIdrawable * read,
int x, int y, int w, int h,
@ -234,7 +243,8 @@ static const __DRIswrastLoaderExtension swrastLoaderExtension = {
{__DRI_SWRAST_LOADER, __DRI_SWRAST_LOADER_VERSION},
swrastGetDrawableInfo,
swrastPutImage,
swrastGetImage
swrastGetImage,
swrastPutImage2,
};
static const __DRIextension *loader_extensions[] = {
@ -584,6 +594,21 @@ driswSwapBuffers(__GLXDRIdrawable * pdraw,
return 0;
}
static void
driswCopySubBuffer(__GLXDRIdrawable * pdraw,
int x, int y, int width, int height, Bool flush)
{
struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
if (flush) {
glFlush();
}
(*psc->copySubBuffer->copySubBuffer) (pdp->driDrawable,
x, y, width, height);
}
static void
driswDestroyScreen(struct glx_screen *base)
{
@ -632,6 +657,9 @@ driswBindExtensions(struct drisw_screen *psc, const __DRIextension **extensions)
"GLX_EXT_create_context_es2_profile");
}
if (psc->copySubBuffer)
__glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
/* FIXME: Figure out what other extensions can be ported here from dri2. */
for (i = 0; extensions[i]; i++) {
if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
@ -673,6 +701,8 @@ driswCreateScreen(int screen, struct glx_display *priv)
psc->core = (__DRIcoreExtension *) extensions[i];
if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0)
psc->swrast = (__DRIswrastExtension *) extensions[i];
if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0)
psc->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
}
if (psc->core == NULL || psc->swrast == NULL) {
@ -718,6 +748,9 @@ driswCreateScreen(int screen, struct glx_display *priv)
psp->createDrawable = driswCreateDrawable;
psp->swapBuffers = driswSwapBuffers;
if (psc->copySubBuffer)
psp->copySubBuffer = driswCopySubBuffer;
return &psc->base;
handle_error:

View File

@ -873,3 +873,18 @@ const __DRIimageDriverExtension driImageDriverExtension = {
.getAPIMask = driGetAPIMask,
.createContextAttribs = driCreateContextAttribs,
};
/* swrast copy sub buffer entrypoint. */
static void driCopySubBuffer(__DRIdrawable *pdp, int x, int y,
int w, int h)
{
assert(pdp->driScreenPriv->swrast_loader);
pdp->driScreenPriv->driver->CopySubBuffer(pdp, x, y, w, h);
}
/* for swrast only */
const __DRIcopySubBufferExtension driCopySubBufferExtension = {
{ __DRI_COPY_SUB_BUFFER, 1 },
.copySubBuffer = driCopySubBuffer,
};

View File

@ -66,7 +66,7 @@ extern const __DRIcoreExtension driCoreExtension;
extern const __DRIswrastExtension driSWRastExtension;
extern const __DRIdri2Extension driDRI2Extension;
extern const __DRI2configQueryExtension dri2ConfigQueryExtension;
extern const __DRIcopySubBufferExtension driCopySubBufferExtension;
/**
* Driver callback functions.
*
@ -115,6 +115,9 @@ struct __DriverAPIRec {
int width, int height);
void (*ReleaseBuffer) (__DRIscreen *screenPrivate, __DRIbuffer *buffer);
void (*CopySubBuffer)(__DRIdrawable *driDrawPriv, int x, int y,
int w, int h);
};
extern const struct __DriverAPIRec driDriverAPI;

View File

@ -820,6 +820,39 @@ dri_unbind_context(__DRIcontext * cPriv)
return GL_TRUE;
}
static void
dri_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y,
int w, int h)
{
__DRIscreen *sPriv = dPriv->driScreenPriv;
void *data;
int iy;
struct dri_drawable *drawable = dri_drawable(dPriv);
struct gl_framebuffer *fb;
struct dri_swrast_renderbuffer *frontrb, *backrb;
TRACE;
fb = &drawable->Base;
frontrb =
dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
backrb =
dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
/* check for signle-buffered */
if (backrb == NULL)
return;
iy = frontrb->Base.Base.Height - y - h;
data = (char *)backrb->Base.Buffer + (iy * backrb->pitch) + (x * ((backrb->bpp + 7) / 8));
sPriv->swrast_loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
x, iy, w, h,
frontrb->pitch,
data,
dPriv->loaderPrivate);
}
static const struct __DriverAPIRec swrast_driver_api = {
.InitScreen = dri_init_screen,
@ -831,6 +864,7 @@ static const struct __DriverAPIRec swrast_driver_api = {
.SwapBuffers = dri_swap_buffers,
.MakeCurrent = dri_make_current,
.UnbindContext = dri_unbind_context,
.CopySubBuffer = dri_copy_sub_buffer,
};
static const struct __DRIDriverVtableExtensionRec swrast_vtable = {
@ -841,6 +875,7 @@ static const struct __DRIDriverVtableExtensionRec swrast_vtable = {
static const __DRIextension *swrast_driver_extensions[] = {
&driCoreExtension.base,
&driSWRastExtension.base,
&driCopySubBufferExtension.base,
&swrast_vtable.base,
NULL
};