summaryrefslogtreecommitdiff
path: root/src/glx/glx_pbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glx/glx_pbuffer.c')
-rw-r--r--src/glx/glx_pbuffer.c372
1 files changed, 211 insertions, 161 deletions
diff --git a/src/glx/glx_pbuffer.c b/src/glx/glx_pbuffer.c
index c145ee92405..dc64ab64701 100644
--- a/src/glx/glx_pbuffer.c
+++ b/src/glx/glx_pbuffer.c
@@ -38,6 +38,9 @@
#include <limits.h>
#include "glxextensions.h"
+#include <X11/Xlib-xcb.h>
+#include <xcb/xproto.h>
+
#ifdef GLX_USE_APPLEGL
#include <pthread.h>
#include "apple/apple_glx_drawable.h"
@@ -45,16 +48,12 @@
#include "glx_error.h"
-#ifndef GLX_USE_APPLEGL
+#if !defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE)
/**
* Change a drawable's attribute.
*
* This function is used to implement \c glXSelectEvent and
* \c glXSelectEventSGIX.
- *
- * \note
- * This function dynamically determines whether to use the SGIX_pbuffer
- * version of the protocol or the GLX 1.3 version of the protocol.
*/
static void
ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
@@ -78,31 +77,14 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
LockDisplay(dpy);
- if (priv->minorVersion >= 3) {
- xGLXChangeDrawableAttributesReq *req;
-
- GetReqExtra(GLXChangeDrawableAttributes, 8 * num_attribs, req);
- output = (CARD32 *) (req + 1);
-
- req->reqType = opcode;
- req->glxCode = X_GLXChangeDrawableAttributes;
- req->drawable = drawable;
- req->numAttribs = (CARD32) num_attribs;
- }
- else {
- xGLXVendorPrivateWithReplyReq *vpreq;
-
- GetReqExtra(GLXVendorPrivateWithReply, 8 + (8 * num_attribs), vpreq);
- output = (CARD32 *) (vpreq + 1);
-
- vpreq->reqType = opcode;
- vpreq->glxCode = X_GLXVendorPrivateWithReply;
- vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX;
+ xGLXChangeDrawableAttributesReq *req;
+ GetReqExtra(GLXChangeDrawableAttributes, 8 * num_attribs, req);
+ output = (CARD32 *) (req + 1);
- output[0] = (CARD32) drawable;
- output[1] = num_attribs;
- output += 2;
- }
+ req->reqType = opcode;
+ req->glxCode = X_GLXChangeDrawableAttributes;
+ req->drawable = drawable;
+ req->numAttribs = (CARD32) num_attribs;
(void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs);
@@ -168,7 +150,7 @@ determineTextureFormat(const int *attribs, int numAttribs)
static GLboolean
CreateDRIDrawable(Display *dpy, struct glx_config *config,
- XID drawable, XID glxdrawable,
+ XID drawable, XID glxdrawable, int type,
const int *attrib_list, size_t num_attribs)
{
#ifdef GLX_DIRECT_RENDERING
@@ -185,39 +167,37 @@ CreateDRIDrawable(Display *dpy, struct glx_config *config,
if (psc->driScreen == NULL)
return GL_TRUE;
- pdraw = psc->driScreen->createDrawable(psc, drawable,
- glxdrawable, config);
+ pdraw = psc->driScreen->createDrawable(psc, drawable, glxdrawable,
+ type, config);
if (pdraw == NULL) {
fprintf(stderr, "failed to create drawable\n");
return GL_FALSE;
}
if (__glxHashInsert(priv->drawHash, glxdrawable, pdraw)) {
- (*pdraw->destroyDrawable) (pdraw);
+ pdraw->destroyDrawable(pdraw);
return GL_FALSE;
}
pdraw->textureTarget = determineTextureTarget(attrib_list, num_attribs);
pdraw->textureFormat = determineTextureFormat(attrib_list, num_attribs);
+
+ pdraw->refcount = 1;
#endif
return GL_TRUE;
}
static void
-DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable)
+DestroyDRIDrawable(Display *dpy, GLXDrawable drawable)
{
#ifdef GLX_DIRECT_RENDERING
struct glx_display *const priv = __glXInitialize(dpy);
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
- XID xid;
if (priv != NULL && pdraw != NULL) {
- xid = pdraw->xDrawable;
- (*pdraw->destroyDrawable) (pdraw);
+ pdraw->destroyDrawable(pdraw);
__glxHashDelete(priv->drawHash, drawable);
- if (destroy_xdrawable)
- XFreePixmap(priv->dpy, xid);
}
#endif
}
@@ -228,10 +208,6 @@ DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable)
* This function is used to implement \c glXGetSelectedEvent and
* \c glXGetSelectedEventSGIX.
*
- * \note
- * This function dynamically determines whether to use the SGIX_pbuffer
- * version of the protocol or the GLX 1.3 version of the protocol.
- *
* \todo
* The number of attributes returned is likely to be small, probably less than
* 10. Given that, this routine should try to use an array on the stack to
@@ -263,6 +239,7 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
* generated."
*/
if (drawable == 0) {
+ XNoOp(dpy);
__glXSendError(dpy, GLXBadDrawable, 0, X_GLXGetDrawableAttributes, false);
return 0;
}
@@ -293,6 +270,7 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
if (pdraw == NULL || gc == &dummyContext || gc->currentDpy != dpy ||
(gc->currentDrawable != drawable &&
gc->currentReadable != drawable)) {
+ XNoOp(dpy);
__glXSendError(dpy, GLXBadDrawable, drawable,
X_GLXGetDrawableAttributes, false);
return 0;
@@ -303,45 +281,31 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
if (psc->driScreen->getBufferAge != NULL)
*value = psc->driScreen->getBufferAge(pdraw);
- return 0;
+ return 1;
}
if (pdraw) {
if (attribute == GLX_SWAP_INTERVAL_EXT) {
*value = pdraw->psc->driScreen->getSwapInterval(pdraw);
- return 0;
+ return 1;
} else if (attribute == GLX_MAX_SWAP_INTERVAL_EXT) {
- *value = INT_MAX;
- return 0;
+ *value = pdraw->psc->driScreen->maxSwapInterval;
+ return 1;
} else if (attribute == GLX_LATE_SWAPS_TEAR_EXT) {
*value = __glXExtensionBitIsEnabled(pdraw->psc,
EXT_swap_control_tear_bit);
- return 0;
+ return 1;
}
}
#endif
LockDisplay(dpy);
- if (priv->minorVersion >= 3) {
- xGLXGetDrawableAttributesReq *req;
-
- GetReq(GLXGetDrawableAttributes, req);
- req->reqType = opcode;
- req->glxCode = X_GLXGetDrawableAttributes;
- req->drawable = drawable;
- }
- else {
- xGLXVendorPrivateWithReplyReq *vpreq;
-
- GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
- data = (CARD32 *) (vpreq + 1);
- data[0] = (CARD32) drawable;
-
- vpreq->reqType = opcode;
- vpreq->glxCode = X_GLXVendorPrivateWithReply;
- vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
- }
+ xGLXGetDrawableAttributesReq *req;
+ GetReq(GLXGetDrawableAttributes, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXGetDrawableAttributes;
+ req->drawable = drawable;
_XReply(dpy, (xReply *) & reply, 0, False);
@@ -353,7 +317,7 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
length = reply.length;
if (length) {
- num_attributes = (priv->minorVersion > 2) ? reply.numAttribs : length / 2;
+ num_attributes = reply.numAttribs;
data = malloc(length * sizeof(CARD32));
if (data == NULL) {
/* Throw data on the floor */
@@ -391,9 +355,41 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable,
UnlockDisplay(dpy);
SyncHandle();
+#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
+ if (pdraw && attribute == GLX_FBCONFIG_ID && !found) {
+ /* If we failed to lookup the GLX_FBCONFIG_ID, it may be because the drawable is
+ * a bare Window, so try differently by first figure out its visual, then GLX
+ * visual like driInferDrawableConfig does.
+ */
+ xcb_get_window_attributes_cookie_t cookie = { 0 };
+ xcb_get_window_attributes_reply_t *attr = NULL;
+
+ xcb_connection_t *conn = XGetXCBConnection(dpy);
+
+ if (conn) {
+ cookie = xcb_get_window_attributes(conn, drawable);
+ attr = xcb_get_window_attributes_reply(conn, cookie, NULL);
+ if (attr) {
+ /* Find the Window's GLX Visual */
+ struct glx_config *conf = glx_config_find_visual(pdraw->psc->configs, attr->visual);
+ free(attr);
+
+ if (conf)
+ *value = conf->fbconfigID;
+ }
+ }
+ }
+#endif
+
return found;
}
+static int dummyErrorHandler(Display *display, xError *err, XExtCodes *codes,
+ int *ret_code)
+{
+ return 1; /* do nothing */
+}
+
static void
protocolDestroyDrawable(Display *dpy, GLXDrawable drawable, CARD32 glxCode)
{
@@ -413,6 +409,19 @@ protocolDestroyDrawable(Display *dpy, GLXDrawable drawable, CARD32 glxCode)
UnlockDisplay(dpy);
SyncHandle();
+
+ /* Viewperf2020/Sw calls XDestroyWindow(win) and then glXDestroyWindow(win),
+ * causing an X error and abort. This is the workaround.
+ */
+ struct glx_display *priv = __glXInitialize(dpy);
+
+ if (priv->screens[0] &&
+ priv->screens[0]->allow_invalid_glx_destroy_window) {
+ void *old = XESetError(priv->dpy, priv->codes.extension,
+ dummyErrorHandler);
+ XSync(dpy, false);
+ XESetError(priv->dpy, priv->codes.extension, old);
+ }
}
/**
@@ -420,7 +429,7 @@ protocolDestroyDrawable(Display *dpy, GLXDrawable drawable, CARD32 glxCode)
*/
static GLXDrawable
CreateDrawable(Display *dpy, struct glx_config *config,
- Drawable drawable, const int *attrib_list, CARD8 glxCode)
+ Drawable drawable, int type, const int *attrib_list)
{
xGLXCreateWindowReq *req;
struct glx_drawable *glxDraw;
@@ -451,13 +460,17 @@ CreateDrawable(Display *dpy, struct glx_config *config,
data = (CARD32 *) (req + 1);
req->reqType = opcode;
- req->glxCode = glxCode;
req->screen = config->screen;
req->fbconfig = config->fbconfigID;
req->window = drawable;
req->glxwindow = xid = XAllocID(dpy);
req->numAttribs = i;
+ if (type == GLX_WINDOW_BIT)
+ req->glxCode = X_GLXCreateWindow;
+ else
+ req->glxCode = X_GLXCreatePixmap;
+
if (attrib_list)
memcpy(data, attrib_list, 8 * i);
@@ -469,8 +482,9 @@ CreateDrawable(Display *dpy, struct glx_config *config,
return None;
}
- if (!CreateDRIDrawable(dpy, config, drawable, xid, attrib_list, i)) {
- if (glxCode == X_GLXCreatePixmap)
+ if (!CreateDRIDrawable(dpy, config, drawable, xid, type, attrib_list, i)) {
+ CARD8 glxCode;
+ if (type == GLX_PIXMAP_BIT)
glxCode = X_GLXDestroyPixmap;
else
glxCode = X_GLXDestroyWindow;
@@ -488,14 +502,10 @@ CreateDrawable(Display *dpy, struct glx_config *config,
static void
DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode)
{
- if ((dpy == NULL) || (drawable == 0)) {
- return;
- }
-
protocolDestroyDrawable(dpy, drawable, glxCode);
DestroyGLXDrawable(dpy, drawable);
- DestroyDRIDrawable(dpy, drawable, GL_FALSE);
+ DestroyDRIDrawable(dpy, drawable);
return;
}
@@ -506,10 +516,6 @@ DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode)
*
* This function is used to implement \c glXCreatePbuffer and
* \c glXCreateGLXPbufferSGIX.
- *
- * \note
- * This function dynamically determines whether to use the SGIX_pbuffer
- * version of the protocol or the GLX 1.3 version of the protocol.
*/
static GLXDrawable
CreatePbuffer(Display * dpy, struct glx_config *config,
@@ -521,9 +527,6 @@ CreatePbuffer(Display * dpy, struct glx_config *config,
CARD32 *data;
CARD8 opcode;
unsigned int i;
- Pixmap pixmap;
- GLboolean glx_1_3 = GL_FALSE;
- int depth = config->rgbBits;
if (priv == NULL)
return None;
@@ -541,46 +544,24 @@ CreatePbuffer(Display * dpy, struct glx_config *config,
LockDisplay(dpy);
id = XAllocID(dpy);
- if (priv->minorVersion >= 3) {
- xGLXCreatePbufferReq *req;
- unsigned int extra = (size_in_attribs) ? 0 : 2;
-
- glx_1_3 = GL_TRUE;
-
- GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req);
- data = (CARD32 *) (req + 1);
-
- req->reqType = opcode;
- req->glxCode = X_GLXCreatePbuffer;
- req->screen = config->screen;
- req->fbconfig = config->fbconfigID;
- req->pbuffer = id;
- req->numAttribs = i + extra;
-
- if (!size_in_attribs) {
- data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
- data[(2 * i) + 1] = width;
- data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
- data[(2 * i) + 3] = height;
- data += 4;
- }
- }
- else {
- xGLXVendorPrivateReq *vpreq;
-
- GetReqExtra(GLXVendorPrivate, 20 + (8 * i), vpreq);
- data = (CARD32 *) (vpreq + 1);
-
- vpreq->reqType = opcode;
- vpreq->glxCode = X_GLXVendorPrivate;
- vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
+ xGLXCreatePbufferReq *req;
+ unsigned int extra = (size_in_attribs) ? 0 : 2;
+ GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req);
+ data = (CARD32 *) (req + 1);
- data[0] = config->screen;
- data[1] = config->fbconfigID;
- data[2] = id;
- data[3] = width;
- data[4] = height;
- data += 5;
+ req->reqType = opcode;
+ req->glxCode = X_GLXCreatePbuffer;
+ req->screen = config->screen;
+ req->fbconfig = config->fbconfigID;
+ req->pbuffer = id;
+ req->numAttribs = i + extra;
+
+ if (!size_in_attribs) {
+ data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
+ data[(2 * i) + 1] = width;
+ data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
+ data[(2 * i) + 3] = height;
+ data += 4;
}
(void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i);
@@ -588,16 +569,9 @@ CreatePbuffer(Display * dpy, struct glx_config *config,
UnlockDisplay(dpy);
SyncHandle();
- if (depth == 30)
- depth = 32;
-
- pixmap = XCreatePixmap(dpy, RootWindow(dpy, config->screen),
- width, height, depth);
-
- if (!CreateDRIDrawable(dpy, config, pixmap, id, attrib_list, i)) {
- CARD32 o = glx_1_3 ? X_GLXDestroyPbuffer : X_GLXvop_DestroyGLXPbufferSGIX;
- XFreePixmap(dpy, pixmap);
- protocolDestroyDrawable(dpy, id, o);
+ /* xserver created a pixmap with the same id as pbuffer */
+ if (!CreateDRIDrawable(dpy, config, id, id, GLX_PBUFFER_BIT, attrib_list, i)) {
+ protocolDestroyDrawable(dpy, id, X_GLXDestroyPbuffer);
id = None;
}
@@ -609,10 +583,6 @@ CreatePbuffer(Display * dpy, struct glx_config *config,
*
* This function is used to implement \c glXDestroyPbuffer and
* \c glXDestroyGLXPbufferSGIX.
- *
- * \note
- * This function dynamically determines whether to use the SGIX_pbuffer
- * version of the protocol or the GLX 1.3 version of the protocol.
*/
static void
DestroyPbuffer(Display * dpy, GLXDrawable drawable)
@@ -630,32 +600,16 @@ DestroyPbuffer(Display * dpy, GLXDrawable drawable)
LockDisplay(dpy);
- if (priv->minorVersion >= 3) {
- xGLXDestroyPbufferReq *req;
-
- GetReq(GLXDestroyPbuffer, req);
- req->reqType = opcode;
- req->glxCode = X_GLXDestroyPbuffer;
- req->pbuffer = (GLXPbuffer) drawable;
- }
- else {
- xGLXVendorPrivateWithReplyReq *vpreq;
- CARD32 *data;
-
- GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
- data = (CARD32 *) (vpreq + 1);
-
- data[0] = (CARD32) drawable;
-
- vpreq->reqType = opcode;
- vpreq->glxCode = X_GLXVendorPrivateWithReply;
- vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
- }
+ xGLXDestroyPbufferReq *req;
+ GetReq(GLXDestroyPbuffer, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXDestroyPbuffer;
+ req->pbuffer = (GLXPbuffer) drawable;
UnlockDisplay(dpy);
SyncHandle();
- DestroyDRIDrawable(dpy, drawable, GL_TRUE);
+ DestroyDRIDrawable(dpy, drawable);
return;
}
@@ -909,7 +863,7 @@ glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap,
return pixmap;
#else
return CreateDrawable(dpy, (struct glx_config *) config,
- (Drawable) pixmap, attrib_list, X_GLXCreatePixmap);
+ (Drawable) pixmap, GLX_PIXMAP_BIT, attrib_list);
#endif
}
@@ -943,7 +897,7 @@ glXCreateWindow(Display * dpy, GLXFBConfig config, Window win,
return win;
#else
return CreateDrawable(dpy, (struct glx_config *) config,
- (Drawable) win, attrib_list, X_GLXCreateWindow);
+ (Drawable) win, GLX_WINDOW_BIT, attrib_list);
#endif
}
@@ -983,3 +937,99 @@ GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
(Display * dpy, GLXDrawable drawable,
unsigned long *mask), (dpy, drawable, mask),
glXGetSelectedEvent)
+
+_GLX_PUBLIC GLXPixmap
+glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
+{
+#ifdef GLX_USE_APPLEGL
+ int screen = vis->screen;
+ struct glx_screen *const psc = GetGLXScreenConfigs(dpy, screen);
+ const struct glx_config *config;
+
+ config = glx_config_find_visual(psc->visuals, vis->visualid);
+
+ if(apple_glx_pixmap_create(dpy, vis->screen, pixmap, config))
+ return None;
+
+ return pixmap;
+#else
+ xGLXCreateGLXPixmapReq *req;
+ struct glx_drawable *glxDraw;
+ GLXPixmap xid;
+ CARD8 opcode;
+
+#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
+ struct glx_display *const priv = __glXInitialize(dpy);
+
+ if (priv == NULL)
+ return None;
+#endif
+
+ opcode = __glXSetupForCommand(dpy);
+ if (!opcode) {
+ return None;
+ }
+
+ glxDraw = malloc(sizeof(*glxDraw));
+ if (!glxDraw)
+ return None;
+
+ /* Send the glXCreateGLXPixmap request */
+ LockDisplay(dpy);
+ GetReq(GLXCreateGLXPixmap, req);
+ req->reqType = opcode;
+ req->glxCode = X_GLXCreateGLXPixmap;
+ req->screen = vis->screen;
+ req->visual = vis->visualid;
+ req->pixmap = pixmap;
+ req->glxpixmap = xid = XAllocID(dpy);
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ if (InitGLXDrawable(dpy, glxDraw, pixmap, req->glxpixmap)) {
+ free(glxDraw);
+ return None;
+ }
+
+#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
+ do {
+ /* FIXME: Maybe delay __DRIdrawable creation until the drawable
+ * is actually bound to a context... */
+
+ struct glx_screen *psc = GetGLXScreenConfigs(dpy, vis->screen);
+ struct glx_config *config = glx_config_find_visual(psc->visuals,
+ vis->visualid);
+
+ if (!CreateDRIDrawable(dpy, config, pixmap, xid, GLX_PIXMAP_BIT,
+ NULL, 0)) {
+ protocolDestroyDrawable(dpy, xid, X_GLXDestroyGLXPixmap);
+ xid = None;
+ }
+ } while (0);
+#endif
+
+ return xid;
+#endif
+}
+
+/*
+** Destroy the named pixmap
+*/
+_GLX_PUBLIC void
+glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
+{
+#ifdef GLX_USE_APPLEGL
+ if(apple_glx_pixmap_destroy(dpy, glxpixmap))
+ __glXSendError(dpy, GLXBadPixmap, glxpixmap, X_GLXDestroyPixmap, false);
+#else
+ DestroyDrawable(dpy, glxpixmap, X_GLXDestroyGLXPixmap);
+#endif /* GLX_USE_APPLEGL */
+}
+
+_GLX_PUBLIC GLXPixmap
+glXCreateGLXPixmapWithConfigSGIX(Display * dpy,
+ GLXFBConfigSGIX fbconfig,
+ Pixmap pixmap)
+{
+ return glXCreatePixmap(dpy, fbconfig, pixmap, NULL);
+}