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.

egl_g3d_api.c 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  1. /*
  2. * Mesa 3-D graphics library
  3. * Version: 7.9
  4. *
  5. * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included
  15. * in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE.
  24. */
  25. #include "egldriver.h"
  26. #include "eglcurrent.h"
  27. #include "egllog.h"
  28. #include "pipe/p_screen.h"
  29. #include "util/u_memory.h"
  30. #include "util/u_inlines.h"
  31. #include "util/u_box.h"
  32. #include "egl_g3d.h"
  33. #include "egl_g3d_api.h"
  34. #include "egl_g3d_image.h"
  35. #include "egl_g3d_sync.h"
  36. #include "egl_g3d_st.h"
  37. #include "native.h"
  38. /**
  39. * Return the state tracker for the given context.
  40. */
  41. static struct st_api *
  42. egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx,
  43. enum st_profile_type *profile)
  44. {
  45. struct st_api *stapi;
  46. EGLint api = -1;
  47. *profile = ST_PROFILE_DEFAULT;
  48. switch (ctx->ClientAPI) {
  49. case EGL_OPENGL_ES_API:
  50. switch (ctx->ClientVersion) {
  51. case 1:
  52. api = ST_API_OPENGL;
  53. *profile = ST_PROFILE_OPENGL_ES1;
  54. break;
  55. case 2:
  56. api = ST_API_OPENGL;
  57. *profile = ST_PROFILE_OPENGL_ES2;
  58. break;
  59. default:
  60. _eglLog(_EGL_WARNING, "unknown client version %d",
  61. ctx->ClientVersion);
  62. break;
  63. }
  64. break;
  65. case EGL_OPENVG_API:
  66. api = ST_API_OPENVG;
  67. break;
  68. case EGL_OPENGL_API:
  69. api = ST_API_OPENGL;
  70. break;
  71. default:
  72. _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI);
  73. break;
  74. }
  75. stapi = egl_g3d_get_st_api(drv, api);
  76. if (stapi && !(stapi->profile_mask & (1 << *profile)))
  77. stapi = NULL;
  78. return stapi;
  79. }
  80. struct egl_g3d_choose_config_data {
  81. _EGLConfig criteria;
  82. enum pipe_format format;
  83. };
  84. static int
  85. egl_g3d_compare_config(const _EGLConfig *conf1, const _EGLConfig *conf2,
  86. void *priv_data)
  87. {
  88. struct egl_g3d_choose_config_data *data =
  89. (struct egl_g3d_choose_config_data *) priv_data;
  90. const _EGLConfig *criteria = &data->criteria;;
  91. /* EGL_NATIVE_VISUAL_TYPE ignored? */
  92. return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE);
  93. }
  94. static EGLBoolean
  95. egl_g3d_match_config(const _EGLConfig *conf, void *priv_data)
  96. {
  97. struct egl_g3d_choose_config_data *data =
  98. (struct egl_g3d_choose_config_data *) priv_data;
  99. struct egl_g3d_config *gconf = egl_g3d_config(conf);
  100. if (data->format != PIPE_FORMAT_NONE &&
  101. data->format != gconf->native->color_format)
  102. return EGL_FALSE;
  103. return _eglMatchConfig(conf, &data->criteria);
  104. }
  105. static EGLBoolean
  106. egl_g3d_choose_config(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attribs,
  107. EGLConfig *configs, EGLint size, EGLint *num_configs)
  108. {
  109. struct egl_g3d_choose_config_data data;
  110. if (!_eglParseConfigAttribList(&data.criteria, dpy, attribs))
  111. return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
  112. data.format = PIPE_FORMAT_NONE;
  113. if (data.criteria.MatchNativePixmap != EGL_NONE &&
  114. data.criteria.MatchNativePixmap != EGL_DONT_CARE) {
  115. struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  116. if (!gdpy->native->get_pixmap_format(gdpy->native,
  117. (EGLNativePixmapType) data.criteria.MatchNativePixmap,
  118. &data.format))
  119. return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglChooseConfig");
  120. }
  121. return _eglFilterConfigArray(dpy->Configs, configs, size, num_configs,
  122. egl_g3d_match_config, egl_g3d_compare_config, &data);
  123. }
  124. static _EGLContext *
  125. egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
  126. _EGLContext *share, const EGLint *attribs)
  127. {
  128. struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  129. struct egl_g3d_context *gshare = egl_g3d_context(share);
  130. struct egl_g3d_config *gconf = egl_g3d_config(conf);
  131. struct egl_g3d_context *gctx;
  132. struct st_context_attribs stattribs;
  133. gctx = CALLOC_STRUCT(egl_g3d_context);
  134. if (!gctx) {
  135. _eglError(EGL_BAD_ALLOC, "eglCreateContext");
  136. return NULL;
  137. }
  138. if (!_eglInitContext(&gctx->base, dpy, conf, attribs)) {
  139. FREE(gctx);
  140. return NULL;
  141. }
  142. memset(&stattribs, 0, sizeof(stattribs));
  143. if (gconf)
  144. stattribs.visual = gconf->stvis;
  145. gctx->stapi = egl_g3d_choose_st(drv, &gctx->base, &stattribs.profile);
  146. if (!gctx->stapi) {
  147. FREE(gctx);
  148. return NULL;
  149. }
  150. gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi,
  151. &stattribs, (gshare) ? gshare->stctxi : NULL);
  152. if (!gctx->stctxi) {
  153. FREE(gctx);
  154. return NULL;
  155. }
  156. gctx->stctxi->st_manager_private = (void *) &gctx->base;
  157. return &gctx->base;
  158. }
  159. /**
  160. * Destroy a context.
  161. */
  162. static void
  163. destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
  164. {
  165. struct egl_g3d_context *gctx = egl_g3d_context(ctx);
  166. /* FIXME a context might live longer than its display */
  167. if (!dpy->Initialized)
  168. _eglLog(_EGL_FATAL, "destroy a context with an unitialized display");
  169. gctx->stctxi->destroy(gctx->stctxi);
  170. FREE(gctx);
  171. }
  172. static EGLBoolean
  173. egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
  174. {
  175. if (_eglPutContext(ctx))
  176. destroy_context(dpy, ctx);
  177. return EGL_TRUE;
  178. }
  179. struct egl_g3d_create_surface_arg {
  180. EGLint type;
  181. union {
  182. EGLNativeWindowType win;
  183. EGLNativePixmapType pix;
  184. } u;
  185. };
  186. static _EGLSurface *
  187. egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
  188. struct egl_g3d_create_surface_arg *arg,
  189. const EGLint *attribs)
  190. {
  191. struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  192. struct egl_g3d_config *gconf = egl_g3d_config(conf);
  193. struct egl_g3d_surface *gsurf;
  194. struct native_surface *nsurf;
  195. const char *err;
  196. switch (arg->type) {
  197. case EGL_WINDOW_BIT:
  198. err = "eglCreateWindowSurface";
  199. break;
  200. case EGL_PIXMAP_BIT:
  201. err = "eglCreatePixmapSurface";
  202. break;
  203. #ifdef EGL_MESA_screen_surface
  204. case EGL_SCREEN_BIT_MESA:
  205. err = "eglCreateScreenSurface";
  206. break;
  207. #endif
  208. default:
  209. err = "eglCreateUnknownSurface";
  210. break;
  211. }
  212. gsurf = CALLOC_STRUCT(egl_g3d_surface);
  213. if (!gsurf) {
  214. _eglError(EGL_BAD_ALLOC, err);
  215. return NULL;
  216. }
  217. if (!_eglInitSurface(&gsurf->base, dpy, arg->type, conf, attribs)) {
  218. FREE(gsurf);
  219. return NULL;
  220. }
  221. /* create the native surface */
  222. switch (arg->type) {
  223. case EGL_WINDOW_BIT:
  224. nsurf = gdpy->native->create_window_surface(gdpy->native,
  225. arg->u.win, gconf->native);
  226. break;
  227. case EGL_PIXMAP_BIT:
  228. nsurf = gdpy->native->create_pixmap_surface(gdpy->native,
  229. arg->u.pix, gconf->native);
  230. break;
  231. #ifdef EGL_MESA_screen_surface
  232. case EGL_SCREEN_BIT_MESA:
  233. /* prefer back buffer (move to _eglInitSurface?) */
  234. gsurf->base.RenderBuffer = EGL_BACK_BUFFER;
  235. nsurf = gdpy->native->modeset->create_scanout_surface(gdpy->native,
  236. gconf->native, gsurf->base.Width, gsurf->base.Height);
  237. break;
  238. #endif
  239. default:
  240. nsurf = NULL;
  241. break;
  242. }
  243. if (!nsurf) {
  244. FREE(gsurf);
  245. return NULL;
  246. }
  247. /* initialize the geometry */
  248. if (!nsurf->validate(nsurf, 0x0, &gsurf->sequence_number, NULL,
  249. &gsurf->base.Width, &gsurf->base.Height)) {
  250. nsurf->destroy(nsurf);
  251. FREE(gsurf);
  252. return NULL;
  253. }
  254. gsurf->stvis = gconf->stvis;
  255. if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER &&
  256. gconf->stvis.buffer_mask & ST_ATTACHMENT_FRONT_LEFT_MASK)
  257. gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT;
  258. if (dpy->Extensions.NV_post_sub_buffer) {
  259. if (gsurf->base.Type == EGL_WINDOW_BIT &&
  260. gsurf->base.RenderBuffer == EGL_BACK_BUFFER)
  261. gsurf->base.PostSubBufferSupportedNV = EGL_TRUE;
  262. else
  263. gsurf->base.PostSubBufferSupportedNV = EGL_FALSE;
  264. }
  265. gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base);
  266. if (!gsurf->stfbi) {
  267. nsurf->destroy(nsurf);
  268. FREE(gsurf);
  269. return NULL;
  270. }
  271. nsurf->user_data = &gsurf->base;
  272. gsurf->native = nsurf;
  273. return &gsurf->base;
  274. }
  275. static _EGLSurface *
  276. egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
  277. _EGLConfig *conf, EGLNativeWindowType win,
  278. const EGLint *attribs)
  279. {
  280. struct egl_g3d_create_surface_arg arg;
  281. memset(&arg, 0, sizeof(arg));
  282. arg.type = EGL_WINDOW_BIT;
  283. arg.u.win = win;
  284. return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs);
  285. }
  286. static _EGLSurface *
  287. egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
  288. _EGLConfig *conf, EGLNativePixmapType pix,
  289. const EGLint *attribs)
  290. {
  291. struct egl_g3d_create_surface_arg arg;
  292. memset(&arg, 0, sizeof(arg));
  293. arg.type = EGL_PIXMAP_BIT;
  294. arg.u.pix = pix;
  295. return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs);
  296. }
  297. static struct egl_g3d_surface *
  298. create_pbuffer_surface(_EGLDisplay *dpy, _EGLConfig *conf,
  299. const EGLint *attribs, const char *func)
  300. {
  301. struct egl_g3d_config *gconf = egl_g3d_config(conf);
  302. struct egl_g3d_surface *gsurf;
  303. gsurf = CALLOC_STRUCT(egl_g3d_surface);
  304. if (!gsurf) {
  305. _eglError(EGL_BAD_ALLOC, func);
  306. return NULL;
  307. }
  308. if (!_eglInitSurface(&gsurf->base, dpy, EGL_PBUFFER_BIT, conf, attribs)) {
  309. FREE(gsurf);
  310. return NULL;
  311. }
  312. gsurf->stvis = gconf->stvis;
  313. gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base);
  314. if (!gsurf->stfbi) {
  315. FREE(gsurf);
  316. return NULL;
  317. }
  318. return gsurf;
  319. }
  320. static _EGLSurface *
  321. egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
  322. _EGLConfig *conf, const EGLint *attribs)
  323. {
  324. struct egl_g3d_surface *gsurf;
  325. gsurf = create_pbuffer_surface(dpy, conf, attribs,
  326. "eglCreatePbufferSurface");
  327. if (!gsurf)
  328. return NULL;
  329. gsurf->client_buffer_type = EGL_NONE;
  330. return &gsurf->base;
  331. }
  332. static _EGLSurface *
  333. egl_g3d_create_pbuffer_from_client_buffer(_EGLDriver *drv, _EGLDisplay *dpy,
  334. EGLenum buftype,
  335. EGLClientBuffer buffer,
  336. _EGLConfig *conf,
  337. const EGLint *attribs)
  338. {
  339. struct egl_g3d_surface *gsurf;
  340. struct pipe_resource *ptex = NULL;
  341. EGLint pbuffer_attribs[32];
  342. EGLint count, i;
  343. switch (buftype) {
  344. case EGL_OPENVG_IMAGE:
  345. break;
  346. default:
  347. _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferFromClientBuffer");
  348. return NULL;
  349. break;
  350. }
  351. /* parse the attributes first */
  352. count = 0;
  353. for (i = 0; attribs && attribs[i] != EGL_NONE; i++) {
  354. EGLint attr = attribs[i++];
  355. EGLint val = attribs[i];
  356. EGLint err = EGL_SUCCESS;
  357. switch (attr) {
  358. case EGL_TEXTURE_FORMAT:
  359. case EGL_TEXTURE_TARGET:
  360. case EGL_MIPMAP_TEXTURE:
  361. pbuffer_attribs[count++] = attr;
  362. pbuffer_attribs[count++] = val;
  363. break;
  364. default:
  365. err = EGL_BAD_ATTRIBUTE;
  366. break;
  367. }
  368. /* bail out */
  369. if (err != EGL_SUCCESS) {
  370. _eglError(err, "eglCreatePbufferFromClientBuffer");
  371. return NULL;
  372. }
  373. }
  374. pbuffer_attribs[count++] = EGL_NONE;
  375. gsurf = create_pbuffer_surface(dpy, conf, pbuffer_attribs,
  376. "eglCreatePbufferFromClientBuffer");
  377. if (!gsurf)
  378. return NULL;
  379. gsurf->client_buffer_type = buftype;
  380. gsurf->client_buffer = buffer;
  381. /* validate now so that it fails if the client buffer is invalid */
  382. if (!gsurf->stfbi->validate(gsurf->stfbi,
  383. &gsurf->stvis.render_buffer, 1, &ptex)) {
  384. egl_g3d_destroy_st_framebuffer(gsurf->stfbi);
  385. FREE(gsurf);
  386. return NULL;
  387. }
  388. pipe_resource_reference(&ptex, NULL);
  389. return &gsurf->base;
  390. }
  391. /**
  392. * Destroy a surface.
  393. */
  394. static void
  395. destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
  396. {
  397. struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
  398. /* FIXME a surface might live longer than its display */
  399. if (!dpy->Initialized)
  400. _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display");
  401. pipe_resource_reference(&gsurf->render_texture, NULL);
  402. egl_g3d_destroy_st_framebuffer(gsurf->stfbi);
  403. if (gsurf->native)
  404. gsurf->native->destroy(gsurf->native);
  405. FREE(gsurf);
  406. }
  407. static EGLBoolean
  408. egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
  409. {
  410. if (_eglPutSurface(surf))
  411. destroy_surface(dpy, surf);
  412. return EGL_TRUE;
  413. }
  414. static EGLBoolean
  415. egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
  416. _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx)
  417. {
  418. struct egl_g3d_context *gctx = egl_g3d_context(ctx);
  419. struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
  420. struct egl_g3d_surface *gread = egl_g3d_surface(read);
  421. struct egl_g3d_context *old_gctx;
  422. _EGLContext *old_ctx;
  423. _EGLSurface *old_draw, *old_read;
  424. EGLBoolean ok = EGL_TRUE;
  425. /* make new bindings */
  426. if (!_eglBindContext(ctx, draw, read, &old_ctx, &old_draw, &old_read))
  427. return EGL_FALSE;
  428. old_gctx = egl_g3d_context(old_ctx);
  429. if (old_gctx) {
  430. /* flush old context */
  431. old_gctx->stctxi->flush(old_gctx->stctxi, ST_FLUSH_FRONT, NULL);
  432. }
  433. if (gctx) {
  434. ok = gctx->stapi->make_current(gctx->stapi, gctx->stctxi,
  435. (gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL);
  436. if (ok) {
  437. if (gdraw) {
  438. if (gdraw->base.Type == EGL_WINDOW_BIT) {
  439. gctx->base.WindowRenderBuffer =
  440. (gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ?
  441. EGL_SINGLE_BUFFER : EGL_BACK_BUFFER;
  442. }
  443. }
  444. }
  445. }
  446. else if (old_gctx) {
  447. ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL);
  448. if (ok)
  449. old_gctx->base.WindowRenderBuffer = EGL_NONE;
  450. }
  451. if (ok) {
  452. if (_eglPutContext(old_ctx))
  453. destroy_context(dpy, old_ctx);
  454. if (_eglPutSurface(old_draw))
  455. destroy_surface(dpy, old_draw);
  456. if (_eglPutSurface(old_read))
  457. destroy_surface(dpy, old_read);
  458. }
  459. else {
  460. /* undo the previous _eglBindContext */
  461. _eglBindContext(old_ctx, old_draw, old_read, &ctx, &draw, &read);
  462. assert(&gctx->base == ctx &&
  463. &gdraw->base == draw &&
  464. &gread->base == read);
  465. _eglPutSurface(draw);
  466. _eglPutSurface(read);
  467. _eglPutContext(ctx);
  468. _eglPutSurface(old_draw);
  469. _eglPutSurface(old_read);
  470. _eglPutContext(old_ctx);
  471. }
  472. return ok;
  473. }
  474. static EGLBoolean
  475. swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
  476. EGLint num_rects, const EGLint *rects, EGLBoolean preserve)
  477. {
  478. struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
  479. _EGLContext *ctx = _eglGetCurrentContext();
  480. struct egl_g3d_context *gctx = NULL;
  481. struct native_present_control ctrl;
  482. /* no-op for pixmap or pbuffer surface */
  483. if (gsurf->base.Type == EGL_PIXMAP_BIT ||
  484. gsurf->base.Type == EGL_PBUFFER_BIT)
  485. return EGL_TRUE;
  486. /* or when the surface is single-buffered */
  487. if (gsurf->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT)
  488. return EGL_TRUE;
  489. if (ctx && ctx->DrawSurface == surf)
  490. gctx = egl_g3d_context(ctx);
  491. /* flush if the surface is current */
  492. if (gctx) {
  493. gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL);
  494. }
  495. memset(&ctrl, 0, sizeof(ctrl));
  496. ctrl.natt = NATIVE_ATTACHMENT_BACK_LEFT;
  497. ctrl.preserve = preserve;
  498. ctrl.swap_interval = gsurf->base.SwapInterval;
  499. ctrl.premultiplied_alpha = (gsurf->base.VGAlphaFormat == EGL_VG_ALPHA_FORMAT_PRE);
  500. ctrl.num_rects = num_rects;
  501. ctrl.rects = rects;
  502. return gsurf->native->present(gsurf->native, &ctrl);
  503. }
  504. static EGLBoolean
  505. egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
  506. {
  507. struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
  508. return swap_buffers(drv, dpy, surf, 0, NULL,
  509. (gsurf->base.SwapBehavior == EGL_BUFFER_PRESERVED));
  510. }
  511. #ifdef EGL_NOK_swap_region
  512. static EGLBoolean
  513. egl_g3d_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
  514. EGLint num_rects, const EGLint *rects)
  515. {
  516. /* Note: y=0=top */
  517. return swap_buffers(drv, dpy, surf, num_rects, rects, EGL_TRUE);
  518. }
  519. #endif /* EGL_NOK_swap_region */
  520. static EGLBoolean
  521. egl_g3d_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
  522. EGLint x, EGLint y, EGLint width, EGLint height)
  523. {
  524. /* Note: y=0=bottom */
  525. const EGLint rect[4] = { x, surf->Height - y - height, width, height };
  526. return swap_buffers(drv, dpy, surf, 1, rect, EGL_TRUE);
  527. }
  528. static EGLBoolean
  529. egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
  530. EGLNativePixmapType target)
  531. {
  532. struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  533. struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
  534. _EGLContext *ctx = _eglGetCurrentContext();
  535. if (!gsurf->render_texture)
  536. return EGL_TRUE;
  537. /* flush if the surface is current */
  538. if (ctx && ctx->DrawSurface == &gsurf->base) {
  539. struct egl_g3d_context *gctx = egl_g3d_context(ctx);
  540. gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL);
  541. }
  542. return gdpy->native->copy_to_pixmap(gdpy->native,
  543. target, gsurf->render_texture);
  544. }
  545. static EGLBoolean
  546. egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
  547. {
  548. struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  549. struct egl_g3d_context *gctx = egl_g3d_context(ctx);
  550. struct pipe_screen *screen = gdpy->native->screen;
  551. struct pipe_fence_handle *fence = NULL;
  552. gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, &fence);
  553. if (fence) {
  554. screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
  555. screen->fence_reference(screen, &fence, NULL);
  556. }
  557. return EGL_TRUE;
  558. }
  559. static EGLBoolean
  560. egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
  561. {
  562. _EGLContext *ctx = _eglGetCurrentContext();
  563. if (engine != EGL_CORE_NATIVE_ENGINE)
  564. return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
  565. if (ctx && ctx->DrawSurface) {
  566. struct egl_g3d_surface *gsurf = egl_g3d_surface(ctx->DrawSurface);
  567. if (gsurf->native)
  568. gsurf->native->wait(gsurf->native);
  569. }
  570. return EGL_TRUE;
  571. }
  572. static EGLBoolean
  573. egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
  574. _EGLSurface *surf, EGLint buffer)
  575. {
  576. struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
  577. _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API);
  578. struct egl_g3d_context *gctx;
  579. enum pipe_format internal_format;
  580. enum st_texture_type target;
  581. if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT)
  582. return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
  583. if (buffer != EGL_BACK_BUFFER)
  584. return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
  585. if (gsurf->base.BoundToTexture)
  586. return _eglError(EGL_BAD_ACCESS, "eglBindTexImage");
  587. switch (gsurf->base.TextureFormat) {
  588. case EGL_TEXTURE_RGB:
  589. internal_format = PIPE_FORMAT_R8G8B8_UNORM;
  590. break;
  591. case EGL_TEXTURE_RGBA:
  592. internal_format = PIPE_FORMAT_B8G8R8A8_UNORM;
  593. break;
  594. default:
  595. return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
  596. }
  597. switch (gsurf->base.TextureTarget) {
  598. case EGL_TEXTURE_2D:
  599. target = ST_TEXTURE_2D;
  600. break;
  601. default:
  602. return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
  603. }
  604. if (!es1)
  605. return EGL_TRUE;
  606. if (!gsurf->render_texture)
  607. return EGL_FALSE;
  608. /* flush properly if the surface is bound */
  609. if (gsurf->base.CurrentContext) {
  610. gctx = egl_g3d_context(gsurf->base.CurrentContext);
  611. gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL);
  612. }
  613. gctx = egl_g3d_context(es1);
  614. if (gctx->stctxi->teximage) {
  615. if (!gctx->stctxi->teximage(gctx->stctxi, target,
  616. gsurf->base.MipmapLevel, internal_format,
  617. gsurf->render_texture, gsurf->base.MipmapTexture))
  618. return EGL_FALSE;
  619. gsurf->base.BoundToTexture = EGL_TRUE;
  620. }
  621. return EGL_TRUE;
  622. }
  623. static EGLBoolean
  624. egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy,
  625. _EGLSurface *surf, EGLint buffer)
  626. {
  627. struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
  628. if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT ||
  629. !gsurf->base.BoundToTexture)
  630. return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
  631. if (buffer != EGL_BACK_BUFFER)
  632. return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
  633. if (gsurf->render_texture) {
  634. _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API);
  635. struct egl_g3d_context *gctx = egl_g3d_context(ctx);
  636. /* what if the context the surface binds to is no longer current? */
  637. if (gctx) {
  638. gctx->stctxi->teximage(gctx->stctxi, ST_TEXTURE_2D,
  639. gsurf->base.MipmapLevel, PIPE_FORMAT_NONE, NULL, FALSE);
  640. }
  641. }
  642. gsurf->base.BoundToTexture = EGL_FALSE;
  643. return EGL_TRUE;
  644. }
  645. #ifdef EGL_MESA_screen_surface
  646. static _EGLSurface *
  647. egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
  648. _EGLConfig *conf, const EGLint *attribs)
  649. {
  650. struct egl_g3d_create_surface_arg arg;
  651. memset(&arg, 0, sizeof(arg));
  652. arg.type = EGL_SCREEN_BIT_MESA;
  653. return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs);
  654. }
  655. static EGLBoolean
  656. egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy,
  657. _EGLScreen *scr, _EGLSurface *surf,
  658. _EGLMode *mode)
  659. {
  660. struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  661. struct egl_g3d_screen *gscr = egl_g3d_screen(scr);
  662. struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
  663. struct native_surface *nsurf;
  664. const struct native_mode *nmode;
  665. EGLBoolean changed;
  666. if (gsurf) {
  667. EGLint idx;
  668. if (!mode)
  669. return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
  670. if (gsurf->base.Type != EGL_SCREEN_BIT_MESA)
  671. return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA");
  672. if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height)
  673. return _eglError(EGL_BAD_MATCH,
  674. "eglShowSurfaceMESA(surface smaller than mode size)");
  675. /* find the index of the mode */
  676. for (idx = 0; idx < gscr->base.NumModes; idx++)
  677. if (mode == &gscr->base.Modes[idx])
  678. break;
  679. if (idx >= gscr->base.NumModes) {
  680. return _eglError(EGL_BAD_MODE_MESA,
  681. "eglShowSurfaceMESA(unknown mode)");
  682. }
  683. nsurf = gsurf->native;
  684. nmode = gscr->native_modes[idx];
  685. }
  686. else {
  687. if (mode)
  688. return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA");
  689. /* disable the screen */
  690. nsurf = NULL;
  691. nmode = NULL;
  692. }
  693. /* TODO surface panning by CRTC choosing */
  694. changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf,
  695. gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode);
  696. if (changed) {
  697. gscr->base.CurrentSurface = &gsurf->base;
  698. gscr->base.CurrentMode = mode;
  699. }
  700. return changed;
  701. }
  702. #endif /* EGL_MESA_screen_surface */
  703. #ifdef EGL_WL_bind_wayland_display
  704. static EGLBoolean
  705. egl_g3d_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *dpy,
  706. struct wl_display *wl_dpy)
  707. {
  708. struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  709. if (!gdpy->native->wayland_bufmgr)
  710. return EGL_FALSE;
  711. return gdpy->native->wayland_bufmgr->bind_display(gdpy->native, wl_dpy);
  712. }
  713. static EGLBoolean
  714. egl_g3d_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *dpy,
  715. struct wl_display *wl_dpy)
  716. {
  717. struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  718. if (!gdpy->native->wayland_bufmgr)
  719. return EGL_FALSE;
  720. return gdpy->native->wayland_bufmgr->unbind_display(gdpy->native, wl_dpy);
  721. }
  722. #endif /* EGL_WL_bind_wayland_display */
  723. void
  724. egl_g3d_init_driver_api(_EGLDriver *drv)
  725. {
  726. _eglInitDriverFallbacks(drv);
  727. drv->API.ChooseConfig = egl_g3d_choose_config;
  728. drv->API.CreateContext = egl_g3d_create_context;
  729. drv->API.DestroyContext = egl_g3d_destroy_context;
  730. drv->API.CreateWindowSurface = egl_g3d_create_window_surface;
  731. drv->API.CreatePixmapSurface = egl_g3d_create_pixmap_surface;
  732. drv->API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface;
  733. drv->API.CreatePbufferFromClientBuffer = egl_g3d_create_pbuffer_from_client_buffer;
  734. drv->API.DestroySurface = egl_g3d_destroy_surface;
  735. drv->API.MakeCurrent = egl_g3d_make_current;
  736. drv->API.SwapBuffers = egl_g3d_swap_buffers;
  737. drv->API.CopyBuffers = egl_g3d_copy_buffers;
  738. drv->API.WaitClient = egl_g3d_wait_client;
  739. drv->API.WaitNative = egl_g3d_wait_native;
  740. drv->API.BindTexImage = egl_g3d_bind_tex_image;
  741. drv->API.ReleaseTexImage = egl_g3d_release_tex_image;
  742. drv->API.CreateImageKHR = egl_g3d_create_image;
  743. drv->API.DestroyImageKHR = egl_g3d_destroy_image;
  744. #ifdef EGL_MESA_drm_image
  745. drv->API.CreateDRMImageMESA = egl_g3d_create_drm_image;
  746. drv->API.ExportDRMImageMESA = egl_g3d_export_drm_image;
  747. #endif
  748. #ifdef EGL_WL_bind_wayland_display
  749. drv->API.BindWaylandDisplayWL = egl_g3d_bind_wayland_display_wl;
  750. drv->API.UnbindWaylandDisplayWL = egl_g3d_unbind_wayland_display_wl;
  751. #endif
  752. drv->API.CreateSyncKHR = egl_g3d_create_sync;
  753. drv->API.DestroySyncKHR = egl_g3d_destroy_sync;
  754. drv->API.ClientWaitSyncKHR = egl_g3d_client_wait_sync;
  755. drv->API.SignalSyncKHR = egl_g3d_signal_sync;
  756. #ifdef EGL_MESA_screen_surface
  757. drv->API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface;
  758. drv->API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface;
  759. #endif
  760. #ifdef EGL_NOK_swap_region
  761. drv->API.SwapBuffersRegionNOK = egl_g3d_swap_buffers_region;
  762. #endif
  763. drv->API.PostSubBufferNV = egl_g3d_post_sub_buffer;
  764. }