On Mon, Nov 04, 2013 at 06:23:27PM -0800, Keith Packard wrote: > These provide an interface between the driver and the loader to allocate > color buffers through the DRIimage extension interface rather than through a > loader-specific extension (as is used by DRI2, for instance). > > The driver uses the loader 'getBuffers' interface to allocate color buffers. > > The loader uses the createNewScreen2, createNewDrawable, createNewContext, > getAPIMask and createContextAttribs APIS (mostly shared with DRI2). > > This interface will work with the DRI3 loader, and should also work with GBM > and other loaders so that drivers need not be customized for each new loader > interface, as long as they provide this image interface. > > Signed-off-by: Keith Packard <keithp@xxxxxxxxxx> > --- > include/GL/internal/dri_interface.h | 112 +++++++++++++++++++++++++ > src/mesa/drivers/dri/common/dri_util.c | 113 +++++++++++++++++++++++++ > src/mesa/drivers/dri/common/dri_util.h | 6 ++ > src/mesa/drivers/dri/i915/intel_context.c | 111 ++++++++++++++++++++++++- > src/mesa/drivers/dri/i915/intel_mipmap_tree.c | 33 ++++++++ > src/mesa/drivers/dri/i915/intel_mipmap_tree.h | 8 ++ > src/mesa/drivers/dri/i915/intel_screen.c | 1 + > src/mesa/drivers/dri/i965/brw_context.c | 114 ++++++++++++++++++++++++-- > src/mesa/drivers/dri/i965/brw_context.h | 16 ++-- > src/mesa/drivers/dri/i965/intel_mipmap_tree.c | 61 ++++++++++++++ > src/mesa/drivers/dri/i965/intel_mipmap_tree.h | 8 ++ > src/mesa/drivers/dri/i965/intel_screen.c | 5 +- > 12 files changed, 568 insertions(+), 20 deletions(-) > > diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h > index 907aeca..8fc1fa6 100644 > --- a/include/GL/internal/dri_interface.h > +++ b/include/GL/internal/dri_interface.h > @@ -86,6 +86,10 @@ typedef struct __DRIdri2LoaderExtensionRec __DRIdri2LoaderExtension; > typedef struct __DRI2flushExtensionRec __DRI2flushExtension; > typedef struct __DRI2throttleExtensionRec __DRI2throttleExtension; > > + > +typedef struct __DRIimageLoaderExtensionRec __DRIimageLoaderExtension; > +typedef struct __DRIimageDriverExtensionRec __DRIimageDriverExtension; > + > /*@}*/ > > > @@ -1288,4 +1292,112 @@ typedef struct __DRIDriverVtableExtensionRec { > const struct __DriverAPIRec *vtable; > } __DRIDriverVtableExtension; > > +/** > + * Image Loader extension. Drivers use this to allocate color buffers > + */ > + > +#define __DRI_DRIVER_EXTENSIONS "__driDriverExtensions" > + > +enum __DRIimageBufferMask { > + __DRI_IMAGE_BUFFER_BACK = (1 << 0), > + __DRI_IMAGE_BUFFER_FRONT = (1 << 1) > +}; > + > +struct __DRIimageList { > + __DRIimage *back; > + __DRIimage *front; > +}; > + > +#define __DRI_IMAGE_LOADER "DRI_IMAGE_LOADER" > +#define __DRI_IMAGE_LOADER_VERSION 1 > + > +struct __DRIimageLoaderExtensionRec { > + __DRIextension base; > + > + /** > + * Allocate color buffers. > + * > + * \param driDrawable > + * \param width Width of allocated buffers > + * \param height Height of allocated buffers > + * \param format one of __DRI_IMAGE_FORMAT_* > + * \param stamp Address of variable to be updated when > + * getBuffers must be called again > + * \param loaderPrivate The loaderPrivate for driDrawable > + * \param buffer_mask Set of buffers to allocate > + * \param buffers Returned buffers > + */ > + int (*getBuffers)(__DRIdrawable *driDrawable, > + int *width, int *height, > + unsigned int format, > + uint32_t *stamp, > + void *loaderPrivate, > + uint32_t buffer_mask, > + struct __DRIimageList *buffers); > + > + /** > + * Flush pending front-buffer rendering > + * > + * Any rendering that has been performed to the > + * fake front will be flushed to the front > + * > + * \param driDrawable Drawable whose front-buffer is to be flushed > + * \param loaderPrivate Loader's private data that was previously passed > + * into __DRIdri2ExtensionRec::createNewDrawable > + */ > + void (*flushFrontBuffer)(__DRIdrawable *driDrawable, void *loaderPrivate); > +}; > + > +/** > + * DRI extension. > + */ > + > +//struct gl_context; > +//struct dd_function_table; > + > +typedef __DRIscreen * > +(*__DRIcreateNewScreen2)(int screen, int fd, > + const __DRIextension **extensions, > + const __DRIextension **driver_extensions, > + const __DRIconfig ***driver_configs, > + void *loaderPrivate); > + > +typedef __DRIdrawable * > +(*__DRIcreateNewDrawable)(__DRIscreen *screen, > + const __DRIconfig *config, > + void *loaderPrivate); > + > +typedef __DRIcontext * > +(*__DRIcreateNewContext)(__DRIscreen *screen, > + const __DRIconfig *config, > + __DRIcontext *shared, > + void *loaderPrivate); > + > +typedef __DRIcontext * > +(*__DRIcreateContextAttribs)(__DRIscreen *screen, > + int api, > + const __DRIconfig *config, > + __DRIcontext *shared, > + unsigned num_attribs, > + const uint32_t *attribs, > + unsigned *error, > + void *loaderPrivate); > + > +typedef unsigned int > +(*__DRIgetAPIMask)(__DRIscreen *screen); > + > +#define __DRI_IMAGE_DRIVER "DRI_IMAGE_DRIVER" > +#define __DRI_IMAGE_DRIVER_VERSION 1 > + > +struct __DRIimageDriverExtensionRec { > + __DRIextension base; > + > + /* Common DRI functions, shared with DRI2 */ > + __DRIcreateNewScreen2 createNewScreen2; > + __DRIcreateNewDrawable createNewDrawable; > + __DRIcreateNewContext createNewContext; > + __DRIcreateContextAttribs createContextAttribs; > + __DRIgetAPIMask getAPIMask; > +}; > + > #endif > diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c > index 76c8ae5..d8cb7f6 100644 > --- a/src/mesa/drivers/dri/common/dri_util.c > +++ b/src/mesa/drivers/dri/common/dri_util.c > @@ -854,3 +854,116 @@ driImageFormatToGLFormat(uint32_t image_format) > return MESA_FORMAT_NONE; > } > } > + > +/* > + * Copyright © 2013 Keith Packard > + * > + * Permission to use, copy, modify, distribute, and sell this software and its > + * documentation for any purpose is hereby granted without fee, provided that > + * the above copyright notice appear in all copies and that both that copyright > + * notice and this permission notice appear in supporting documentation, and > + * that the name of the copyright holders not be used in advertising or > + * publicity pertaining to distribution of the software without specific, > + * written prior permission. The copyright holders make no representations > + * about the suitability of this software for any purpose. It is provided "as > + * is" without express or implied warranty. > + * > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, > + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO > + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR > + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, > + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER > + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE > + * OF THIS SOFTWARE. > + */ > + > +PUBLIC const char __imageConfigOptions[] = > + DRI_CONF_BEGIN > + DRI_CONF_SECTION_PERFORMANCE > + DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1) > + DRI_CONF_SECTION_END > + DRI_CONF_END; > + > +static void > +setup_image_loader_extensions(__DRIscreen *psp, > + const __DRIextension *const*extensions) > +{ > + int i; > + > + for (i = 0; extensions[i]; i++) { > + if (strcmp(extensions[i]->name, __DRI_IMAGE_LOADER) == 0) > + psp->image.loader = (__DRIimageLoaderExtension *) extensions[i]; > + } > +} > + > +static __DRIscreen * > +image_create_new_screen_2(int scrn, int fd, > + const __DRIextension **extensions, > + const __DRIextension **driver_extensions, > + const __DRIconfig ***driver_configs, void *data) > +{ > + static const __DRIextension *emptyExtensionList[] = { NULL }; > + __DRIscreen *psp; > + drmVersionPtr version; > + > + psp = calloc(1, sizeof(*psp)); > + if (!psp) > + return NULL; > + > + /* By default, use the global driDriverAPI symbol (non-megadrivers). */ > + psp->driver = globalDriverAPI; > + > + /* If the driver exposes its vtable through its extensions list > + * (megadrivers), use that instead. > + */ > + if (driver_extensions) { > + for (int i = 0; driver_extensions[i]; i++) { > + if (strcmp(driver_extensions[i]->name, __DRI_DRIVER_VTABLE) == 0) { > + psp->driver = > + ((__DRIDriverVtableExtension *)driver_extensions[i])->vtable; > + } > + } > + } > + > + setupLoaderExtensions(psp, extensions); > + setup_image_loader_extensions(psp, extensions); > + > + version = drmGetVersion(fd); > + if (version) { > + psp->drm_version.major = version->version_major; > + psp->drm_version.minor = version->version_minor; > + psp->drm_version.patch = version->version_patchlevel; > + drmFreeVersion(version); > + } > + > + psp->loaderPrivate = data; > + > + psp->extensions = emptyExtensionList; > + psp->fd = fd; > + psp->myNum = scrn; > + > + psp->api_mask = (1 << __DRI_API_OPENGL); This is another reason this just needs to be dri2CreateNewScreen2. The above regresses GLES* support. I tried with your ~keithp dri3 branch and using dri2CreateNewScreen2 brings back the GLESes. > + *driver_configs = psp->driver->InitScreen(psp); > + if (*driver_configs == NULL) { > + free(psp); > + return NULL; > + } > + > + driParseOptionInfo(&psp->optionInfo, __imageConfigOptions); > + driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "image"); > + > + return psp; > +} > + > + > +/** Image driver interface */ > +const __DRIimageDriverExtension driImageDriverExtension = { > + .base = { __DRI_IMAGE_DRIVER, __DRI_IMAGE_DRIVER_VERSION }, > + > + .createNewScreen2 = image_create_new_screen_2, > + .createNewDrawable = driCreateNewDrawable, > + .createNewContext = driCreateNewContext, > + .getAPIMask = driGetAPIMask, > + .createContextAttribs = driCreateContextAttribs, > +}; Having written the GBM and Wayland suport for this, it's pretty clear that we just want to use __DRIdri2Extension instead of duplicating these functions. Support for the __DRIimage based getBuffers is a small incremental patch to src/egl/drivers/dri2: src/egl/drivers/dri2/egl_dri2.c | 29 +++++-- src/egl/drivers/dri2/egl_dri2.h | 5 +- src/egl/drivers/dri2/platform_drm.c | 50 ++++++++++-- src/egl/drivers/dri2/platform_wayland.c | 133 ++++++++++++++++++++++---------- src/gbm/backends/dri/gbm_dri.c | 32 +++++++- src/gbm/backends/dri/gbm_driint.h | 11 ++- 6 files changed, 199 insertions(+), 61 deletions(-) The problem is that technically we would have to do: if (dri2_dpy->image_driver) { /* use dri2_dpy->image_driver->createContextAttribs } else if (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) { /* use dri2_dpy->dri2->createContextAttribs all over the place even though they end up calling the same function. The only real purpose of __DRIimageDriverExtension is to let the loader know that the DRI driver supports and will use __DRIimageLoaderExtension if provided, but we can just expose an empty dummy extension to indicate that. > diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h > index fd40769..6f5cd87 100644 > --- a/src/mesa/drivers/dri/common/dri_util.h > +++ b/src/mesa/drivers/dri/common/dri_util.h > @@ -174,6 +174,10 @@ struct __DRIscreenRec { > __DRIuseInvalidateExtension *useInvalidate; > } dri2; > > + struct { > + __DRIimageLoaderExtension *loader; > + } image; > + > driOptionCache optionInfo; > driOptionCache optionCache; > > @@ -283,4 +287,6 @@ dri2InvalidateDrawable(__DRIdrawable *drawable); > extern void > driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv); > > +extern const __DRIimageDriverExtension driImageDriverExtension; > + > #endif /* _DRI_UTIL_H_ */ > diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c > index 1798bc7..8d369ff 100644 > --- a/src/mesa/drivers/dri/i915/intel_context.c > +++ b/src/mesa/drivers/dri/i915/intel_context.c > @@ -91,6 +91,8 @@ intelGetString(struct gl_context * ctx, GLenum name) > } > } > > +#define flushFront(screen) ((screen)->image.loader ? (screen)->image.loader->flushFrontBuffer : (screen)->dri2.loader->flushFrontBuffer) > + > static void > intel_flush_front(struct gl_context *ctx) > { > @@ -100,11 +102,10 @@ intel_flush_front(struct gl_context *ctx) > __DRIscreen *const screen = intel->intelScreen->driScrnPriv; > > if (intel->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { > - if (screen->dri2.loader->flushFrontBuffer != NULL && > + if (flushFront(screen) && > driDrawable && > driDrawable->loaderPrivate) { > - screen->dri2.loader->flushFrontBuffer(driDrawable, > - driDrawable->loaderPrivate); > + flushFront(screen)(driDrawable, driDrawable->loaderPrivate); > > /* We set the dirty bit in intel_prepare_render() if we're > * front buffer rendering once we get there. > @@ -114,6 +115,9 @@ intel_flush_front(struct gl_context *ctx) > } > } > > +static void > +intel_update_image_buffers(struct intel_context *intel, __DRIdrawable *drawable); > + > static unsigned > intel_bits_per_pixel(const struct intel_renderbuffer *rb) > { > @@ -194,7 +198,10 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) > if (unlikely(INTEL_DEBUG & DEBUG_DRI)) > fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); > > - intel_update_dri2_buffers(intel, drawable); > + if (screen->image.loader) > + intel_update_image_buffers(intel, drawable); > + else > + intel_update_dri2_buffers(intel, drawable); > > driUpdateFramebufferSize(&intel->ctx, drawable); > } > @@ -787,3 +794,99 @@ intel_process_dri2_buffer(struct intel_context *intel, > region); > intel_region_release(®ion); > } > + > +/** > + * \brief Query DRI Image loader to obtain a DRIdrawable's buffers. > + * > + * To determine which DRI buffers to request, examine the renderbuffers > + * attached to the drawable's framebuffer. Then request the buffers with > + * dri3 > + * > + * This is called from intel_update_renderbuffers(). > + * > + * \param drawable Drawable whose buffers are queried. > + * \param buffers [out] List of buffers returned by DRI2 query. > + * \param buffer_count [out] Number of buffers returned. > + * > + * \see intel_update_renderbuffers() > + */ > + > +static void > +intel_update_image_buffer(struct intel_context *intel, > + __DRIdrawable *drawable, > + struct intel_renderbuffer *rb, > + __DRIimage *buffer, > + enum __DRIimageBufferMask buffer_type) > +{ > + struct intel_region *region = buffer->region; > + > + if (!rb || !region) > + return; > + > + unsigned num_samples = rb->Base.Base.NumSamples; > + > + if (rb->mt && > + rb->mt->region && > + rb->mt->region == region) > + return; > + > + intel_miptree_release(&rb->mt); > + rb->mt = intel_miptree_create_for_image_buffer(intel, > + buffer_type, > + intel_rb_format(rb), > + num_samples, > + region); > +} > + > + > +static void > +intel_update_image_buffers(struct intel_context *intel, __DRIdrawable *drawable) > +{ > + struct gl_framebuffer *fb = drawable->driverPrivate; > + __DRIscreen *screen = intel->intelScreen->driScrnPriv; > + struct intel_renderbuffer *front_rb; > + struct intel_renderbuffer *back_rb; > + struct __DRIimageList images; > + unsigned int format; > + uint32_t buffer_mask = 0; > + > + front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); > + back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); > + > + if (back_rb) > + format = intel_rb_format(back_rb); > + else if (front_rb) > + format = intel_rb_format(front_rb); > + else > + return; > + > + if ((intel->is_front_buffer_rendering || intel->is_front_buffer_reading || !back_rb) && front_rb) > + buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; > + > + if (back_rb) > + buffer_mask |= __DRI_IMAGE_BUFFER_BACK; > + > + (*screen->image.loader->getBuffers) (drawable, > + &drawable->w, > + &drawable->h, > + driGLFormatToImageFormat(format), > + &drawable->dri2.stamp, > + drawable->loaderPrivate, > + buffer_mask, > + &images); > + > + if (images.front) { I think we should only look at image.front if the __DRI_IMAGE_BUFFER_FRONT bit is set. We never want to set up a front buffer that we didn't ask for and it seems wrong that the loader has to clear image.front, if the driver didn't ask for front. > + assert(front_rb); > + intel_update_image_buffer(intel, > + drawable, > + front_rb, > + images.front, > + __DRI_IMAGE_BUFFER_FRONT); > + } > + if (images.back) Same here. > + intel_update_image_buffer(intel, > + drawable, > + back_rb, > + images.back, > + __DRI_IMAGE_BUFFER_BACK); > +} > diff --git a/src/mesa/drivers/dri/i915/intel_mipmap_tree.c b/src/mesa/drivers/dri/i915/intel_mipmap_tree.c > index 8432b6d..66a7a92 100644 > --- a/src/mesa/drivers/dri/i915/intel_mipmap_tree.c > +++ b/src/mesa/drivers/dri/i915/intel_mipmap_tree.c > @@ -322,6 +322,39 @@ intel_miptree_create_for_dri2_buffer(struct intel_context *intel, > return mt; > } > > +/** > + * For a singlesample image buffer, this simply wraps the given region with a miptree. > + * > + * For a multisample image buffer, this wraps the given region with > + * a singlesample miptree, then creates a multisample miptree into which the > + * singlesample miptree is embedded as a child. > + */ > +struct intel_mipmap_tree* > +intel_miptree_create_for_image_buffer(struct intel_context *intel, > + enum __DRIimageBufferMask buffer_type, > + gl_format format, > + uint32_t num_samples, > + struct intel_region *region) > +{ > + struct intel_mipmap_tree *mt = NULL; > + > + /* Only the front and back buffers, which are color buffers, are allocated > + * through the image loader. > + */ > + assert(_mesa_get_format_base_format(format) == GL_RGB || > + _mesa_get_format_base_format(format) == GL_RGBA); > + > + mt = intel_miptree_create_for_bo(intel, > + region->bo, > + format, > + 0, > + region->width, > + region->height, > + region->pitch, > + region->tiling); > + return mt; > +} > + > struct intel_mipmap_tree* > intel_miptree_create_for_renderbuffer(struct intel_context *intel, > gl_format format, > diff --git a/src/mesa/drivers/dri/i915/intel_mipmap_tree.h b/src/mesa/drivers/dri/i915/intel_mipmap_tree.h > index 1142af6..35cad6d 100644 > --- a/src/mesa/drivers/dri/i915/intel_mipmap_tree.h > +++ b/src/mesa/drivers/dri/i915/intel_mipmap_tree.h > @@ -32,6 +32,7 @@ > > #include "intel_screen.h" > #include "intel_regions.h" > +#include "GL/internal/dri_interface.h" > > #ifdef __cplusplus > extern "C" { > @@ -258,6 +259,13 @@ intel_miptree_create_for_dri2_buffer(struct intel_context *intel, > gl_format format, > struct intel_region *region); > > +struct intel_mipmap_tree* > +intel_miptree_create_for_image_buffer(struct intel_context *intel, > + enum __DRIimageBufferMask buffer_type, > + gl_format format, > + uint32_t num_samples, > + struct intel_region *region); > + > /** > * Create a miptree appropriate as the storage for a non-texture renderbuffer. > * The miptree has the following properties: > diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c > index 12113c7..38badec 100644 > --- a/src/mesa/drivers/dri/i915/intel_screen.c > +++ b/src/mesa/drivers/dri/i915/intel_screen.c > @@ -1166,6 +1166,7 @@ static const struct __DRIDriverVtableExtensionRec i915_vtable = { > /* This is the table of extensions that the loader will dlsym() for. */ > static const __DRIextension *i915_driver_extensions[] = { > &driCoreExtension.base, > + &driImageDriverExtension.base, > &driDRI2Extension.base, > &i915_vtable.base, > &i915_config_options.base, > diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c > index 2557d10..f3bf67f 100644 > --- a/src/mesa/drivers/dri/i965/brw_context.c > +++ b/src/mesa/drivers/dri/i965/brw_context.c > @@ -151,6 +151,8 @@ intelInvalidateState(struct gl_context * ctx, GLuint new_state) > brw->NewGLState |= new_state; > } > > +#define flushFront(screen) ((screen)->image.loader ? (screen)->image.loader->flushFrontBuffer : (screen)->dri2.loader->flushFrontBuffer) > + > static void > intel_flush_front(struct gl_context *ctx) > { > @@ -160,8 +162,7 @@ intel_flush_front(struct gl_context *ctx) > __DRIscreen *const screen = brw->intelScreen->driScrnPriv; > > if (brw->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { > - if (screen->dri2.loader->flushFrontBuffer != NULL && > - driDrawable && > + if (flushFront(screen) && driDrawable && > driDrawable->loaderPrivate) { > > /* Resolve before flushing FAKE_FRONT_LEFT to FRONT_LEFT. > @@ -174,8 +175,7 @@ intel_flush_front(struct gl_context *ctx) > intel_resolve_for_dri2_flush(brw, driDrawable); > intel_batchbuffer_flush(brw); > > - screen->dri2.loader->flushFrontBuffer(driDrawable, > - driDrawable->loaderPrivate); > + flushFront(screen)(driDrawable, driDrawable->loaderPrivate); > > /* We set the dirty bit in intel_prepare_render() if we're > * front buffer rendering once we get there. > @@ -549,7 +549,7 @@ brw_process_driconf_options(struct brw_context *brw) > driQueryOptionb(options, "disable_glsl_line_continuations"); > } > > -bool > +GLboolean > brwCreateContext(gl_api api, > const struct gl_config *mesaVis, > __DRIcontext *driContextPriv, > @@ -979,6 +979,9 @@ intel_process_dri2_buffer(struct brw_context *brw, > const char *buffer_name); > > static void > +intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable); > + > +static void > intel_update_dri2_buffers(struct brw_context *brw, __DRIdrawable *drawable) > { > struct gl_framebuffer *fb = drawable->driverPrivate; > @@ -1038,6 +1041,7 @@ void > intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) > { > struct brw_context *brw = context->driverPrivate; > + __DRIscreen *screen = brw->intelScreen->driScrnPriv; > > /* Set this up front, so that in case our buffers get invalidated > * while we're getting new buffers, we don't clobber the stamp and > @@ -1047,7 +1051,10 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) > if (unlikely(INTEL_DEBUG & DEBUG_DRI)) > fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); > > - intel_update_dri2_buffers(brw, drawable); > + if (screen->image.loader) > + intel_update_image_buffers(brw, drawable); > + else > + intel_update_dri2_buffers(brw, drawable); > > driUpdateFramebufferSize(&brw->ctx, drawable); > } > @@ -1253,3 +1260,98 @@ intel_process_dri2_buffer(struct brw_context *brw, > region); > intel_region_release(®ion); > } > + > +/** > + * \brief Query DRI image loader to obtain a DRIdrawable's buffers. > + * > + * To determine which DRI buffers to request, examine the renderbuffers > + * attached to the drawable's framebuffer. Then request the buffers from > + * the image loader > + * > + * This is called from intel_update_renderbuffers(). > + * > + * \param drawable Drawable whose buffers are queried. > + * \param buffers [out] List of buffers returned by DRI2 query. > + * \param buffer_count [out] Number of buffers returned. > + * > + * \see intel_update_renderbuffers() > + */ > + > +static void > +intel_update_image_buffer(struct brw_context *intel, > + __DRIdrawable *drawable, > + struct intel_renderbuffer *rb, > + __DRIimage *buffer, > + enum __DRIimageBufferMask buffer_type) > +{ > + struct intel_region *region = buffer->region; > + > + if (!rb || !region) > + return; > + > + unsigned num_samples = rb->Base.Base.NumSamples; > + > + if (rb->mt && > + rb->mt->region && > + rb->mt->region == region) > + return; > + > + intel_miptree_release(&rb->mt); > + rb->mt = intel_miptree_create_for_image_buffer(intel, > + buffer_type, > + intel_rb_format(rb), > + num_samples, > + region); > +} > + > +static void > +intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable) > +{ > + struct gl_framebuffer *fb = drawable->driverPrivate; > + __DRIscreen *screen = brw->intelScreen->driScrnPriv; > + struct intel_renderbuffer *front_rb; > + struct intel_renderbuffer *back_rb; > + struct __DRIimageList images; > + unsigned int format; > + uint32_t buffer_mask = 0; > + > + front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); > + back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); > + > + if (back_rb) > + format = intel_rb_format(back_rb); > + else if (front_rb) > + format = intel_rb_format(front_rb); > + else > + return; > + > + if ((brw->is_front_buffer_rendering || brw->is_front_buffer_reading || !back_rb) && front_rb) > + buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; > + > + if (back_rb) > + buffer_mask |= __DRI_IMAGE_BUFFER_BACK; > + > + (*screen->image.loader->getBuffers) (drawable, > + &drawable->w, > + &drawable->h, > + driGLFormatToImageFormat(format), > + &drawable->dri2.stamp, > + drawable->loaderPrivate, > + buffer_mask, > + &images); > + > + if (images.front) { > + assert(front_rb); > + intel_update_image_buffer(brw, > + drawable, > + front_rb, > + images.front, > + __DRI_IMAGE_BUFFER_FRONT); > + } > + if (images.back) > + intel_update_image_buffer(brw, > + drawable, > + back_rb, > + images.back, > + __DRI_IMAGE_BUFFER_BACK); > +} > diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h > index bec4d6b..1ecbfb7 100644 > --- a/src/mesa/drivers/dri/i965/brw_context.h > +++ b/src/mesa/drivers/dri/i965/brw_context.h > @@ -1477,14 +1477,14 @@ void intel_prepare_render(struct brw_context *brw); > void intel_resolve_for_dri2_flush(struct brw_context *brw, > __DRIdrawable *drawable); > > -bool brwCreateContext(gl_api api, > - const struct gl_config *mesaVis, > - __DRIcontext *driContextPriv, > - unsigned major_version, > - unsigned minor_version, > - uint32_t flags, > - unsigned *error, > - void *sharedContextPrivate); > +GLboolean brwCreateContext(gl_api api, > + const struct gl_config *mesaVis, > + __DRIcontext *driContextPriv, > + unsigned major_version, > + unsigned minor_version, > + uint32_t flags, > + unsigned *error, > + void *sharedContextPrivate); > > /*====================================================================== > * brw_misc_state.c > diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c > index 2f5e04f..08dbe88 100644 > --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c > +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c > @@ -725,6 +725,67 @@ intel_miptree_create_for_dri2_buffer(struct brw_context *brw, > return multisample_mt; > } > > +/** > + * For a singlesample image buffer, this simply wraps the given region with a miptree. > + * > + * For a multisample image buffer, this wraps the given region with > + * a singlesample miptree, then creates a multisample miptree into which the > + * singlesample miptree is embedded as a child. > + */ > +struct intel_mipmap_tree* > +intel_miptree_create_for_image_buffer(struct brw_context *intel, > + enum __DRIimageBufferMask buffer_type, > + gl_format format, > + uint32_t num_samples, > + struct intel_region *region) > +{ > + struct intel_mipmap_tree *singlesample_mt = NULL; > + struct intel_mipmap_tree *multisample_mt = NULL; > + > + /* Only the front and back buffers, which are color buffers, are allocated > + * through the image loader. > + */ > + assert(_mesa_get_format_base_format(format) == GL_RGB || > + _mesa_get_format_base_format(format) == GL_RGBA); > + > + singlesample_mt = intel_miptree_create_for_bo(intel, > + region->bo, > + format, > + 0, > + region->width, > + region->height, > + region->pitch, > + region->tiling); > + if (!singlesample_mt) > + return NULL; > + > + intel_region_reference(&singlesample_mt->region, region); > + > + if (num_samples == 0) > + return singlesample_mt; > + > + multisample_mt = intel_miptree_create_for_renderbuffer(intel, > + format, > + region->width, > + region->height, > + num_samples); > + if (!multisample_mt) { > + intel_miptree_release(&singlesample_mt); > + return NULL; > + } > + > + 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); > + } > + > + return multisample_mt; > +} > + > struct intel_mipmap_tree* > intel_miptree_create_for_renderbuffer(struct brw_context *brw, > gl_format format, > diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h > index d718125..8777a8c 100644 > --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h > +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h > @@ -32,6 +32,7 @@ > > #include "intel_regions.h" > #include "intel_resolve_map.h" > +#include <GL/internal/dri_interface.h> > > #ifdef __cplusplus > extern "C" { > @@ -529,6 +530,13 @@ intel_miptree_create_for_dri2_buffer(struct brw_context *brw, > uint32_t num_samples, > struct intel_region *region); > > +struct intel_mipmap_tree* > +intel_miptree_create_for_image_buffer(struct brw_context *intel, > + enum __DRIimageBufferMask buffer_type, > + gl_format format, > + uint32_t num_samples, > + struct intel_region *region); > + > /** > * Create a miptree appropriate as the storage for a non-texture renderbuffer. > * The miptree has the following properties: > diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c > index f9339c1..7571921 100644 > --- a/src/mesa/drivers/dri/i965/intel_screen.c > +++ b/src/mesa/drivers/dri/i965/intel_screen.c > @@ -1176,7 +1176,8 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp) > { > struct intel_screen *intelScreen; > > - if (psp->dri2.loader->base.version <= 2 || > + if (psp->image.loader) { > + } else if (psp->dri2.loader->base.version <= 2 || > psp->dri2.loader->getBuffersWithFormat == NULL) { > fprintf(stderr, > "\nERROR! DRI2 loader with getBuffersWithFormat() " > @@ -1264,7 +1265,6 @@ intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) > free(intelBuffer); > } > > - > static const struct __DriverAPIRec brw_driver_api = { > .InitScreen = intelInitScreen2, > .DestroyScreen = intelDestroyScreen, > @@ -1285,6 +1285,7 @@ static const struct __DRIDriverVtableExtensionRec brw_vtable = { > > static const __DRIextension *brw_driver_extensions[] = { > &driCoreExtension.base, > + &driImageDriverExtension.base, > &driDRI2Extension.base, > &brw_vtable.base, > &brw_config_options.base, > -- > 1.8.4.2 > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel