Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

glx_pbuffer.c 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. /*
  2. * (C) Copyright IBM Corporation 2004
  3. * All Rights Reserved.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a
  6. * copy of this software and associated documentation files (the "Software"),
  7. * to deal in the Software without restriction, including without limitation
  8. * on the rights to use, copy, modify, merge, publish, distribute, sub
  9. * license, and/or sell copies of the Software, and to permit persons to whom
  10. * the Software is furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice (including the next
  13. * paragraph) shall be included in all copies or substantial portions of the
  14. * Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  19. * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22. * DEALINGS IN THE SOFTWARE.
  23. */
  24. /**
  25. * \file glx_pbuffer.c
  26. * Implementation of pbuffer related functions.
  27. *
  28. * \author Ian Romanick <idr@us.ibm.com>
  29. */
  30. #include <inttypes.h>
  31. #include "glxclient.h"
  32. #include <X11/extensions/extutil.h>
  33. #include <X11/extensions/Xext.h>
  34. #include <assert.h>
  35. #include <string.h>
  36. #include "glapi.h"
  37. #include "glxextensions.h"
  38. #include "glcontextmodes.h"
  39. /**
  40. * Change a drawable's attribute.
  41. *
  42. * This function is used to implement \c glXSelectEvent and
  43. * \c glXSelectEventSGIX.
  44. *
  45. * \note
  46. * This function dynamically determines whether to use the SGIX_pbuffer
  47. * version of the protocol or the GLX 1.3 version of the protocol.
  48. *
  49. * \todo
  50. * This function needs to be modified to work with direct-rendering drivers.
  51. */
  52. static void
  53. ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
  54. const CARD32 * attribs, size_t num_attribs)
  55. {
  56. __GLXdisplayPrivate *priv = __glXInitialize(dpy);
  57. CARD32 *output;
  58. CARD8 opcode;
  59. if ((dpy == NULL) || (drawable == 0)) {
  60. return;
  61. }
  62. opcode = __glXSetupForCommand(dpy);
  63. if (!opcode)
  64. return;
  65. LockDisplay(dpy);
  66. if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
  67. xGLXChangeDrawableAttributesReq *req;
  68. GetReqExtra(GLXChangeDrawableAttributes, 8 + (8 * num_attribs), req);
  69. output = (CARD32 *) (req + 1);
  70. req->reqType = opcode;
  71. req->glxCode = X_GLXChangeDrawableAttributes;
  72. req->drawable = drawable;
  73. req->numAttribs = (CARD32) num_attribs;
  74. }
  75. else {
  76. xGLXVendorPrivateWithReplyReq *vpreq;
  77. GetReqExtra(GLXVendorPrivateWithReply, 4 + (8 * num_attribs), vpreq);
  78. output = (CARD32 *) (vpreq + 1);
  79. vpreq->reqType = opcode;
  80. vpreq->glxCode = X_GLXVendorPrivateWithReply;
  81. vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX;
  82. output[0] = (CARD32) drawable;
  83. output++;
  84. }
  85. (void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs);
  86. UnlockDisplay(dpy);
  87. SyncHandle();
  88. return;
  89. }
  90. /**
  91. * Destroy a pbuffer.
  92. *
  93. * This function is used to implement \c glXDestroyPbuffer and
  94. * \c glXDestroyGLXPbufferSGIX.
  95. *
  96. * \note
  97. * This function dynamically determines whether to use the SGIX_pbuffer
  98. * version of the protocol or the GLX 1.3 version of the protocol.
  99. *
  100. * \todo
  101. * This function needs to be modified to work with direct-rendering drivers.
  102. */
  103. static void
  104. DestroyPbuffer(Display * dpy, GLXDrawable drawable)
  105. {
  106. __GLXdisplayPrivate *priv = __glXInitialize(dpy);
  107. CARD8 opcode;
  108. if ((dpy == NULL) || (drawable == 0)) {
  109. return;
  110. }
  111. opcode = __glXSetupForCommand(dpy);
  112. if (!opcode)
  113. return;
  114. LockDisplay(dpy);
  115. if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
  116. xGLXDestroyPbufferReq *req;
  117. GetReq(GLXDestroyPbuffer, req);
  118. req->reqType = opcode;
  119. req->glxCode = X_GLXDestroyPbuffer;
  120. req->pbuffer = (GLXPbuffer) drawable;
  121. }
  122. else {
  123. xGLXVendorPrivateWithReplyReq *vpreq;
  124. CARD32 *data;
  125. GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
  126. data = (CARD32 *) (vpreq + 1);
  127. data[0] = (CARD32) drawable;
  128. vpreq->reqType = opcode;
  129. vpreq->glxCode = X_GLXVendorPrivateWithReply;
  130. vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
  131. }
  132. UnlockDisplay(dpy);
  133. SyncHandle();
  134. return;
  135. }
  136. #ifdef GLX_DIRECT_RENDERING
  137. extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy,
  138. GLXDrawable drawable,
  139. int *const scrn_num);
  140. static GLenum
  141. determineTextureTarget(const int *attribs, int numAttribs)
  142. {
  143. GLenum target = 0;
  144. int i;
  145. for (i = 0; i < numAttribs; i++) {
  146. if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) {
  147. switch (attribs[2 * i + 1]) {
  148. case GLX_TEXTURE_2D_EXT:
  149. target = GL_TEXTURE_2D;
  150. break;
  151. case GLX_TEXTURE_RECTANGLE_EXT:
  152. target = GL_TEXTURE_RECTANGLE_ARB;
  153. break;
  154. }
  155. }
  156. }
  157. return target;
  158. }
  159. #endif
  160. /**
  161. * Get a drawable's attribute.
  162. *
  163. * This function is used to implement \c glXGetSelectedEvent and
  164. * \c glXGetSelectedEventSGIX.
  165. *
  166. * \note
  167. * This function dynamically determines whether to use the SGIX_pbuffer
  168. * version of the protocol or the GLX 1.3 version of the protocol.
  169. *
  170. * \todo
  171. * The number of attributes returned is likely to be small, probably less than
  172. * 10. Given that, this routine should try to use an array on the stack to
  173. * capture the reply rather than always calling Xmalloc.
  174. *
  175. * \todo
  176. * This function needs to be modified to work with direct-rendering drivers.
  177. */
  178. static int
  179. GetDrawableAttribute(Display * dpy, GLXDrawable drawable,
  180. int attribute, unsigned int *value)
  181. {
  182. __GLXdisplayPrivate *priv;
  183. xGLXGetDrawableAttributesReply reply;
  184. CARD32 *data;
  185. CARD8 opcode;
  186. unsigned int length;
  187. unsigned int i;
  188. unsigned int num_attributes;
  189. GLboolean use_glx_1_3;
  190. if ((dpy == NULL) || (drawable == 0)) {
  191. return 0;
  192. }
  193. priv = __glXInitialize(dpy);
  194. use_glx_1_3 = ((priv->majorVersion > 1) || (priv->minorVersion >= 3));
  195. *value = 0;
  196. opcode = __glXSetupForCommand(dpy);
  197. if (!opcode)
  198. return 0;
  199. LockDisplay(dpy);
  200. if (use_glx_1_3) {
  201. xGLXGetDrawableAttributesReq *req;
  202. GetReqExtra(GLXGetDrawableAttributes, 4, req);
  203. req->reqType = opcode;
  204. req->glxCode = X_GLXGetDrawableAttributes;
  205. req->drawable = drawable;
  206. }
  207. else {
  208. xGLXVendorPrivateWithReplyReq *vpreq;
  209. GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
  210. data = (CARD32 *) (vpreq + 1);
  211. data[0] = (CARD32) drawable;
  212. vpreq->reqType = opcode;
  213. vpreq->glxCode = X_GLXVendorPrivateWithReply;
  214. vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
  215. }
  216. _XReply(dpy, (xReply *) & reply, 0, False);
  217. if (reply.type == X_Error) {
  218. UnlockDisplay(dpy);
  219. SyncHandle();
  220. return 0;
  221. }
  222. length = reply.length;
  223. if (length) {
  224. num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
  225. data = (CARD32 *) Xmalloc(length * sizeof(CARD32));
  226. if (data == NULL) {
  227. /* Throw data on the floor */
  228. _XEatData(dpy, length);
  229. }
  230. else {
  231. _XRead(dpy, (char *) data, length * sizeof(CARD32));
  232. /* Search the set of returned attributes for the attribute requested by
  233. * the caller.
  234. */
  235. for (i = 0; i < num_attributes; i++) {
  236. if (data[i * 2] == attribute) {
  237. *value = data[(i * 2) + 1];
  238. break;
  239. }
  240. }
  241. #ifdef GLX_DIRECT_RENDERING
  242. {
  243. __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
  244. if (pdraw != NULL && !pdraw->textureTarget)
  245. pdraw->textureTarget =
  246. determineTextureTarget((const int *) data, num_attributes);
  247. }
  248. #endif
  249. Xfree(data);
  250. }
  251. }
  252. UnlockDisplay(dpy);
  253. SyncHandle();
  254. return 0;
  255. }
  256. /**
  257. * Create a non-pbuffer GLX drawable.
  258. *
  259. * \todo
  260. * This function needs to be modified to work with direct-rendering drivers.
  261. */
  262. static GLXDrawable
  263. CreateDrawable(Display * dpy, const __GLcontextModes * fbconfig,
  264. Drawable drawable, const int *attrib_list, CARD8 glxCode)
  265. {
  266. xGLXCreateWindowReq *req;
  267. CARD32 *data;
  268. unsigned int i;
  269. CARD8 opcode;
  270. i = 0;
  271. if (attrib_list) {
  272. while (attrib_list[i * 2] != None)
  273. i++;
  274. }
  275. opcode = __glXSetupForCommand(dpy);
  276. if (!opcode)
  277. return None;
  278. LockDisplay(dpy);
  279. GetReqExtra(GLXCreateWindow, 8 * i, req);
  280. data = (CARD32 *) (req + 1);
  281. req->reqType = opcode;
  282. req->glxCode = glxCode;
  283. req->screen = (CARD32) fbconfig->screen;
  284. req->fbconfig = fbconfig->fbconfigID;
  285. req->window = (CARD32) drawable;
  286. req->glxwindow = (GLXWindow) XAllocID(dpy);
  287. req->numAttribs = (CARD32) i;
  288. memcpy(data, attrib_list, 8 * i);
  289. UnlockDisplay(dpy);
  290. SyncHandle();
  291. #ifdef GLX_DIRECT_RENDERING
  292. do {
  293. /* FIXME: Maybe delay __DRIdrawable creation until the drawable
  294. * is actually bound to a context... */
  295. __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
  296. __GLXDRIdrawable *pdraw;
  297. __GLXscreenConfigs *psc;
  298. psc = &priv->screenConfigs[fbconfig->screen];
  299. if (psc->driScreen == NULL)
  300. break;
  301. pdraw = psc->driScreen->createDrawable(psc, drawable,
  302. req->glxwindow, fbconfig);
  303. if (pdraw == NULL) {
  304. fprintf(stderr, "failed to create drawable\n");
  305. break;
  306. }
  307. if (__glxHashInsert(psc->drawHash, req->glxwindow, pdraw)) {
  308. (*pdraw->destroyDrawable) (pdraw);
  309. return None; /* FIXME: Check what we're supposed to do here... */
  310. }
  311. pdraw->textureTarget = determineTextureTarget(attrib_list, i);
  312. } while (0);
  313. #endif
  314. return (GLXDrawable) req->glxwindow;
  315. }
  316. /**
  317. * Destroy a non-pbuffer GLX drawable.
  318. *
  319. * \todo
  320. * This function needs to be modified to work with direct-rendering drivers.
  321. */
  322. static void
  323. DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode)
  324. {
  325. xGLXDestroyPbufferReq *req;
  326. CARD8 opcode;
  327. if ((dpy == NULL) || (drawable == 0)) {
  328. return;
  329. }
  330. opcode = __glXSetupForCommand(dpy);
  331. if (!opcode)
  332. return;
  333. LockDisplay(dpy);
  334. GetReqExtra(GLXDestroyPbuffer, 4, req);
  335. req->reqType = opcode;
  336. req->glxCode = glxCode;
  337. req->pbuffer = (GLXPbuffer) drawable;
  338. UnlockDisplay(dpy);
  339. SyncHandle();
  340. #ifdef GLX_DIRECT_RENDERING
  341. {
  342. int screen;
  343. __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
  344. __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
  345. __GLXscreenConfigs *psc = &priv->screenConfigs[screen];
  346. if (pdraw != NULL) {
  347. (*pdraw->destroyDrawable) (pdraw);
  348. __glxHashDelete(psc->drawHash, drawable);
  349. }
  350. }
  351. #endif
  352. return;
  353. }
  354. /**
  355. * Create a pbuffer.
  356. *
  357. * This function is used to implement \c glXCreatePbuffer and
  358. * \c glXCreateGLXPbufferSGIX.
  359. *
  360. * \note
  361. * This function dynamically determines whether to use the SGIX_pbuffer
  362. * version of the protocol or the GLX 1.3 version of the protocol.
  363. *
  364. * \todo
  365. * This function needs to be modified to work with direct-rendering drivers.
  366. */
  367. static GLXDrawable
  368. CreatePbuffer(Display * dpy, const __GLcontextModes * fbconfig,
  369. unsigned int width, unsigned int height,
  370. const int *attrib_list, GLboolean size_in_attribs)
  371. {
  372. __GLXdisplayPrivate *priv = __glXInitialize(dpy);
  373. GLXDrawable id = 0;
  374. CARD32 *data;
  375. CARD8 opcode;
  376. unsigned int i;
  377. i = 0;
  378. if (attrib_list) {
  379. while (attrib_list[i * 2])
  380. i++;
  381. }
  382. opcode = __glXSetupForCommand(dpy);
  383. if (!opcode)
  384. return None;
  385. LockDisplay(dpy);
  386. id = XAllocID(dpy);
  387. if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
  388. xGLXCreatePbufferReq *req;
  389. unsigned int extra = (size_in_attribs) ? 0 : 2;
  390. GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req);
  391. data = (CARD32 *) (req + 1);
  392. req->reqType = opcode;
  393. req->glxCode = X_GLXCreatePbuffer;
  394. req->screen = (CARD32) fbconfig->screen;
  395. req->fbconfig = fbconfig->fbconfigID;
  396. req->pbuffer = (GLXPbuffer) id;
  397. req->numAttribs = (CARD32) (i + extra);
  398. if (!size_in_attribs) {
  399. data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
  400. data[(2 * i) + 1] = width;
  401. data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
  402. data[(2 * i) + 3] = height;
  403. data += 4;
  404. }
  405. }
  406. else {
  407. xGLXVendorPrivateReq *vpreq;
  408. GetReqExtra(GLXVendorPrivate, 20 + (8 * i), vpreq);
  409. data = (CARD32 *) (vpreq + 1);
  410. vpreq->reqType = opcode;
  411. vpreq->glxCode = X_GLXVendorPrivate;
  412. vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
  413. data[0] = (CARD32) fbconfig->screen;
  414. data[1] = (CARD32) fbconfig->fbconfigID;
  415. data[2] = (CARD32) id;
  416. data[3] = (CARD32) width;
  417. data[4] = (CARD32) height;
  418. data += 5;
  419. }
  420. (void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i);
  421. UnlockDisplay(dpy);
  422. SyncHandle();
  423. return id;
  424. }
  425. /**
  426. * Create a new pbuffer.
  427. */
  428. PUBLIC GLXPbufferSGIX
  429. glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config,
  430. unsigned int width, unsigned int height,
  431. int *attrib_list)
  432. {
  433. return (GLXPbufferSGIX) CreatePbuffer(dpy, (__GLcontextModes *) config,
  434. width, height,
  435. attrib_list, GL_FALSE);
  436. }
  437. /**
  438. * Create a new pbuffer.
  439. */
  440. PUBLIC GLXPbuffer
  441. glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list)
  442. {
  443. int i, width, height;
  444. width = 0;
  445. height = 0;
  446. for (i = 0; attrib_list[i * 2]; i++) {
  447. switch (attrib_list[i * 2]) {
  448. case GLX_PBUFFER_WIDTH:
  449. width = attrib_list[i * 2 + 1];
  450. break;
  451. case GLX_PBUFFER_HEIGHT:
  452. height = attrib_list[i * 2 + 1];
  453. break;
  454. }
  455. }
  456. return (GLXPbuffer) CreatePbuffer(dpy, (__GLcontextModes *) config,
  457. width, height, attrib_list, GL_TRUE);
  458. }
  459. /**
  460. * Destroy an existing pbuffer.
  461. */
  462. PUBLIC void
  463. glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf)
  464. {
  465. DestroyPbuffer(dpy, pbuf);
  466. }
  467. /**
  468. * Query an attribute of a drawable.
  469. */
  470. PUBLIC void
  471. glXQueryDrawable(Display * dpy, GLXDrawable drawable,
  472. int attribute, unsigned int *value)
  473. {
  474. GetDrawableAttribute(dpy, drawable, attribute, value);
  475. }
  476. /**
  477. * Query an attribute of a pbuffer.
  478. */
  479. PUBLIC int
  480. glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable,
  481. int attribute, unsigned int *value)
  482. {
  483. return GetDrawableAttribute(dpy, drawable, attribute, value);
  484. }
  485. /**
  486. * Select the event mask for a drawable.
  487. */
  488. PUBLIC void
  489. glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask)
  490. {
  491. CARD32 attribs[2];
  492. attribs[0] = (CARD32) GLX_EVENT_MASK;
  493. attribs[1] = (CARD32) mask;
  494. ChangeDrawableAttribute(dpy, drawable, attribs, 1);
  495. }
  496. /**
  497. * Get the selected event mask for a drawable.
  498. */
  499. PUBLIC void
  500. glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask)
  501. {
  502. unsigned int value;
  503. /* The non-sense with value is required because on LP64 platforms
  504. * sizeof(unsigned int) != sizeof(unsigned long). On little-endian
  505. * we could just type-cast the pointer, but why?
  506. */
  507. GetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value);
  508. *mask = value;
  509. }
  510. PUBLIC GLXPixmap
  511. glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap,
  512. const int *attrib_list)
  513. {
  514. return CreateDrawable(dpy, (__GLcontextModes *) config,
  515. (Drawable) pixmap, attrib_list, X_GLXCreatePixmap);
  516. }
  517. PUBLIC GLXWindow
  518. glXCreateWindow(Display * dpy, GLXFBConfig config, Window win,
  519. const int *attrib_list)
  520. {
  521. return CreateDrawable(dpy, (__GLcontextModes *) config,
  522. (Drawable) win, attrib_list, X_GLXCreateWindow);
  523. }
  524. PUBLIC void
  525. glXDestroyPixmap(Display * dpy, GLXPixmap pixmap)
  526. {
  527. DestroyDrawable(dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap);
  528. }
  529. PUBLIC void
  530. glXDestroyWindow(Display * dpy, GLXWindow win)
  531. {
  532. DestroyDrawable(dpy, (GLXDrawable) win, X_GLXDestroyWindow);
  533. }
  534. PUBLIC
  535. GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
  536. (Display * dpy, GLXPbufferSGIX pbuf),
  537. (dpy, pbuf), glXDestroyPbuffer)
  538. PUBLIC
  539. GLX_ALIAS_VOID(glXSelectEventSGIX,
  540. (Display * dpy, GLXDrawable drawable,
  541. unsigned long mask), (dpy, drawable, mask),
  542. glXSelectEvent)
  543. PUBLIC
  544. GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
  545. (Display * dpy, GLXDrawable drawable,
  546. unsigned long *mask), (dpy, drawable, mask),
  547. glXGetSelectedEvent)