#include "xm_api.h"
#include "xm_st.h"
-#include "main/context.h"
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
+#include "util/u_atomic.h"
#include "xm_public.h"
#include <GL/glx.h>
static struct xm_driver driver;
static struct st_api *stapi;
+/* Default strict invalidate to false. This means we will not call
+ * XGetGeometry after every swapbuffers, which allows swapbuffers to
+ * remain asynchronous. For apps running at 100fps with synchronous
+ * swapping, a 10% boost is typical. For gears, I see closer to 20%
+ * speedup.
+ *
+ * Note that the work of copying data on swapbuffers doesn't disappear
+ * - this change just allows the X server to execute the PutImage
+ * asynchronously without us effectively blocked until its completion.
+ *
+ * This speeds up even llvmpipe's threaded rasterization as the
+ * swapbuffers operation was a large part of the serial component of
+ * an llvmpipe frame.
+ *
+ * The downside of this is correctness - applications which don't call
+ * glViewport on window resizes will get incorrect rendering. A
+ * better solution would be to have per-frame but asynchronous
+ * invalidation. Xcb almost looks as if it could provide this, but
+ * the API doesn't seem to quite be there.
+ */
+boolean xmesa_strict_invalidate = FALSE;
+
void xmesa_set_driver( const struct xm_driver *templ )
{
driver = *templ;
stapi = driver.create_st_api();
+
+ xmesa_strict_invalidate =
+ debug_get_bool_option("XMESA_STRICT_INVALIDATE", FALSE);
}
xmesa_get_param(struct st_manager *smapi,
enum st_manager_param param)
{
- return 0;
+ switch(param) {
+ case ST_MANAGER_BROKEN_INVALIDATE:
+ return !xmesa_strict_invalidate;
+ default:
+ return 0;
+ }
}
static XMesaDisplay
Status stat;
pipe_mutex_lock(xmdpy->mutex);
- XSync(b->xm_visual->display, 0); /* added for Chromium */
stat = get_drawable_size(dpy, b->ws.drawable, width, height);
pipe_mutex_unlock(xmdpy->mutex);
{
const enum pipe_texture_target target = PIPE_TEXTURE_2D;
const unsigned tex_usage = PIPE_BIND_DEPTH_STENCIL;
- const unsigned geom_flags = (PIPE_TEXTURE_GEOM_NON_SQUARE |
- PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO);
const unsigned sample_count = 0;
enum pipe_format formats[8], fmt;
int count, i;
for (i = 0; i < count; i++) {
if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i],
target, sample_count,
- tex_usage, geom_flags)) {
+ tex_usage)) {
fmt = formats[i];
break;
}
/**
* Allocate a new XMesaBuffer object which corresponds to the given drawable.
- * Note that XMesaBuffer is derived from GLframebuffer.
+ * Note that XMesaBuffer is derived from struct gl_framebuffer.
* The new XMesaBuffer will not have any size (Width=Height=0).
*
* \param d the corresponding X drawable (window or pixmap)
if (!b)
return NULL;
- b->ws.drawable = d;
+ b->ws.drawable = b->drawable = d;
b->ws.visual = vis->visinfo->visual;
b->ws.depth = vis->visinfo->depth;
/* RGB WINDOW:
* We support RGB rendering into almost any kind of visual.
*/
- const int xclass = v->mesa_visual.visualType;
+ const int xclass = v->visualType;
if (xclass != GLX_TRUE_COLOR && xclass == !GLX_DIRECT_COLOR) {
_mesa_warning(NULL,
"XMesa: RGB mode rendering not supported in given visual.\n");
v->mesa_visual.redMask = visinfo->red_mask;
v->mesa_visual.greenMask = visinfo->green_mask;
v->mesa_visual.blueMask = visinfo->blue_mask;
- v->mesa_visual.visualID = visinfo->visualid;
- v->mesa_visual.screen = visinfo->screen;
+ v->visualID = visinfo->visualid;
+ v->screen = visinfo->screen;
#if !(defined(__cplusplus) || defined(c_plusplus))
- v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
+ v->visualType = xmesa_convert_from_x_visual_type(visinfo->class);
#else
- v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
+ v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
#endif
v->mesa_visual.visualRating = visualCaveat;
(void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
{
- const int xclass = v->mesa_visual.visualType;
+ const int xclass = v->visualType;
if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
red_bits = _mesa_bitcount(GET_REDMASK(v));
green_bits = _mesa_bitcount(GET_GREENMASK(v));
alpha_bits = v->mesa_visual.alphaBits;
}
- _mesa_initialize_visual( &v->mesa_visual,
- db_flag, stereo_flag,
- red_bits, green_bits,
- blue_bits, alpha_bits,
- depth_size,
- stencil_size,
- accum_red_size, accum_green_size,
- accum_blue_size, accum_alpha_size,
- 0 );
+ /* initialize visual */
+ {
+ struct gl_config *vis = &v->mesa_visual;
+
+ vis->rgbMode = GL_TRUE;
+ vis->doubleBufferMode = db_flag;
+ vis->stereoMode = stereo_flag;
+
+ vis->redBits = red_bits;
+ vis->greenBits = green_bits;
+ vis->blueBits = blue_bits;
+ vis->alphaBits = alpha_bits;
+ vis->rgbBits = red_bits + green_bits + blue_bits;
+
+ vis->indexBits = 0;
+ vis->depthBits = depth_size;
+ vis->stencilBits = stencil_size;
+
+ vis->accumRedBits = accum_red_size;
+ vis->accumGreenBits = accum_green_size;
+ vis->accumBlueBits = accum_blue_size;
+ vis->accumAlphaBits = accum_alpha_size;
+
+ vis->haveAccumBuffer = accum_red_size > 0;
+ vis->haveDepthBuffer = depth_size > 0;
+ vis->haveStencilBuffer = stencil_size > 0;
+
+ vis->numAuxBuffers = 0;
+ vis->level = 0;
+ vis->sampleBuffers = 0;
+ vis->samples = 0;
+ }
v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
if (db_flag)
}
+/**
+ * Return the informative name.
+ */
+const char *
+xmesa_get_name(void)
+{
+ return stapi->name;
+}
+
+
/**
* Do per-display initializations.
*/
* \return an XMesaContext or NULL if error.
*/
PUBLIC
-XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
+XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list,
+ GLuint major, GLuint minor,
+ GLuint profileMask, GLuint contextFlags)
{
XMesaDisplay xmdpy = xmesa_init_display(v->display);
+ struct st_context_attribs attribs;
XMesaContext c;
if (!xmdpy)
return NULL;
- /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
+ /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */
c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
if (!c)
return NULL;
c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */
c->xm_read_buffer = NULL;
+ memset(&attribs, 0, sizeof(attribs));
+ attribs.profile = ST_PROFILE_DEFAULT;
+ attribs.visual = v->stvis;
+ attribs.major = major;
+ attribs.minor = minor;
+ if (contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
+ attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
+ if (contextFlags & GLX_CONTEXT_DEBUG_BIT_ARB)
+ attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
+ if (contextFlags & GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB)
+ attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS;
+ if (profileMask & GLX_CONTEXT_CORE_PROFILE_BIT_ARB)
+ attribs.flags |= ST_CONTEXT_FLAG_CORE_PROFILE;
+ if (profileMask & GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
+ attribs.flags |= ST_CONTEXT_FLAG_COMPATIBLE_PROFILE;
+
c->st = stapi->create_context(stapi, xmdpy->smapi,
- &v->stvis, (share_list) ? share_list->st : NULL);
+ &attribs, (share_list) ? share_list->st : NULL);
if (c->st == NULL)
goto fail;
}
+/**
+ * Notify the binding context to validate the buffer.
+ */
+void
+xmesa_notify_invalid_buffer(XMesaBuffer b)
+{
+ p_atomic_inc(&b->stfb->stamp);
+}
+
+
/**
* Query the current drawable size and notify the binding context.
*/
void
xmesa_check_buffer_size(XMesaBuffer b)
{
- XMesaContext xmctx = XMesaGetCurrentContext();
+ GLuint old_width, old_height;
if (b->type == PBUFFER)
return;
+ old_width = b->width;
+ old_height = b->height;
+
xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height);
- if (xmctx && xmctx->xm_buffer == b)
- xmctx->st->notify_invalid_framebuffer(xmctx->st, b->stfb);
+
+ if (b->width != old_width || b->height != old_height)
+ xmesa_notify_invalid_buffer(b);
}
XMesaContext xmctx = XMesaGetCurrentContext();
if (xmctx && xmctx->xm_buffer == b) {
- xmctx->st->flush( xmctx->st,
- PIPE_FLUSH_RENDER_CACHE |
- PIPE_FLUSH_SWAPBUFFERS |
- PIPE_FLUSH_FRAME,
- NULL);
+ xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL);
}
xmesa_swap_st_framebuffer(b->stfb);
XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display);
struct pipe_fence_handle *fence = NULL;
- c->st->flush(c->st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
+ c->st->flush(c->st, ST_FLUSH_FRONT, &fence);
if (fence) {
- xmdpy->screen->fence_finish(xmdpy->screen, fence, 0);
+ xmdpy->screen->fence_finish(xmdpy->screen, fence,
+ PIPE_TIMEOUT_INFINITE);
xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL);
}
XFlush( c->xm_visual->display );