This series has a bunch of DRI3 cleanups and fixes followed by a few patches that finish up DRI3 support in gallium.
The first two patches have nothing to do with DRI3, just some warning fixes:
[PATCH 01/18] Remove glBlendColor and glBlendEquations decls from [PATCH 02/18] dri/swrast: Passing dri_context * instead of
DRI3 cleanups
[PATCH 03/18] Don't use libudev for glx/dri3 [PATCH 04/18] dri3: Switch to libxshmfence version 1.1 [PATCH 05/18] dri3: Free resources when drawable is destroyed. [PATCH 06/18] dri3: Clean up struct dri3_drawable [PATCH 07/18] dri3: Track full 64-bit SBC numbers, instead of just [PATCH 08/18] dri3: Fix dri3_wait_for_sbc to wait for completion of [PATCH 09/18] dri3: Enable GLX_INTEL_swap_event [PATCH 10/18] i965: Correct check for re-bound buffer in [PATCH 11/18] i965: Set fast color clear mcs_state on newly allocated [PATCH 12/18] dri3: Rename DRI3_MAX_BACK to DRI3_NUM_BACK [PATCH 13/18] dri3: Flush XCB before blocking for special events [PATCH 14/18] dri3, i915, i965: Add __DRI_IMAGE_FOURCC_SARGB8888
And the gallium patches: The middle two are from Ben Skeggs, but haven't been reviewed and not in an area of the code I feel comfortable reviewing.
[PATCH 15/18] gallium: Add __DRIimageDriverExtension support to [PATCH 16/18] gallium/dri: fix unsetting of format when encountering [PATCH 17/18] nvc0: fix segfault if nv50_miptree_from_handle() fails [PATCH 18/18] gallium: Use base.stamp for all drawable invalidation
These are duplicates from gl.h; I'm not sure which file they belong in, but you don't get to have them in both places.
Signed-off-by: Keith Packard keithp@keithp.com --- include/GL/glext.h | 2 -- 1 file changed, 2 deletions(-)
diff --git a/include/GL/glext.h b/include/GL/glext.h index 7d6033e..b432d2e 100644 --- a/include/GL/glext.h +++ b/include/GL/glext.h @@ -457,8 +457,6 @@ GLAPI void APIENTRY glWindowPos3i (GLint x, GLint y, GLint z); GLAPI void APIENTRY glWindowPos3iv (const GLint *v); GLAPI void APIENTRY glWindowPos3s (GLshort x, GLshort y, GLshort z); GLAPI void APIENTRY glWindowPos3sv (const GLshort *v); -GLAPI void APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GLAPI void APIENTRY glBlendEquation (GLenum mode); #endif #endif /* GL_VERSION_1_4 */
On 12/13/2013 05:25 PM, Keith Packard wrote:
These are duplicates from gl.h; I'm not sure which file they belong in, but you don't get to have them in both places.
Signed-off-by: Keith Packard keithp@keithp.com
include/GL/glext.h | 2 -- 1 file changed, 2 deletions(-)
diff --git a/include/GL/glext.h b/include/GL/glext.h index 7d6033e..b432d2e 100644 --- a/include/GL/glext.h +++ b/include/GL/glext.h @@ -457,8 +457,6 @@ GLAPI void APIENTRY glWindowPos3i (GLint x, GLint y, GLint z); GLAPI void APIENTRY glWindowPos3iv (const GLint *v); GLAPI void APIENTRY glWindowPos3s (GLshort x, GLshort y, GLshort z); GLAPI void APIENTRY glWindowPos3sv (const GLshort *v); -GLAPI void APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GLAPI void APIENTRY glBlendEquation (GLenum mode); #endif #endif /* GL_VERSION_1_4 */
NAK. These headers come directly from Khronos; we need to somehow get this fixed upstream and take their version.
--Ken
Kenneth Graunke kenneth@whitecape.org writes:
NAK. These headers come directly from Khronos; we need to somehow get this fixed upstream and take their version.
Until they're fixed upstream, we should fix them when incorporating them into the repository. Having broken headers in our code just because they're broken upstream doesn't make any sense.
I can envision a fairly simple script that would fetch the current version from khronos, apply a sequence of patches and then commit the result to the mesa repository.
On 12/13/2013 05:25 PM, Keith Packard wrote:
These are duplicates from gl.h; I'm not sure which file they belong in, but you don't get to have them in both places.
If you're doing something that involves defining GL_GLEXT_PROTOTYPES, you're doing it wrong.
Also, unless you're sending kernel or libdrm patches, there's no reason to CC dri-devel. :)
Signed-off-by: Keith Packard keithp@keithp.com
include/GL/glext.h | 2 -- 1 file changed, 2 deletions(-)
diff --git a/include/GL/glext.h b/include/GL/glext.h index 7d6033e..b432d2e 100644 --- a/include/GL/glext.h +++ b/include/GL/glext.h @@ -457,8 +457,6 @@ GLAPI void APIENTRY glWindowPos3i (GLint x, GLint y, GLint z); GLAPI void APIENTRY glWindowPos3iv (const GLint *v); GLAPI void APIENTRY glWindowPos3s (GLshort x, GLshort y, GLshort z); GLAPI void APIENTRY glWindowPos3sv (const GLshort *v); -GLAPI void APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GLAPI void APIENTRY glBlendEquation (GLenum mode); #endif #endif /* GL_VERSION_1_4 */
These are the same address, but different types and driContextSetFlags wants a gl_context pointer.
Signed-off-by: Keith Packard keithp@keithp.com --- src/mesa/drivers/dri/swrast/swrast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/mesa/drivers/dri/swrast/swrast.c b/src/mesa/drivers/dri/swrast/swrast.c index cfa9316..79a2740 100644 --- a/src/mesa/drivers/dri/swrast/swrast.c +++ b/src/mesa/drivers/dri/swrast/swrast.c @@ -705,7 +705,7 @@ dri_create_context(gl_api api, goto context_fail; }
- driContextSetFlags(ctx, flags); + driContextSetFlags(mesaCtx, flags);
/* do bounds checking to prevent segfaults and server crashes! */ mesaCtx->Const.CheckArrayBounds = GL_TRUE;
libudev doesn't have a stable API/ABI, and if the application wants to use one version, we'd best not load another into libGL.
Signed-off-by: Keith Packard keithp@keithp.com --- configure.ac | 8 ----- src/glx/dri3_common.c | 85 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 50 insertions(+), 43 deletions(-)
diff --git a/configure.ac b/configure.ac index c14d39a..1193cff 100644 --- a/configure.ac +++ b/configure.ac @@ -824,9 +824,6 @@ xyesno) PKG_CHECK_MODULES([DRI2PROTO], [dri2proto >= $DRI2PROTO_REQUIRED]) GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV libdrm >= $LIBDRM_REQUIRED" if test x"$enable_dri3" = xyes; then - if test x"$have_libudev" != xyes; then - AC_MSG_ERROR([DRI3 requires libudev >= $LIBUDEV_REQUIRED]) - fi PKG_CHECK_MODULES([DRI3PROTO], [dri3proto >= $DRI3PROTO_REQUIRED]) PKG_CHECK_MODULES([PRESENTPROTO], [presentproto >= $PRESENTPROTO_REQUIRED]) fi @@ -850,11 +847,6 @@ xyesno) X11_INCLUDES="$X11_INCLUDES $DRIGL_CFLAGS" GL_LIB_DEPS="$DRIGL_LIBS"
- if test x"$enable_dri3$have_libudev" = xyesyes; then - X11_INCLUDES="$X11_INCLUDES $LIBUDEV_CFLAGS" - GL_LIB_DEPS="$GL_LIB_DEPS $LIBUDEV_LIBS" - fi - # need DRM libs, $PTHREAD_LIBS, etc. GL_LIB_DEPS="$GL_LIB_DEPS $LIBDRM_LIBS -lm $PTHREAD_LIBS $DLOPEN_LIBS" GL_PC_LIB_PRIV="-lm $PTHREAD_LIBS $DLOPEN_LIBS" diff --git a/src/glx/dri3_common.c b/src/glx/dri3_common.c index c758f96..511fbc8 100644 --- a/src/glx/dri3_common.c +++ b/src/glx/dri3_common.c @@ -23,7 +23,7 @@ /* * This code is derived from src/egl/drivers/dri2/common.c which * carries the following copyright: - * + * * Copyright © 2011 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a @@ -67,62 +67,80 @@ #include <sys/types.h> #include <sys/mman.h> #include <sys/time.h> +#include <stdbool.h> #include "xf86drm.h" #include "dri_common.h" #include "dri3_priv.h"
#define DRIVER_MAP_DRI3_ONLY -#include "pci_ids/pci_id_driver_map.h"
-#include <libudev.h> +#include "pci_ids/pci_id_driver_map.h"
-static struct udev_device * -dri3_udev_device_new_from_fd(struct udev *udev, int fd) +static dev_t +dri3_rdev_from_fd(int fd) { - struct udev_device *device; struct stat buf;
if (fstat(fd, &buf) < 0) { ErrorMessageF("DRI3: failed to stat fd %d", fd); - return NULL; + return 0; } + return buf.st_rdev; +}
- device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev); - if (device == NULL) { - ErrorMessageF("DRI3: could not create udev device for fd %d", fd); - return NULL; - } +/* + * There are multiple udev library versions, and they aren't polite about + * symbols, so just avoid using it until some glorious future when the udev + * developers figure out how to not break things + */
- return device; +#define SYS_PATH_MAX 256 + +static bool +dri3_read_hex(dev_t rdev, char *entry, int *value) +{ + char path[SYS_PATH_MAX]; + FILE *f; + int r; + + snprintf(path, sizeof (path), "/sys/dev/char/%u:%u/device/%s", + major(rdev), minor(rdev), entry); + + f = fopen(path,"r"); + if (f == NULL) + return false; + + r = fscanf(f, "0x%x\n", value); + fclose(f); + if (r != 1) + return false; + return true; +} + +static bool +dri3_get_pci_id_from_fd(int fd, int *vendorp, int *chipp) +{ + dev_t rdev = dri3_rdev_from_fd(fd); + + if (!rdev) + return false; + + if (!dri3_read_hex(rdev, "vendor", vendorp)) + return false; + if (!dri3_read_hex(rdev, "device", chipp)) + return false; + return true; }
char * dri3_get_driver_for_fd(int fd) { - struct udev *udev; - struct udev_device *device, *parent; - const char *pci_id; char *driver = NULL; int vendor_id, chip_id, i, j;
- udev = udev_new(); - device = dri3_udev_device_new_from_fd(udev, fd); - if (device == NULL) + if (!dri3_get_pci_id_from_fd(fd, &vendor_id, &chip_id)) return NULL;
- parent = udev_device_get_parent(device); - if (parent == NULL) { - ErrorMessageF("DRI3: could not get parent device"); - goto out; - } - - pci_id = udev_device_get_property_value(parent, "PCI_ID"); - if (pci_id == NULL || - sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) { - ErrorMessageF("DRI3: malformed or no PCI ID"); - goto out; - } - for (i = 0; driver_map[i].driver; i++) { if (vendor_id != driver_map[i].vendor_id) continue; @@ -139,8 +157,5 @@ dri3_get_driver_for_fd(int fd) }
out: - udev_device_unref(device); - udev_unref(udev); - return driver; }
libxshmfence v1.0 foolishly used 'int32_t *' for the fence type, which works when the fence is a linux futex. However, version 1.1 changes the exported datatype to 'struct xshmfence *'
Require libxshmfence version 1.1 and switch the API around.
Signed-off-by: Keith Packard keithp@keithp.com --- configure.ac | 2 +- src/glx/dri3_glx.c | 4 ++-- src/glx/dri3_priv.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac index 1193cff..db0debc 100644 --- a/configure.ac +++ b/configure.ac @@ -833,7 +833,7 @@ xyesno) dri_modules="x11 xext xdamage xfixes x11-xcb xcb-glx >= 1.8.1 xcb-dri2 >= 1.8"
if test x"$enable_dri3" = xyes; then - dri_modules="$dri_modules xcb-dri3 xcb-present xcb-sync xshmfence" + dri_modules="$dri_modules xcb-dri3 xcb-present xcb-sync xshmfence >= 1.1" fi
# add xf86vidmode if available diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index b047cc8..1834c6d 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -676,7 +676,7 @@ dri3_alloc_render_buffer(struct glx_screen *glx_screen, Drawable draw, xcb_connection_t *c = XGetXCBConnection(dpy); xcb_pixmap_t pixmap; xcb_sync_fence_t sync_fence; - int32_t *shm_fence; + struct xshmfence *shm_fence; int buffer_fd, fence_fd; int stride;
@@ -921,7 +921,7 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, struct dri3_screen *psc; xcb_connection_t *c; xcb_sync_fence_t sync_fence; - int32_t *shm_fence; + struct xshmfence *shm_fence; int fence_fd; __DRIimage *image_planar; int stride, offset; diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h index c892800..4bffeb7 100644 --- a/src/glx/dri3_priv.h +++ b/src/glx/dri3_priv.h @@ -87,7 +87,7 @@ struct dri3_buffer { */
uint32_t sync_fence; /* XID of X SyncFence object */ - int32_t *shm_fence; /* pointer to xshmfence object */ + struct xshmfence *shm_fence; /* pointer to xshmfence object */ GLboolean busy; /* Set on swap, cleared on IdleNotify */ void *driverPrivate;
On 12/13/2013 05:25 PM, Keith Packard wrote:
libxshmfence v1.0 foolishly used 'int32_t *' for the fence type, which works when the fence is a linux futex. However, version 1.1 changes the exported datatype to 'struct xshmfence *'
Require libxshmfence version 1.1 and switch the API around.
Signed-off-by: Keith Packard keithp@keithp.com
configure.ac | 2 +- src/glx/dri3_glx.c | 4 ++-- src/glx/dri3_priv.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac index 1193cff..db0debc 100644 --- a/configure.ac +++ b/configure.ac @@ -833,7 +833,7 @@ xyesno) dri_modules="x11 xext xdamage xfixes x11-xcb xcb-glx >= 1.8.1 xcb-dri2 >= 1.8"
if test x"$enable_dri3" = xyes; then
dri_modules="$dri_modules xcb-dri3 xcb-present xcb-sync xshmfence"
dri_modules="$dri_modules xcb-dri3 xcb-present xcb-sync xshmfence >= 1.1"
fi
# add xf86vidmode if available
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index b047cc8..1834c6d 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -676,7 +676,7 @@ dri3_alloc_render_buffer(struct glx_screen *glx_screen, Drawable draw, xcb_connection_t *c = XGetXCBConnection(dpy); xcb_pixmap_t pixmap; xcb_sync_fence_t sync_fence;
- int32_t *shm_fence;
- struct xshmfence *shm_fence; int buffer_fd, fence_fd; int stride;
@@ -921,7 +921,7 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, struct dri3_screen *psc; xcb_connection_t *c; xcb_sync_fence_t sync_fence;
- int32_t *shm_fence;
- struct xshmfence *shm_fence; int fence_fd; __DRIimage *image_planar; int stride, offset;
diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h index c892800..4bffeb7 100644 --- a/src/glx/dri3_priv.h +++ b/src/glx/dri3_priv.h @@ -87,7 +87,7 @@ struct dri3_buffer { */
uint32_t sync_fence; /* XID of X SyncFence object */
- int32_t *shm_fence; /* pointer to xshmfence object */
- struct xshmfence *shm_fence; /* pointer to xshmfence object */
Would be great to line these comments up. Patches 2 and 4-6 are: Reviewed-by: Kenneth Graunke kenneth@whitecape.org
GLboolean busy; /* Set on swap, cleared on IdleNotify */ void *driverPrivate;
Kenneth Graunke kenneth@whitecape.org writes:
Would be great to line these comments up.
Fixed.
Patches 2 and 4-6 are: Reviewed-by: Kenneth Graunke kenneth@whitecape.org
Review marked. Thanks much!
Always nice to clean up after ourselves.
Signed-off-by: Keith Packard keithp@keithp.com --- src/glx/dri3_glx.c | 17 ++++++++++++++++- src/glx/dri3_priv.h | 5 ++++- 2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index 1834c6d..4c0dc29 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -266,13 +266,25 @@ dri3_create_context(struct glx_screen *base, }
static void +dri3_free_render_buffer(struct dri3_drawable *pdraw, struct dri3_buffer *buffer); + +static void dri3_destroy_drawable(__GLXDRIdrawable *base) { struct dri3_screen *psc = (struct dri3_screen *) base->psc; struct dri3_drawable *pdraw = (struct dri3_drawable *) base; + xcb_connection_t *c = XGetXCBConnection(pdraw->base.psc->dpy); + int i;
(*psc->core->destroyDrawable) (pdraw->driDrawable);
+ for (i = 0; i < DRI3_NUM_BUFFERS; i++) { + if (pdraw->buffers[i]) + dri3_free_render_buffer(pdraw, pdraw->buffers[i]); + } + + if (pdraw->special_event) + xcb_unregister_for_special_event(c, pdraw->special_event); free(pdraw); }
@@ -736,6 +748,7 @@ dri3_alloc_render_buffer(struct glx_screen *glx_screen, Drawable draw, fence_fd);
buffer->pixmap = pixmap; + buffer->own_pixmap = true; buffer->sync_fence = sync_fence; buffer->shm_fence = shm_fence; buffer->width = width; @@ -769,7 +782,8 @@ dri3_free_render_buffer(struct dri3_drawable *pdraw, struct dri3_buffer *buffer) struct dri3_screen *psc = (struct dri3_screen *) pdraw->base.psc; xcb_connection_t *c = XGetXCBConnection(pdraw->base.psc->dpy);
- xcb_free_pixmap(c, buffer->pixmap); + if (buffer->own_pixmap) + xcb_free_pixmap(c, buffer->pixmap); xcb_sync_destroy_fence(c, buffer->sync_fence); xshmfence_unmap_shm(buffer->shm_fence); (*psc->image->destroyImage)(buffer->image); @@ -987,6 +1001,7 @@ dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, goto no_image;
buffer->pixmap = pixmap; + buffer->own_pixmap = false; buffer->width = bp_reply->width; buffer->height = bp_reply->height; buffer->buffer_type = buffer_type; diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h index 4bffeb7..2990c4f 100644 --- a/src/glx/dri3_priv.h +++ b/src/glx/dri3_priv.h @@ -89,6 +89,7 @@ struct dri3_buffer { uint32_t sync_fence; /* XID of X SyncFence object */ struct xshmfence *shm_fence; /* pointer to xshmfence object */ GLboolean busy; /* Set on swap, cleared on IdleNotify */ + GLboolean own_pixmap; /* We allocated the pixmap ID, free on destroy */ void *driverPrivate;
uint32_t size; @@ -171,6 +172,8 @@ dri3_pixmap_buf_id(enum dri3_buffer_type buffer_type) return DRI3_FRONT_ID; }
+#define DRI3_NUM_BUFFERS (1 + DRI3_MAX_BACK) + struct dri3_drawable { __GLXDRIdrawable base; __DRIdrawable *driDrawable; @@ -194,7 +197,7 @@ struct dri3_drawable { uint64_t previous_time; unsigned frames;
- struct dri3_buffer *buffers[1 + DRI3_MAX_BACK]; + struct dri3_buffer *buffers[DRI3_NUM_BUFFERS]; int cur_back; int depth;
Move the depth field up with width and height.
Remove unused previous_time and frames fields.
Signed-off-by: Keith Packard keithp@keithp.com Reviewed-by: Kenneth Graunke kenneth@whitecape.org --- src/glx/dri3_priv.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h index 2990c4f..4adef50 100644 --- a/src/glx/dri3_priv.h +++ b/src/glx/dri3_priv.h @@ -177,7 +177,7 @@ dri3_pixmap_buf_id(enum dri3_buffer_type buffer_type) struct dri3_drawable { __GLXDRIdrawable base; __DRIdrawable *driDrawable; - int width, height; + int width, height, depth; int swap_interval; uint8_t have_back; uint8_t have_fake_front; @@ -193,13 +193,9 @@ struct dri3_drawable { /* For WaitMSC */ uint32_t present_msc_request_serial; uint32_t present_msc_event_serial; - - uint64_t previous_time; - unsigned frames;
struct dri3_buffer *buffers[DRI3_NUM_BUFFERS]; int cur_back; - int depth;
uint32_t *stamp;
Tracking the full 64-bit SBC values makes it clearer how those values are being used, and simplifies the wait_msc code. The only trick is in re-constructing the full 64-bit value from Present's 32-bit serial number that we use to pass the SBC value from request to event.
Signed-off-by: Keith Packard keithp@keithp.com --- src/glx/dri3_glx.c | 34 +++++++++++++++++++++------------- src/glx/dri3_priv.h | 16 +++++++++------- 2 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index 4c0dc29..b9a786f 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -364,10 +364,17 @@ dri3_handle_present_event(struct dri3_drawable *priv, xcb_present_generic_event_ case XCB_PRESENT_COMPLETE_NOTIFY: { xcb_present_complete_notify_event_t *ce = (void *) ge;
- if (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP) - priv->present_event_serial = ce->serial; - else - priv->present_msc_event_serial = ce->serial; + /* Compute the processed SBC number from the received 32-bit serial number merged + * with the upper 32-bits of the sent 64-bit serial number while checking for + * wrap + */ + if (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP) { + priv->recv_sbc = (priv->send_sbc & 0xffffffff00000000LL) | ce->serial; + if (priv->recv_sbc > priv->send_sbc) + priv->recv_sbc -= 0x100000000; + } else { + priv->recv_msc_serial = ce->serial; + } priv->ust = ce->ust; priv->msc = ce->msc; break; @@ -398,12 +405,13 @@ dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, struct dri3_drawable *priv = (struct dri3_drawable *) pdraw; xcb_generic_event_t *ev; xcb_present_generic_event_t *ge; + uint32_t msc_serial;
/* Ask for the an event for the target MSC */ - ++priv->present_msc_request_serial; + msc_serial = ++priv->send_msc_serial; xcb_present_notify_msc(c, priv->base.xDrawable, - priv->present_msc_request_serial, + msc_serial, target_msc, divisor, remainder); @@ -412,7 +420,7 @@ dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
/* Wait for the event */ if (priv->special_event) { - while (priv->present_msc_request_serial != priv->present_msc_event_serial) { + while ((int32_t) (msc_serial - priv->recv_msc_serial) > 0) { ev = xcb_wait_for_special_event(c, priv->special_event); if (!ev) break; @@ -423,7 +431,7 @@ dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
*ust = priv->ust; *msc = priv->msc; - *sbc = priv->sbc; + *sbc = priv->recv_sbc;
return 1; } @@ -450,7 +458,7 @@ dri3_wait_for_sbc(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, { struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
- while (priv->sbc < target_sbc) { + while (priv->send_sbc < target_sbc) { sleep(1); } return dri3_wait_for_msc(pdraw, 0, 0, 0, ust, msc, sbc); @@ -1281,15 +1289,15 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, /* Compute when we want the frame shown by taking the last known successful * MSC and adding in a swap interval for each outstanding swap request */ - ++priv->present_request_serial; + ++priv->send_sbc; if (target_msc == 0) - target_msc = priv->msc + priv->swap_interval * (priv->present_request_serial - priv->present_event_serial); + target_msc = priv->msc + priv->swap_interval * (priv->send_sbc - priv->recv_sbc);
priv->buffers[buf_id]->busy = 1; xcb_present_pixmap(c, priv->base.xDrawable, priv->buffers[buf_id]->pixmap, - priv->present_request_serial, + (uint32_t) priv->send_sbc, 0, /* valid */ 0, /* update */ 0, /* x_off */ @@ -1301,7 +1309,7 @@ dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, target_msc, divisor, remainder, 0, NULL); - ret = ++priv->sbc; + ret = (int64_t) priv->send_sbc;
/* If there's a fake front, then copy the source back buffer * to the fake front to keep it up to date. This needs diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h index 4adef50..4c5579e 100644 --- a/src/glx/dri3_priv.h +++ b/src/glx/dri3_priv.h @@ -183,16 +183,18 @@ struct dri3_drawable { uint8_t have_fake_front; uint8_t is_pixmap;
- uint32_t present_request_serial; - uint32_t present_event_serial; - - uint64_t sbc; + /* SBC numbers are tracked by using the serial numbers + * in the present request and complete events + */ + uint64_t send_sbc; + uint64_t recv_sbc;
+ /* Last received UST/MSC values */ uint64_t ust, msc;
- /* For WaitMSC */ - uint32_t present_msc_request_serial; - uint32_t present_msc_event_serial; + /* Serial numbers for tracking wait_for_msc events */ + uint32_t send_msc_serial; + uint32_t recv_msc_serial;
struct dri3_buffer *buffers[DRI3_NUM_BUFFERS]; int cur_back;
Eric figured out that glXWaitForSbcOML wanted to block until the requested SBC had been completed, which means to wait until the PresentCompleteNotify event for that SBC had been received.
This replaces the simple sleep(1) loop (which was bogus) with a loop that just checks to see if we've seen the specified SBC value come back in a PresentCompleteNotify event yet.
The change is a bit larger than that as I've broken out a piece of common code to wait for and process a single Present event for the target drawable.
Signed-off-by: Keith Packard keithp@keithp.com --- src/glx/dri3_glx.c | 55 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 16 deletions(-)
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index b9a786f..d2b9d0e 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -397,14 +397,33 @@ dri3_handle_present_event(struct dri3_drawable *priv, xcb_present_generic_event_ free(ge); }
+static bool +dri3_wait_for_event(__GLXDRIdrawable *pdraw) +{ + xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy); + struct dri3_drawable *priv = (struct dri3_drawable *) pdraw; + xcb_generic_event_t *ev; + xcb_present_generic_event_t *ge; + + ev = xcb_wait_for_special_event(c, priv->special_event); + if (!ev) + return false; + ge = (void *) ev; + dri3_handle_present_event(priv, ge); + return true; +} + +/** dri3_wait_for_msc + * + * Get the X server to send an event when the target msc/divisor/remainder is + * reached. + */ static int dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) { xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy); struct dri3_drawable *priv = (struct dri3_drawable *) pdraw; - xcb_generic_event_t *ev; - xcb_present_generic_event_t *ge; uint32_t msc_serial;
/* Ask for the an event for the target MSC */ @@ -421,11 +440,8 @@ dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, /* Wait for the event */ if (priv->special_event) { while ((int32_t) (msc_serial - priv->recv_msc_serial) > 0) { - ev = xcb_wait_for_special_event(c, priv->special_event); - if (!ev) - break; - ge = (void *) ev; - dri3_handle_present_event(priv, ge); + if (!dri3_wait_for_event(pdraw)) + return 0; } }
@@ -436,6 +452,11 @@ dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, return 1; }
+/** dri3_drawable_get_msc + * + * Return the current UST/MSC/SBC triplet by asking the server + * for an event + */ static int dri3_drawable_get_msc(struct glx_screen *psc, __GLXDRIdrawable *pdraw, int64_t *ust, int64_t *msc, int64_t *sbc) @@ -445,12 +466,9 @@ dri3_drawable_get_msc(struct glx_screen *psc, __GLXDRIdrawable *pdraw,
/** dri3_wait_for_sbc * - * Wait for the swap buffer count to increase. The only way this - * can happen is if some other thread is doing swap buffers as - * we no longer share swap buffer counts with other processes. - * - * I'm not sure this is actually useful as such, and so this - * implementation is a kludge that just polls once a second + * Wait for the completed swap buffer count to reach the specified + * target. Presumably the application knows that this will be reached with + * outstanding complete events, or we're going to be here awhile. */ static int dri3_wait_for_sbc(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, @@ -458,10 +476,15 @@ dri3_wait_for_sbc(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, { struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
- while (priv->send_sbc < target_sbc) { - sleep(1); + while (priv->recv_sbc < target_sbc) { + if (!dri3_wait_for_event(pdraw)) + return 0; } - return dri3_wait_for_msc(pdraw, 0, 0, 0, ust, msc, sbc); + + *ust = priv->ust; + *msc = priv->msc; + *sbc = priv->recv_sbc; + return 1; }
/**
Now that we're tracking SBC values correctly, and the X server has the ability to send the GLX swap events from a PresentPixmap request, enable this extension.
Signed-off-by: Keith Packard keithp@keithp.com --- src/glx/dri3_glx.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-)
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index d2b9d0e..ea20138 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -1524,23 +1524,7 @@ dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv, __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control"); __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control"); __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read"); - - /* - * GLX_INTEL_swap_event is broken on the server side, where it's - * currently unconditionally enabled. This completely breaks - * systems running on drivers which don't support that extension. - * There's no way to test for its presence on this side, so instead - * of disabling it unconditionally, just disable it for drivers - * which are known to not support it, or for DDX drivers supporting - * only an older (pre-ScheduleSwap) version of DRI2. - * - * This is a hack which is required until: - * http://lists.x.org/archives/xorg-devel/2013-February/035449.html - * is merged and updated xserver makes it's way into distros: - */ -// if (pdp->swapAvailable && strcmp(driverName, "vmwgfx") != 0) { -// __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event"); -// } + __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event");
mask = psc->image_driver->getAPIMask(psc->driScreen);
The buffer-object is the persistent thing passed through the loader, so when updating an image buffer, check to see if it is already bound to the provided bo. The region, on the other hand, is allocated separately for the miptree, and so will never be the same as that passed back from the loader.
Signed-off-by: Keith Packard keithp@keithp.com Reviewed-by: Eric Anholt eric@anholt.net --- src/mesa/drivers/dri/i965/brw_context.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c index 688091f..78c06fc 100644 --- a/src/mesa/drivers/dri/i965/brw_context.c +++ b/src/mesa/drivers/dri/i965/brw_context.c @@ -1303,10 +1303,21 @@ intel_update_image_buffer(struct brw_context *intel,
unsigned num_samples = rb->Base.Base.NumSamples;
- if (rb->mt && - rb->mt->region && - rb->mt->region == region) - return; + /* Check and see if we're already bound to the right + * buffer object + */ + if (num_samples == 0) { + if (rb->mt && + rb->mt->region && + rb->mt->region->bo == region->bo) + return; + } else { + if (rb->mt && + rb->mt->singlesample_mt && + rb->mt->singlesample_mt->region && + rb->mt->singlesample_mt->region->bo == region->bo) + return; + }
intel_miptree_release(&rb->mt); rb->mt = intel_miptree_create_for_image_buffer(intel,
Just copying code from the dri2 path to set up the fast color clear state.
This also removes a couple of bogus intel_region_reference calls.
Signed-off-by: Keith Packard keithp@keithp.com Reviewed-by: Eric Anholt eric@anholt.net --- src/mesa/drivers/dri/i965/intel_mipmap_tree.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c index a96c7ea..de47143 100644 --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c @@ -771,7 +771,13 @@ intel_miptree_create_for_image_buffer(struct brw_context *intel, if (!singlesample_mt) return NULL;
- intel_region_reference(&singlesample_mt->region, region); + /* If this miptree is capable of supporting fast color clears, set + * mcs_state appropriately to ensure that fast clears will occur. + * Allocation of the MCS miptree will be deferred until the first fast + * clear actually occurs. + */ + if (intel_is_non_msrt_mcs_buffer_supported(intel, singlesample_mt)) + singlesample_mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED;
if (num_samples == 0) return singlesample_mt; @@ -789,8 +795,6 @@ intel_miptree_create_for_image_buffer(struct brw_context *intel, multisample_mt->singlesample_mt = singlesample_mt; multisample_mt->need_downsample = false;
- intel_region_reference(&multisample_mt->region, region); - if (intel->is_front_buffer_rendering && buffer_type == __DRI_IMAGE_BUFFER_FRONT) { intel_miptree_upsample(intel, multisample_mt); }
It is the maximum number of back buffers, but the name is confusing and is easily read as the maximum back buffer index. Chage to DRI3_NUM_BACK to make the intended usage a bit clearer.
Signed-off-by: Keith Packard keithp@keithp.com --- src/glx/dri3_glx.c | 4 ++-- src/glx/dri3_priv.h | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index ea20138..c26d6e5 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -1065,7 +1065,7 @@ dri3_find_back(xcb_connection_t *c, struct dri3_drawable *priv)
for (;;) {
- for (b = 0; b < DRI3_MAX_BACK; b++) { + for (b = 0; b < DRI3_NUM_BACK; b++) { int id = DRI3_BACK_ID(b); struct dri3_buffer *buffer = priv->buffers[id];
@@ -1181,7 +1181,7 @@ dri3_free_buffers(__DRIdrawable *driDrawable, switch (buffer_type) { case dri3_buffer_back: first_id = DRI3_BACK_ID(0); - n_id = DRI3_MAX_BACK; + n_id = DRI3_NUM_BACK; break; case dri3_buffer_front: first_id = DRI3_FRONT_ID; diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h index 4c5579e..49a13ba 100644 --- a/src/glx/dri3_priv.h +++ b/src/glx/dri3_priv.h @@ -143,14 +143,14 @@ struct dri3_context __DRIcontext *driContext; };
-#define DRI3_MAX_BACK 2 +#define DRI3_NUM_BACK 2 #define DRI3_BACK_ID(i) (i) -#define DRI3_FRONT_ID (DRI3_MAX_BACK) +#define DRI3_FRONT_ID (DRI3_NUM_BACK)
static inline int dri3_buf_id_next(int buf_id) { - if (buf_id == DRI3_MAX_BACK - 1) + if (buf_id == DRI3_NUM_BACK - 1) return 0; return buf_id + 1; } @@ -159,7 +159,7 @@ static inline int dri3_buf_id_prev(int buf_id) { if (buf_id == 0) - return DRI3_MAX_BACK - 1; + return DRI3_NUM_BACK - 1; return buf_id - 1; }
@@ -172,7 +172,7 @@ dri3_pixmap_buf_id(enum dri3_buffer_type buffer_type) return DRI3_FRONT_ID; }
-#define DRI3_NUM_BUFFERS (1 + DRI3_MAX_BACK) +#define DRI3_NUM_BUFFERS (1 + DRI3_NUM_BACK)
struct dri3_drawable { __GLXDRIdrawable base;
XCB doesn't flush the output buffer automatically, so we have to call xcb_flush ourselves before waiting.
Signed-off-by: Keith Packard keithp@keithp.com --- src/glx/dri3_glx.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index c26d6e5..7982f6b 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -405,6 +405,7 @@ dri3_wait_for_event(__GLXDRIdrawable *pdraw) xcb_generic_event_t *ev; xcb_present_generic_event_t *ge;
+ xcb_flush(c); ev = xcb_wait_for_special_event(c, priv->special_event); if (!ev) return false; @@ -1074,6 +1075,7 @@ dri3_find_back(xcb_connection_t *c, struct dri3_drawable *priv) if (!buffer->busy) return b; } + xcb_flush(c); ev = xcb_wait_for_special_event(c, priv->special_event); if (!ev) return -1;
The __DRIimage createImageFromFds function takes a fourcc code, but there was no fourcc code that match __DRI_IMAGE_FORMAT_SARGB8. This adds a define for that format, adds a translation in DRI3 from __DRI_IMAGE_FORMAT_SARGB8 to __DRI_IMAGE_FOURCC_SARGB8888 and then adds translations *back* to __IMAGE_FORMAT_SARGB8 in both the i915 and i965 drivers.
I'll refrain from comments on whether I think having two separate sets of format defines in dri_interface.h is a good idea or not...
Signed-off-by: Keith Packard keithp@keithp.com Reviewed-by: Eric Anholt eric@anholt.net --- include/GL/internal/dri_interface.h | 1 + src/glx/dri3_glx.c | 1 + src/mesa/drivers/dri/i915/intel_screen.c | 3 +++ src/mesa/drivers/dri/i965/intel_screen.c | 3 +++ 4 files changed, 8 insertions(+)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index 81f7e60..9e82904 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -1041,6 +1041,7 @@ struct __DRIdri2ExtensionRec { #define __DRI_IMAGE_FOURCC_XRGB8888 0x34325258 #define __DRI_IMAGE_FOURCC_ABGR8888 0x34324241 #define __DRI_IMAGE_FOURCC_XBGR8888 0x34324258 +#define __DRI_IMAGE_FOURCC_SARGB8888 0x83324258 #define __DRI_IMAGE_FOURCC_YUV410 0x39565559 #define __DRI_IMAGE_FOURCC_YUV411 0x31315559 #define __DRI_IMAGE_FOURCC_YUV420 0x32315559 diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c index 7982f6b..ad6de65 100644 --- a/src/glx/dri3_glx.c +++ b/src/glx/dri3_glx.c @@ -936,6 +936,7 @@ image_format_to_fourcc(int format)
/* Convert from __DRI_IMAGE_FORMAT to __DRI_IMAGE_FOURCC (sigh) */ switch (format) { + case __DRI_IMAGE_FORMAT_SARGB8: return __DRI_IMAGE_FOURCC_SARGB8888; case __DRI_IMAGE_FORMAT_RGB565: return __DRI_IMAGE_FOURCC_RGB565; case __DRI_IMAGE_FORMAT_XRGB8888: return __DRI_IMAGE_FOURCC_XRGB8888; case __DRI_IMAGE_FORMAT_ARGB8888: return __DRI_IMAGE_FOURCC_ARGB8888; diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c index d607f47..d442eab 100644 --- a/src/mesa/drivers/dri/i915/intel_screen.c +++ b/src/mesa/drivers/dri/i915/intel_screen.c @@ -184,6 +184,9 @@ static struct intel_image_format intel_image_formats[] = { { __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1, { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
+ { __DRI_IMAGE_FOURCC_SARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_SARGB8, 4 } } }, + { __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_COMPONENTS_RGB, 1, { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } },
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c index 4373685..9a5bf5c 100644 --- a/src/mesa/drivers/dri/i965/intel_screen.c +++ b/src/mesa/drivers/dri/i965/intel_screen.c @@ -220,6 +220,9 @@ static struct intel_image_format intel_image_formats[] = { { __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1, { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
+ { __DRI_IMAGE_FOURCC_SARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_SARGB8, 4 } } }, + { __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_COMPONENTS_RGB, 1, { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } },
Provide the hook to pull textures out of __DRIimage structures and use them as renderbuffers.
Signed-off-by: Keith Packard keithp@keithp.com --- src/gallium/state_trackers/dri/drm/dri2.c | 238 +++++++++++++++++++++++++++++- 1 file changed, 230 insertions(+), 8 deletions(-)
diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c index 8ff77b3..03b93ae 100644 --- a/src/gallium/state_trackers/dri/drm/dri2.c +++ b/src/gallium/state_trackers/dri/drm/dri2.c @@ -457,6 +457,219 @@ dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) FREE(buffer); }
+static void +dri_image_allocate_textures(struct dri_context *ctx, + struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned statts_count) +{ + __DRIdrawable *dPriv = drawable->dPriv; + __DRIscreen *sPriv = drawable->sPriv; + struct dri_screen *screen = dri_screen(sPriv); + unsigned int image_format = __DRI_IMAGE_FORMAT_NONE; + uint32_t buffer_mask = 0; + struct __DRIimageList images; + boolean alloc_depthstencil = FALSE; + int i, j; + struct pipe_resource templ; + + /* See if we need a depth-stencil buffer. */ + for (i = 0; i < statts_count; i++) { + if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { + alloc_depthstencil = TRUE; + break; + } + } + + /* Delete the resources we won't need. */ + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + /* Don't delete the depth-stencil buffer, we can reuse it. */ + if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil) + continue; + + pipe_resource_reference(&drawable->textures[i], NULL); + } + + if (drawable->stvis.samples > 1) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + boolean del = TRUE; + + /* Don't delete MSAA resources for the attachments which are enabled, + * we can reuse them. */ + for (j = 0; j < statts_count; j++) { + if (i == statts[j]) { + del = FALSE; + break; + } + } + + if (del) { + pipe_resource_reference(&drawable->msaa_textures[i], NULL); + } + } + } + + for (i = 0; i < statts_count; i++) { + enum pipe_format pf; + unsigned bind; + + dri_drawable_get_format(drawable, statts[i], &pf, &bind); + if (pf == PIPE_FORMAT_NONE) + continue; + + switch (pf) { + case PIPE_FORMAT_B5G6R5_UNORM: + image_format = __DRI_IMAGE_FORMAT_RGB565; + break; + case PIPE_FORMAT_B8G8R8X8_UNORM: + image_format = __DRI_IMAGE_FORMAT_XRGB8888; + break; + case PIPE_FORMAT_B8G8R8A8_UNORM: + image_format = __DRI_IMAGE_FORMAT_ARGB8888; + break; + case PIPE_FORMAT_R8G8B8A8_UNORM: + image_format = __DRI_IMAGE_FORMAT_ABGR8888; + break; + default: + image_format = __DRI_IMAGE_FORMAT_NONE; + break; + } + + switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; + break; + case ST_ATTACHMENT_BACK_LEFT: + buffer_mask |= __DRI_IMAGE_BUFFER_BACK; + break; + default: + continue; + } + } + + (*sPriv->image.loader->getBuffers) (dPriv, + image_format, + &dPriv->dri2.stamp, + dPriv->loaderPrivate, + buffer_mask, + &images); + + if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) { + struct pipe_resource *texture = images.front->texture; + + dPriv->w = texture->width0; + dPriv->h = texture->height0; + + pipe_resource_reference(&drawable->textures[ST_ATTACHMENT_FRONT_LEFT], texture); + } + + if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) { + struct pipe_resource *texture = images.back->texture; + + dPriv->w = images.back->texture->width0; + dPriv->h = images.back->texture->height0; + + pipe_resource_reference(&drawable->textures[ST_ATTACHMENT_BACK_LEFT], texture); + } + + memset(&templ, 0, sizeof(templ)); + templ.target = screen->target; + templ.last_level = 0; + templ.width0 = dPriv->w; + templ.height0 = dPriv->h; + templ.depth0 = 1; + templ.array_size = 1; + + /* Allocate private MSAA colorbuffers. */ + if (drawable->stvis.samples > 1) { + for (i = 0; i < statts_count; i++) { + enum st_attachment_type att = statts[i]; + + if (att == ST_ATTACHMENT_DEPTH_STENCIL) + continue; + + if (drawable->textures[att]) { + templ.format = drawable->textures[att]->format; + templ.bind = drawable->textures[att]->bind; + templ.nr_samples = drawable->stvis.samples; + + /* Try to reuse the resource. + * (the other resource parameters should be constant) + */ + if (!drawable->msaa_textures[att] || + drawable->msaa_textures[att]->width0 != templ.width0 || + drawable->msaa_textures[att]->height0 != templ.height0) { + /* Allocate a new one. */ + pipe_resource_reference(&drawable->msaa_textures[att], NULL); + + drawable->msaa_textures[att] = + screen->base.screen->resource_create(screen->base.screen, + &templ); + assert(drawable->msaa_textures[att]); + + /* If there are any MSAA resources, we should initialize them + * such that they contain the same data as the single-sample + * resources we just got from the X server. + * + * The reason for this is that the state tracker (and + * therefore the app) can access the MSAA resources only. + * The single-sample resources are not exposed + * to the state tracker. + * + */ + dri_pipe_blit(ctx->st->pipe, + drawable->msaa_textures[att], + drawable->textures[att]); + } + } + else { + pipe_resource_reference(&drawable->msaa_textures[att], NULL); + } + } + } + + /* Allocate a private depth-stencil buffer. */ + if (alloc_depthstencil) { + enum st_attachment_type att = ST_ATTACHMENT_DEPTH_STENCIL; + struct pipe_resource **zsbuf; + enum pipe_format format; + unsigned bind; + + dri_drawable_get_format(drawable, att, &format, &bind); + + if (format) { + templ.format = format; + templ.bind = bind; + + if (drawable->stvis.samples > 1) { + templ.nr_samples = drawable->stvis.samples; + zsbuf = &drawable->msaa_textures[att]; + } + else { + templ.nr_samples = 0; + zsbuf = &drawable->textures[att]; + } + + /* Try to reuse the resource. + * (the other resource parameters should be constant) + */ + if (!*zsbuf || + (*zsbuf)->width0 != templ.width0 || + (*zsbuf)->height0 != templ.height0) { + /* Allocate a new one. */ + pipe_resource_reference(zsbuf, NULL); + *zsbuf = screen->base.screen->resource_create(screen->base.screen, + &templ); + assert(*zsbuf); + } + } + else { + pipe_resource_reference(&drawable->msaa_textures[att], NULL); + pipe_resource_reference(&drawable->textures[att], NULL); + } + } +} + /* * Backend functions for st_framebuffer interface. */ @@ -467,13 +680,18 @@ dri2_allocate_textures(struct dri_context *ctx, const enum st_attachment_type *statts, unsigned statts_count) { - __DRIbuffer *buffers; - unsigned num_buffers = statts_count; - - buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); - if (buffers) - dri2_drawable_process_buffers(ctx, drawable, buffers, num_buffers, - statts, statts_count); + __DRIscreen *sPriv = drawable->sPriv; + + if (sPriv->image.loader) { + dri_image_allocate_textures(ctx, drawable, statts, statts_count); + } else { + __DRIbuffer *buffers; + unsigned num_buffers = statts_count; + buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); + if (buffers) + dri2_drawable_process_buffers(ctx, drawable, buffers, num_buffers, + statts, statts_count); + } }
static void @@ -482,6 +700,7 @@ dri2_flush_frontbuffer(struct dri_context *ctx, enum st_attachment_type statt) { __DRIdrawable *dri_drawable = drawable->dPriv; + struct __DRIimageLoaderExtensionRec *image = drawable->sPriv->image.loader; struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader; struct pipe_context *pipe = ctx->st->pipe;
@@ -501,7 +720,9 @@ dri2_flush_frontbuffer(struct dri_context *ctx,
pipe->flush(pipe, NULL, 0);
- if (loader->flushFrontBuffer) { + if (image->flushFrontBuffer) { + image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); + } else if (loader->flushFrontBuffer) { loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); } } @@ -1116,6 +1337,7 @@ const struct __DriverAPIRec driDriverAPI = { /* This is the table of extensions that the loader will dlsym() for. */ PUBLIC const __DRIextension *__driDriverExtensions[] = { &driCoreExtension.base, + &driImageDriverExtension.base, &driDRI2Extension.base, &gallium_config_options.base, NULL
Some of the code seems to be copy-pasted from dri2_drawable_process_buffers. The MSAA color and depth-stencil texture allocation could be moved to a common function.
Marek
On Sat, Dec 14, 2013 at 2:25 AM, Keith Packard keithp@keithp.com wrote:
Provide the hook to pull textures out of __DRIimage structures and use them as renderbuffers.
Signed-off-by: Keith Packard keithp@keithp.com
src/gallium/state_trackers/dri/drm/dri2.c | 238 +++++++++++++++++++++++++++++- 1 file changed, 230 insertions(+), 8 deletions(-)
diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c index 8ff77b3..03b93ae 100644 --- a/src/gallium/state_trackers/dri/drm/dri2.c +++ b/src/gallium/state_trackers/dri/drm/dri2.c @@ -457,6 +457,219 @@ dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) FREE(buffer); }
+static void +dri_image_allocate_textures(struct dri_context *ctx,
struct dri_drawable *drawable,
const enum st_attachment_type *statts,
unsigned statts_count)
+{
- __DRIdrawable *dPriv = drawable->dPriv;
- __DRIscreen *sPriv = drawable->sPriv;
- struct dri_screen *screen = dri_screen(sPriv);
- unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;
- uint32_t buffer_mask = 0;
- struct __DRIimageList images;
- boolean alloc_depthstencil = FALSE;
- int i, j;
- struct pipe_resource templ;
- /* See if we need a depth-stencil buffer. */
- for (i = 0; i < statts_count; i++) {
if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
alloc_depthstencil = TRUE;
break;
}
- }
- /* Delete the resources we won't need. */
- for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
/* Don't delete the depth-stencil buffer, we can reuse it. */
if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
continue;
pipe_resource_reference(&drawable->textures[i], NULL);
- }
- if (drawable->stvis.samples > 1) {
for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
boolean del = TRUE;
/* Don't delete MSAA resources for the attachments which are enabled,
* we can reuse them. */
for (j = 0; j < statts_count; j++) {
if (i == statts[j]) {
del = FALSE;
break;
}
}
if (del) {
pipe_resource_reference(&drawable->msaa_textures[i], NULL);
}
}
- }
- for (i = 0; i < statts_count; i++) {
enum pipe_format pf;
unsigned bind;
dri_drawable_get_format(drawable, statts[i], &pf, &bind);
if (pf == PIPE_FORMAT_NONE)
continue;
switch (pf) {
case PIPE_FORMAT_B5G6R5_UNORM:
image_format = __DRI_IMAGE_FORMAT_RGB565;
break;
case PIPE_FORMAT_B8G8R8X8_UNORM:
image_format = __DRI_IMAGE_FORMAT_XRGB8888;
break;
case PIPE_FORMAT_B8G8R8A8_UNORM:
image_format = __DRI_IMAGE_FORMAT_ARGB8888;
break;
case PIPE_FORMAT_R8G8B8A8_UNORM:
image_format = __DRI_IMAGE_FORMAT_ABGR8888;
break;
default:
image_format = __DRI_IMAGE_FORMAT_NONE;
break;
}
switch (statts[i]) {
case ST_ATTACHMENT_FRONT_LEFT:
buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
break;
case ST_ATTACHMENT_BACK_LEFT:
buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
break;
default:
continue;
}
- }
- (*sPriv->image.loader->getBuffers) (dPriv,
image_format,
&dPriv->dri2.stamp,
dPriv->loaderPrivate,
buffer_mask,
&images);
- if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
struct pipe_resource *texture = images.front->texture;
dPriv->w = texture->width0;
dPriv->h = texture->height0;
pipe_resource_reference(&drawable->textures[ST_ATTACHMENT_FRONT_LEFT], texture);
- }
- if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
struct pipe_resource *texture = images.back->texture;
dPriv->w = images.back->texture->width0;
dPriv->h = images.back->texture->height0;
pipe_resource_reference(&drawable->textures[ST_ATTACHMENT_BACK_LEFT], texture);
- }
- memset(&templ, 0, sizeof(templ));
- templ.target = screen->target;
- templ.last_level = 0;
- templ.width0 = dPriv->w;
- templ.height0 = dPriv->h;
- templ.depth0 = 1;
- templ.array_size = 1;
- /* Allocate private MSAA colorbuffers. */
- if (drawable->stvis.samples > 1) {
for (i = 0; i < statts_count; i++) {
enum st_attachment_type att = statts[i];
if (att == ST_ATTACHMENT_DEPTH_STENCIL)
continue;
if (drawable->textures[att]) {
templ.format = drawable->textures[att]->format;
templ.bind = drawable->textures[att]->bind;
templ.nr_samples = drawable->stvis.samples;
/* Try to reuse the resource.
* (the other resource parameters should be constant)
*/
if (!drawable->msaa_textures[att] ||
drawable->msaa_textures[att]->width0 != templ.width0 ||
drawable->msaa_textures[att]->height0 != templ.height0) {
/* Allocate a new one. */
pipe_resource_reference(&drawable->msaa_textures[att], NULL);
drawable->msaa_textures[att] =
screen->base.screen->resource_create(screen->base.screen,
&templ);
assert(drawable->msaa_textures[att]);
/* If there are any MSAA resources, we should initialize them
* such that they contain the same data as the single-sample
* resources we just got from the X server.
*
* The reason for this is that the state tracker (and
* therefore the app) can access the MSAA resources only.
* The single-sample resources are not exposed
* to the state tracker.
*
*/
dri_pipe_blit(ctx->st->pipe,
drawable->msaa_textures[att],
drawable->textures[att]);
}
}
else {
pipe_resource_reference(&drawable->msaa_textures[att], NULL);
}
}
- }
- /* Allocate a private depth-stencil buffer. */
- if (alloc_depthstencil) {
enum st_attachment_type att = ST_ATTACHMENT_DEPTH_STENCIL;
struct pipe_resource **zsbuf;
enum pipe_format format;
unsigned bind;
dri_drawable_get_format(drawable, att, &format, &bind);
if (format) {
templ.format = format;
templ.bind = bind;
if (drawable->stvis.samples > 1) {
templ.nr_samples = drawable->stvis.samples;
zsbuf = &drawable->msaa_textures[att];
}
else {
templ.nr_samples = 0;
zsbuf = &drawable->textures[att];
}
/* Try to reuse the resource.
* (the other resource parameters should be constant)
*/
if (!*zsbuf ||
(*zsbuf)->width0 != templ.width0 ||
(*zsbuf)->height0 != templ.height0) {
/* Allocate a new one. */
pipe_resource_reference(zsbuf, NULL);
*zsbuf = screen->base.screen->resource_create(screen->base.screen,
&templ);
assert(*zsbuf);
}
}
else {
pipe_resource_reference(&drawable->msaa_textures[att], NULL);
pipe_resource_reference(&drawable->textures[att], NULL);
}
- }
+}
/*
- Backend functions for st_framebuffer interface.
*/ @@ -467,13 +680,18 @@ dri2_allocate_textures(struct dri_context *ctx, const enum st_attachment_type *statts, unsigned statts_count) {
- __DRIbuffer *buffers;
- unsigned num_buffers = statts_count;
- buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
- if (buffers)
dri2_drawable_process_buffers(ctx, drawable, buffers, num_buffers,
statts, statts_count);
- __DRIscreen *sPriv = drawable->sPriv;
- if (sPriv->image.loader) {
dri_image_allocate_textures(ctx, drawable, statts, statts_count);
- } else {
__DRIbuffer *buffers;
unsigned num_buffers = statts_count;
buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
if (buffers)
dri2_drawable_process_buffers(ctx, drawable, buffers, num_buffers,
statts, statts_count);
- }
}
static void @@ -482,6 +700,7 @@ dri2_flush_frontbuffer(struct dri_context *ctx, enum st_attachment_type statt) { __DRIdrawable *dri_drawable = drawable->dPriv;
- struct __DRIimageLoaderExtensionRec *image = drawable->sPriv->image.loader; struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader; struct pipe_context *pipe = ctx->st->pipe;
@@ -501,7 +720,9 @@ dri2_flush_frontbuffer(struct dri_context *ctx,
pipe->flush(pipe, NULL, 0);
- if (loader->flushFrontBuffer) {
- if (image->flushFrontBuffer) {
image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
- } else if (loader->flushFrontBuffer) { loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); }
} @@ -1116,6 +1337,7 @@ const struct __DriverAPIRec driDriverAPI = { /* This is the table of extensions that the loader will dlsym() for. */ PUBLIC const __DRIextension *__driDriverExtensions[] = { &driCoreExtension.base,
- &driImageDriverExtension.base, &driDRI2Extension.base, &gallium_config_options.base, NULL
-- 1.8.4.4
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Marek Olšák maraeo@gmail.com writes:
Some of the code seems to be copy-pasted from dri2_drawable_process_buffers. The MSAA color and depth-stencil texture allocation could be moved to a common function.
It's either that or plan on moving DRI2 to the image interface as well at some point? As we'll have to keep DRI2 support around, it sure would be nice to share the driver backend bits between DRI3 and DRI2?
On Fri, Dec 27, 2013 at 9:27 PM, Keith Packard keithp@keithp.com wrote:
Marek Olšák maraeo@gmail.com writes:
Some of the code seems to be copy-pasted from dri2_drawable_process_buffers. The MSAA color and depth-stencil texture allocation could be moved to a common function.
It's either that or plan on moving DRI2 to the image interface as well at some point? As we'll have to keep DRI2 support around, it sure would be nice to share the driver backend bits between DRI3 and DRI2?
Yes, but it would break the "new Mesa + old libGL without DRIimage" combination. Not that I care much about that. It's up to you. I think it would be good to do what the Intel Mesa driver does.
Marek
From: Ben Skeggs bskeggs@redhat.com
Signed-off-by: Ben Skeggs bskeggs@redhat.com Signed-off-by: Keith Packard keithp@keithp.com --- src/gallium/state_trackers/dri/drm/dri2.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c index 03b93ae..a9d6a10 100644 --- a/src/gallium/state_trackers/dri/drm/dri2.c +++ b/src/gallium/state_trackers/dri/drm/dri2.c @@ -517,6 +517,17 @@ dri_image_allocate_textures(struct dri_context *ctx, if (pf == PIPE_FORMAT_NONE) continue;
+ switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; + break; + case ST_ATTACHMENT_BACK_LEFT: + buffer_mask |= __DRI_IMAGE_BUFFER_BACK; + break; + default: + continue; + } + switch (pf) { case PIPE_FORMAT_B5G6R5_UNORM: image_format = __DRI_IMAGE_FORMAT_RGB565; @@ -534,17 +545,6 @@ dri_image_allocate_textures(struct dri_context *ctx, image_format = __DRI_IMAGE_FORMAT_NONE; break; } - - switch (statts[i]) { - case ST_ATTACHMENT_FRONT_LEFT: - buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; - break; - case ST_ATTACHMENT_BACK_LEFT: - buffer_mask |= __DRI_IMAGE_BUFFER_BACK; - break; - default: - continue; - } }
(*sPriv->image.loader->getBuffers) (dPriv,
From: Ben Skeggs bskeggs@redhat.com
Signed-off-by: Ben Skeggs bskeggs@redhat.com Signed-off-by: Keith Packard keithp@keithp.com --- src/gallium/drivers/nouveau/nvc0/nvc0_resource.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_resource.c b/src/gallium/drivers/nouveau/nvc0/nvc0_resource.c index 4e70903..7fbc6e1 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_resource.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_resource.c @@ -26,7 +26,8 @@ nvc0_resource_from_handle(struct pipe_screen * screen, } else { struct pipe_resource *res = nv50_miptree_from_handle(screen, templ, whandle); - nv04_resource(res)->vtbl = &nvc0_miptree_vtbl; + if (res) + nv04_resource(res)->vtbl = &nvc0_miptree_vtbl; return res; } }
Upper levels of the stack use base.stamp to tell when a drawable needs to be revalidated, but the dri state tracker was using dPriv->lastStamp. Those two, along with dri2.stamp, all get simultaneously incremented when a dri2 invalidate event was delivered, and so end up containing precisely the same value.
This patch doesn't change the fact that there are three variables, rather it switches all of the tests to use only base.stamp, which is functionally equivalent to the previous code.
Then, it passes base.stamp to the image loader getBuffers function so that the one which is checked will get updated by the XCB special event queue used by DRI3.
Signed-off-by: Keith Packard keithp@keithp.com Reviewed-by: Marek Olšák marek.olsak@amd.com --- src/gallium/state_trackers/dri/common/dri_drawable.c | 4 ++-- src/gallium/state_trackers/dri/drm/dri2.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.c b/src/gallium/state_trackers/dri/common/dri_drawable.c index f255108..734bca2 100644 --- a/src/gallium/state_trackers/dri/common/dri_drawable.c +++ b/src/gallium/state_trackers/dri/common/dri_drawable.c @@ -73,7 +73,7 @@ dri_st_framebuffer_validate(struct st_context_iface *stctx, * checked. */ do { - lastStamp = drawable->dPriv->lastStamp; + lastStamp = drawable->base.stamp; new_stamp = (drawable->texture_stamp != lastStamp);
if (new_stamp || new_mask || screen->broken_invalidate) { @@ -91,7 +91,7 @@ dri_st_framebuffer_validate(struct st_context_iface *stctx, drawable->texture_stamp = lastStamp; drawable->texture_mask = statt_mask; } - } while (lastStamp != drawable->dPriv->lastStamp); + } while (lastStamp != drawable->base.stamp);
if (!out) return TRUE; diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c index a9d6a10..9bdb775 100644 --- a/src/gallium/state_trackers/dri/drm/dri2.c +++ b/src/gallium/state_trackers/dri/drm/dri2.c @@ -549,7 +549,7 @@ dri_image_allocate_textures(struct dri_context *ctx,
(*sPriv->image.loader->getBuffers) (dPriv, image_format, - &dPriv->dri2.stamp, + (uint32_t *) &drawable->base.stamp, dPriv->loaderPrivate, buffer_mask, &images);
dri-devel@lists.freedesktop.org