Clone of mesa.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

native_kms.c 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. /*
  2. * Mesa 3-D graphics library
  3. * Version: 7.8
  4. *
  5. * Copyright (C) 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
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. */
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include "pipe/p_screen.h"
  27. #include "pipe/p_context.h"
  28. #include "util/u_debug.h"
  29. #include "util/u_memory.h"
  30. #include "util/u_inlines.h"
  31. #include "egllog.h"
  32. #include "native_kms.h"
  33. static boolean
  34. kms_surface_validate(struct native_surface *nsurf, uint attachment_mask,
  35. unsigned int *seq_num, struct pipe_resource **textures,
  36. int *width, int *height)
  37. {
  38. struct kms_surface *ksurf = kms_surface(nsurf);
  39. struct kms_display *kdpy = ksurf->kdpy;
  40. struct pipe_screen *screen = kdpy->base.screen;
  41. struct pipe_resource templ, *ptex;
  42. int att;
  43. if (attachment_mask) {
  44. memset(&templ, 0, sizeof(templ));
  45. templ.target = PIPE_TEXTURE_2D;
  46. templ.last_level = 0;
  47. templ.width0 = ksurf->width;
  48. templ.height0 = ksurf->height;
  49. templ.depth0 = 1;
  50. templ.format = ksurf->color_format;
  51. templ.tex_usage = PIPE_BIND_RENDER_TARGET;
  52. if (ksurf->type == KMS_SURFACE_TYPE_SCANOUT)
  53. templ.tex_usage |= PIPE_BIND_SCANOUT;
  54. }
  55. /* create textures */
  56. for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
  57. /* delay the allocation */
  58. if (!native_attachment_mask_test(attachment_mask, att))
  59. continue;
  60. ptex = ksurf->textures[att];
  61. if (!ptex) {
  62. ptex = screen->resource_create(screen, &templ);
  63. ksurf->textures[att] = ptex;
  64. }
  65. if (textures) {
  66. textures[att] = NULL;
  67. pipe_resource_reference(&textures[att], ptex);
  68. }
  69. }
  70. if (seq_num)
  71. *seq_num = ksurf->sequence_number;
  72. if (width)
  73. *width = ksurf->width;
  74. if (height)
  75. *height = ksurf->height;
  76. return TRUE;
  77. }
  78. /**
  79. * Add textures as DRM framebuffers.
  80. */
  81. static boolean
  82. kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
  83. {
  84. struct kms_surface *ksurf = kms_surface(nsurf);
  85. struct kms_display *kdpy = ksurf->kdpy;
  86. int num_framebuffers = (need_back) ? 2 : 1;
  87. int i, err;
  88. for (i = 0; i < num_framebuffers; i++) {
  89. struct kms_framebuffer *fb;
  90. enum native_attachment natt;
  91. struct winsys_handle whandle;
  92. uint block_bits;
  93. if (i == 0) {
  94. fb = &ksurf->front_fb;
  95. natt = NATIVE_ATTACHMENT_FRONT_LEFT;
  96. }
  97. else {
  98. fb = &ksurf->back_fb;
  99. natt = NATIVE_ATTACHMENT_BACK_LEFT;
  100. }
  101. if (!fb->texture) {
  102. /* make sure the texture has been allocated */
  103. kms_surface_validate(&ksurf->base, 1 << natt, NULL, NULL, NULL, NULL);
  104. if (!ksurf->textures[natt])
  105. return FALSE;
  106. pipe_resource_reference(&fb->texture, ksurf->textures[natt]);
  107. }
  108. /* already initialized */
  109. if (fb->buffer_id)
  110. continue;
  111. /* TODO detect the real value */
  112. fb->is_passive = TRUE;
  113. memset(&whandle, 0, sizeof(whandle));
  114. whandle.type = DRM_API_HANDLE_TYPE_KMS;
  115. if (!kdpy->base.screen->resource_get_handle(kdpy->base.screen,
  116. fb->texture, &whandle))
  117. return FALSE;
  118. block_bits = util_format_get_blocksizebits(ksurf->color_format);
  119. err = drmModeAddFB(kdpy->fd, ksurf->width, ksurf->height,
  120. block_bits, block_bits, whandle.stride, whandle.handle,
  121. &fb->buffer_id);
  122. if (err) {
  123. fb->buffer_id = 0;
  124. return FALSE;
  125. }
  126. }
  127. return TRUE;
  128. }
  129. static boolean
  130. kms_surface_flush_frontbuffer(struct native_surface *nsurf)
  131. {
  132. #ifdef DRM_MODE_FEATURE_DIRTYFB
  133. struct kms_surface *ksurf = kms_surface(nsurf);
  134. struct kms_display *kdpy = ksurf->kdpy;
  135. /* pbuffer is private */
  136. if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER)
  137. return TRUE;
  138. if (ksurf->front_fb.is_passive)
  139. drmModeDirtyFB(kdpy->fd, ksurf->front_fb.buffer_id, NULL, 0);
  140. #endif
  141. return TRUE;
  142. }
  143. static boolean
  144. kms_surface_swap_buffers(struct native_surface *nsurf)
  145. {
  146. struct kms_surface *ksurf = kms_surface(nsurf);
  147. struct kms_crtc *kcrtc = &ksurf->current_crtc;
  148. struct kms_display *kdpy = ksurf->kdpy;
  149. struct kms_framebuffer tmp_fb;
  150. struct pipe_resource *tmp_texture;
  151. int err;
  152. /* pbuffer is private */
  153. if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER)
  154. return TRUE;
  155. if (!ksurf->back_fb.buffer_id) {
  156. if (!kms_surface_init_framebuffers(&ksurf->base, TRUE))
  157. return FALSE;
  158. }
  159. if (ksurf->is_shown && kcrtc->crtc) {
  160. err = drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
  161. ksurf->back_fb.buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
  162. kcrtc->connectors, kcrtc->num_connectors, &kcrtc->crtc->mode);
  163. if (err)
  164. return FALSE;
  165. }
  166. /* swap the buffers */
  167. tmp_fb = ksurf->front_fb;
  168. ksurf->front_fb = ksurf->back_fb;
  169. ksurf->back_fb = tmp_fb;
  170. tmp_texture = ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT];
  171. ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT] =
  172. ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT];
  173. ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT] = tmp_texture;
  174. /* the front/back textures are swapped */
  175. ksurf->sequence_number++;
  176. kdpy->event_handler->invalid_surface(&kdpy->base,
  177. &ksurf->base, ksurf->sequence_number);
  178. return TRUE;
  179. }
  180. static void
  181. kms_surface_wait(struct native_surface *nsurf)
  182. {
  183. /* no-op */
  184. }
  185. static void
  186. kms_surface_destroy(struct native_surface *nsurf)
  187. {
  188. struct kms_surface *ksurf = kms_surface(nsurf);
  189. int i;
  190. if (ksurf->current_crtc.crtc)
  191. drmModeFreeCrtc(ksurf->current_crtc.crtc);
  192. if (ksurf->front_fb.buffer_id)
  193. drmModeRmFB(ksurf->kdpy->fd, ksurf->front_fb.buffer_id);
  194. pipe_resource_reference(&ksurf->front_fb.texture, NULL);
  195. if (ksurf->back_fb.buffer_id)
  196. drmModeRmFB(ksurf->kdpy->fd, ksurf->back_fb.buffer_id);
  197. pipe_resource_reference(&ksurf->back_fb.texture, NULL);
  198. for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
  199. struct pipe_resource *ptex = ksurf->textures[i];
  200. pipe_resource_reference(&ptex, NULL);
  201. }
  202. free(ksurf);
  203. }
  204. static struct kms_surface *
  205. kms_display_create_surface(struct native_display *ndpy,
  206. enum kms_surface_type type,
  207. const struct native_config *nconf,
  208. uint width, uint height)
  209. {
  210. struct kms_display *kdpy = kms_display(ndpy);
  211. struct kms_config *kconf = kms_config(nconf);
  212. struct kms_surface *ksurf;
  213. ksurf = CALLOC_STRUCT(kms_surface);
  214. if (!ksurf)
  215. return NULL;
  216. ksurf->kdpy = kdpy;
  217. ksurf->type = type;
  218. ksurf->color_format = kconf->base.color_format;
  219. ksurf->width = width;
  220. ksurf->height = height;
  221. ksurf->base.destroy = kms_surface_destroy;
  222. ksurf->base.swap_buffers = kms_surface_swap_buffers;
  223. ksurf->base.flush_frontbuffer = kms_surface_flush_frontbuffer;
  224. ksurf->base.validate = kms_surface_validate;
  225. ksurf->base.wait = kms_surface_wait;
  226. return ksurf;
  227. }
  228. /**
  229. * Choose a CRTC that supports all given connectors.
  230. */
  231. static uint32_t
  232. kms_display_choose_crtc(struct native_display *ndpy,
  233. uint32_t *connectors, int num_connectors)
  234. {
  235. struct kms_display *kdpy = kms_display(ndpy);
  236. int idx;
  237. for (idx = 0; idx < kdpy->resources->count_crtcs; idx++) {
  238. boolean found_crtc = TRUE;
  239. int i, j;
  240. for (i = 0; i < num_connectors; i++) {
  241. drmModeConnectorPtr connector;
  242. int encoder_idx = -1;
  243. connector = drmModeGetConnector(kdpy->fd, connectors[i]);
  244. if (!connector) {
  245. found_crtc = FALSE;
  246. break;
  247. }
  248. /* find an encoder the CRTC supports */
  249. for (j = 0; j < connector->count_encoders; j++) {
  250. drmModeEncoderPtr encoder =
  251. drmModeGetEncoder(kdpy->fd, connector->encoders[j]);
  252. if (encoder->possible_crtcs & (1 << idx)) {
  253. encoder_idx = j;
  254. break;
  255. }
  256. drmModeFreeEncoder(encoder);
  257. }
  258. drmModeFreeConnector(connector);
  259. if (encoder_idx < 0) {
  260. found_crtc = FALSE;
  261. break;
  262. }
  263. }
  264. if (found_crtc)
  265. break;
  266. }
  267. if (idx >= kdpy->resources->count_crtcs) {
  268. _eglLog(_EGL_WARNING,
  269. "failed to find a CRTC that supports the given %d connectors",
  270. num_connectors);
  271. return 0;
  272. }
  273. return kdpy->resources->crtcs[idx];
  274. }
  275. /**
  276. * Remember the original CRTC status and set the CRTC
  277. */
  278. static boolean
  279. kms_display_set_crtc(struct native_display *ndpy, int crtc_idx,
  280. uint32_t buffer_id, uint32_t x, uint32_t y,
  281. uint32_t *connectors, int num_connectors,
  282. drmModeModeInfoPtr mode)
  283. {
  284. struct kms_display *kdpy = kms_display(ndpy);
  285. struct kms_crtc *kcrtc = &kdpy->saved_crtcs[crtc_idx];
  286. uint32_t crtc_id;
  287. int err;
  288. if (kcrtc->crtc) {
  289. crtc_id = kcrtc->crtc->crtc_id;
  290. }
  291. else {
  292. int count = 0, i;
  293. /*
  294. * Choose the CRTC once. It could be more dynamic, but let's keep it
  295. * simple for now.
  296. */
  297. crtc_id = kms_display_choose_crtc(&kdpy->base,
  298. connectors, num_connectors);
  299. /* save the original CRTC status */
  300. kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
  301. if (!kcrtc->crtc)
  302. return FALSE;
  303. for (i = 0; i < kdpy->num_connectors; i++) {
  304. struct kms_connector *kconn = &kdpy->connectors[i];
  305. drmModeConnectorPtr connector = kconn->connector;
  306. drmModeEncoderPtr encoder;
  307. encoder = drmModeGetEncoder(kdpy->fd, connector->encoder_id);
  308. if (encoder) {
  309. if (encoder->crtc_id == crtc_id) {
  310. kcrtc->connectors[count++] = connector->connector_id;
  311. if (count >= Elements(kcrtc->connectors))
  312. break;
  313. }
  314. drmModeFreeEncoder(encoder);
  315. }
  316. }
  317. kcrtc->num_connectors = count;
  318. }
  319. err = drmModeSetCrtc(kdpy->fd, crtc_id, buffer_id, x, y,
  320. connectors, num_connectors, mode);
  321. if (err) {
  322. drmModeFreeCrtc(kcrtc->crtc);
  323. kcrtc->crtc = NULL;
  324. kcrtc->num_connectors = 0;
  325. return FALSE;
  326. }
  327. return TRUE;
  328. }
  329. static boolean
  330. kms_display_program(struct native_display *ndpy, int crtc_idx,
  331. struct native_surface *nsurf, uint x, uint y,
  332. const struct native_connector **nconns, int num_nconns,
  333. const struct native_mode *nmode)
  334. {
  335. struct kms_display *kdpy = kms_display(ndpy);
  336. struct kms_surface *ksurf = kms_surface(nsurf);
  337. const struct kms_mode *kmode = kms_mode(nmode);
  338. uint32_t connector_ids[32];
  339. uint32_t buffer_id;
  340. drmModeModeInfo mode_tmp, *mode;
  341. int i;
  342. if (num_nconns > Elements(connector_ids)) {
  343. _eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns);
  344. num_nconns = Elements(connector_ids);
  345. }
  346. if (ksurf) {
  347. if (!kms_surface_init_framebuffers(&ksurf->base, FALSE))
  348. return FALSE;
  349. buffer_id = ksurf->front_fb.buffer_id;
  350. /* the mode argument of drmModeSetCrtc is not constified */
  351. mode_tmp = kmode->mode;
  352. mode = &mode_tmp;
  353. }
  354. else {
  355. /* disable the CRTC */
  356. buffer_id = 0;
  357. mode = NULL;
  358. num_nconns = 0;
  359. }
  360. for (i = 0; i < num_nconns; i++) {
  361. struct kms_connector *kconn = kms_connector(nconns[i]);
  362. connector_ids[i] = kconn->connector->connector_id;
  363. }
  364. if (!kms_display_set_crtc(&kdpy->base, crtc_idx, buffer_id, x, y,
  365. connector_ids, num_nconns, mode)) {
  366. _eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx);
  367. return FALSE;
  368. }
  369. if (kdpy->shown_surfaces[crtc_idx])
  370. kdpy->shown_surfaces[crtc_idx]->is_shown = FALSE;
  371. kdpy->shown_surfaces[crtc_idx] = ksurf;
  372. /* remember the settings for buffer swapping */
  373. if (ksurf) {
  374. uint32_t crtc_id = kdpy->saved_crtcs[crtc_idx].crtc->crtc_id;
  375. struct kms_crtc *kcrtc = &ksurf->current_crtc;
  376. if (kcrtc->crtc)
  377. drmModeFreeCrtc(kcrtc->crtc);
  378. kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
  379. assert(num_nconns < Elements(kcrtc->connectors));
  380. memcpy(kcrtc->connectors, connector_ids,
  381. sizeof(*connector_ids) * num_nconns);
  382. kcrtc->num_connectors = num_nconns;
  383. ksurf->is_shown = TRUE;
  384. }
  385. return TRUE;
  386. }
  387. static const struct native_mode **
  388. kms_display_get_modes(struct native_display *ndpy,
  389. const struct native_connector *nconn,
  390. int *num_modes)
  391. {
  392. struct kms_display *kdpy = kms_display(ndpy);
  393. struct kms_connector *kconn = kms_connector(nconn);
  394. const struct native_mode **nmodes_return;
  395. int count, i;
  396. /* delete old data */
  397. if (kconn->connector) {
  398. drmModeFreeConnector(kconn->connector);
  399. free(kconn->kms_modes);
  400. kconn->connector = NULL;
  401. kconn->kms_modes = NULL;
  402. kconn->num_modes = 0;
  403. }
  404. /* detect again */
  405. kconn->connector = drmModeGetConnector(kdpy->fd, kconn->connector_id);
  406. if (!kconn->connector)
  407. return NULL;
  408. count = kconn->connector->count_modes;
  409. kconn->kms_modes = calloc(count, sizeof(*kconn->kms_modes));
  410. if (!kconn->kms_modes) {
  411. drmModeFreeConnector(kconn->connector);
  412. kconn->connector = NULL;
  413. return NULL;
  414. }
  415. for (i = 0; i < count; i++) {
  416. struct kms_mode *kmode = &kconn->kms_modes[i];
  417. drmModeModeInfoPtr mode = &kconn->connector->modes[i];
  418. kmode->mode = *mode;
  419. kmode->base.desc = kmode->mode.name;
  420. kmode->base.width = kmode->mode.hdisplay;
  421. kmode->base.height = kmode->mode.vdisplay;
  422. kmode->base.refresh_rate = kmode->mode.vrefresh;
  423. /* not all kernels have vrefresh = refresh_rate * 1000 */
  424. if (kmode->base.refresh_rate > 1000)
  425. kmode->base.refresh_rate = (kmode->base.refresh_rate + 500) / 1000;
  426. }
  427. nmodes_return = malloc(count * sizeof(*nmodes_return));
  428. if (nmodes_return) {
  429. for (i = 0; i < count; i++)
  430. nmodes_return[i] = &kconn->kms_modes[i].base;
  431. if (num_modes)
  432. *num_modes = count;
  433. }
  434. return nmodes_return;
  435. }
  436. static const struct native_connector **
  437. kms_display_get_connectors(struct native_display *ndpy, int *num_connectors,
  438. int *num_crtc)
  439. {
  440. struct kms_display *kdpy = kms_display(ndpy);
  441. const struct native_connector **connectors;
  442. int i;
  443. if (!kdpy->connectors) {
  444. kdpy->connectors =
  445. calloc(kdpy->resources->count_connectors, sizeof(*kdpy->connectors));
  446. if (!kdpy->connectors)
  447. return NULL;
  448. for (i = 0; i < kdpy->resources->count_connectors; i++) {
  449. struct kms_connector *kconn = &kdpy->connectors[i];
  450. kconn->connector_id = kdpy->resources->connectors[i];
  451. /* kconn->connector is allocated when the modes are asked */
  452. }
  453. kdpy->num_connectors = kdpy->resources->count_connectors;
  454. }
  455. connectors = malloc(kdpy->num_connectors * sizeof(*connectors));
  456. if (connectors) {
  457. for (i = 0; i < kdpy->num_connectors; i++)
  458. connectors[i] = &kdpy->connectors[i].base;
  459. if (num_connectors)
  460. *num_connectors = kdpy->num_connectors;
  461. }
  462. if (num_crtc)
  463. *num_crtc = kdpy->resources->count_crtcs;
  464. return connectors;
  465. }
  466. static struct native_surface *
  467. kms_display_create_scanout_surface(struct native_display *ndpy,
  468. const struct native_config *nconf,
  469. uint width, uint height)
  470. {
  471. struct kms_surface *ksurf;
  472. ksurf = kms_display_create_surface(ndpy,
  473. KMS_SURFACE_TYPE_SCANOUT, nconf, width, height);
  474. return &ksurf->base;
  475. }
  476. static struct native_surface *
  477. kms_display_create_pbuffer_surface(struct native_display *ndpy,
  478. const struct native_config *nconf,
  479. uint width, uint height)
  480. {
  481. struct kms_surface *ksurf;
  482. ksurf = kms_display_create_surface(ndpy,
  483. KMS_SURFACE_TYPE_PBUFFER, nconf, width, height);
  484. return &ksurf->base;
  485. }
  486. static boolean
  487. kms_display_is_format_supported(struct native_display *ndpy,
  488. enum pipe_format fmt, boolean is_color)
  489. {
  490. return ndpy->screen->is_format_supported(ndpy->screen,
  491. fmt, PIPE_TEXTURE_2D,
  492. (is_color) ? PIPE_BIND_RENDER_TARGET :
  493. PIPE_BIND_DEPTH_STENCIL, 0);
  494. }
  495. static const struct native_config **
  496. kms_display_get_configs(struct native_display *ndpy, int *num_configs)
  497. {
  498. struct kms_display *kdpy = kms_display(ndpy);
  499. const struct native_config **configs;
  500. /* first time */
  501. if (!kdpy->config) {
  502. struct native_config *nconf;
  503. enum pipe_format format;
  504. kdpy->config = calloc(1, sizeof(*kdpy->config));
  505. if (!kdpy->config)
  506. return NULL;
  507. nconf = &kdpy->config->base;
  508. /* always double-buffered */
  509. nconf->mode.doubleBufferMode = TRUE;
  510. format = PIPE_FORMAT_B8G8R8A8_UNORM;
  511. if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) {
  512. format = PIPE_FORMAT_A8R8G8B8_UNORM;
  513. if (!kms_display_is_format_supported(&kdpy->base, format, TRUE))
  514. format = PIPE_FORMAT_NONE;
  515. }
  516. if (format == PIPE_FORMAT_NONE)
  517. return NULL;
  518. nconf->color_format = format;
  519. nconf->mode.redBits = 8;
  520. nconf->mode.greenBits = 8;
  521. nconf->mode.blueBits = 8;
  522. nconf->mode.alphaBits = 8;
  523. nconf->mode.rgbBits = 32;
  524. format = PIPE_FORMAT_Z24S8_UNORM;
  525. if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) {
  526. format = PIPE_FORMAT_S8Z24_UNORM;
  527. if (!kms_display_is_format_supported(&kdpy->base, format, FALSE))
  528. format = PIPE_FORMAT_NONE;
  529. }
  530. if (format != PIPE_FORMAT_NONE) {
  531. nconf->depth_format = format;
  532. nconf->stencil_format = format;
  533. nconf->mode.depthBits = 24;
  534. nconf->mode.stencilBits = 8;
  535. nconf->mode.haveDepthBuffer = TRUE;
  536. nconf->mode.haveStencilBuffer = TRUE;
  537. }
  538. nconf->scanout_bit = TRUE;
  539. nconf->mode.drawableType = GLX_PBUFFER_BIT;
  540. nconf->mode.swapMethod = GLX_SWAP_EXCHANGE_OML;
  541. nconf->mode.visualID = 0;
  542. nconf->mode.visualType = EGL_NONE;
  543. nconf->mode.renderType = GLX_RGBA_BIT;
  544. nconf->mode.rgbMode = TRUE;
  545. nconf->mode.xRenderable = FALSE;
  546. }
  547. configs = malloc(sizeof(*configs));
  548. if (configs) {
  549. configs[0] = &kdpy->config->base;
  550. if (num_configs)
  551. *num_configs = 1;
  552. }
  553. return configs;
  554. }
  555. static int
  556. kms_display_get_param(struct native_display *ndpy,
  557. enum native_param_type param)
  558. {
  559. int val;
  560. switch (param) {
  561. default:
  562. val = 0;
  563. break;
  564. }
  565. return val;
  566. }
  567. static void
  568. kms_display_destroy(struct native_display *ndpy)
  569. {
  570. struct kms_display *kdpy = kms_display(ndpy);
  571. int i;
  572. if (kdpy->config)
  573. free(kdpy->config);
  574. if (kdpy->connectors) {
  575. for (i = 0; i < kdpy->num_connectors; i++) {
  576. struct kms_connector *kconn = &kdpy->connectors[i];
  577. if (kconn->connector) {
  578. drmModeFreeConnector(kconn->connector);
  579. free(kconn->kms_modes);
  580. }
  581. }
  582. free(kdpy->connectors);
  583. }
  584. if (kdpy->shown_surfaces)
  585. free(kdpy->shown_surfaces);
  586. if (kdpy->saved_crtcs) {
  587. for (i = 0; i < kdpy->resources->count_crtcs; i++) {
  588. struct kms_crtc *kcrtc = &kdpy->saved_crtcs[i];
  589. if (kcrtc->crtc) {
  590. /* restore crtc */
  591. drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
  592. kcrtc->crtc->buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
  593. kcrtc->connectors, kcrtc->num_connectors,
  594. &kcrtc->crtc->mode);
  595. drmModeFreeCrtc(kcrtc->crtc);
  596. }
  597. }
  598. free(kdpy->saved_crtcs);
  599. }
  600. if (kdpy->resources)
  601. drmModeFreeResources(kdpy->resources);
  602. if (kdpy->base.screen)
  603. kdpy->base.screen->destroy(kdpy->base.screen);
  604. if (kdpy->fd >= 0)
  605. drmClose(kdpy->fd);
  606. if (kdpy->api)
  607. kdpy->api->destroy(kdpy->api);
  608. free(kdpy);
  609. }
  610. /**
  611. * Initialize KMS and pipe screen.
  612. */
  613. static boolean
  614. kms_display_init_screen(struct native_display *ndpy)
  615. {
  616. struct kms_display *kdpy = kms_display(ndpy);
  617. struct drm_create_screen_arg arg;
  618. int fd;
  619. fd = drmOpen(kdpy->api->name, NULL);
  620. if (fd < 0) {
  621. _eglLog(_EGL_WARNING, "failed to open DRM device");
  622. return FALSE;
  623. }
  624. #if 0
  625. if (drmSetMaster(fd)) {
  626. _eglLog(_EGL_WARNING, "failed to become DRM master");
  627. return FALSE;
  628. }
  629. #endif
  630. memset(&arg, 0, sizeof(arg));
  631. arg.mode = DRM_CREATE_NORMAL;
  632. kdpy->base.screen = kdpy->api->create_screen(kdpy->api, fd, &arg);
  633. if (!kdpy->base.screen) {
  634. _eglLog(_EGL_WARNING, "failed to create DRM screen");
  635. drmClose(fd);
  636. return FALSE;
  637. }
  638. kdpy->fd = fd;
  639. return TRUE;
  640. }
  641. static struct native_display_modeset kms_display_modeset = {
  642. .get_connectors = kms_display_get_connectors,
  643. .get_modes = kms_display_get_modes,
  644. .create_scanout_surface = kms_display_create_scanout_surface,
  645. .program = kms_display_program
  646. };
  647. static struct native_display *
  648. kms_create_display(EGLNativeDisplayType dpy,
  649. struct native_event_handler *event_handler,
  650. struct drm_api *api)
  651. {
  652. struct kms_display *kdpy;
  653. kdpy = CALLOC_STRUCT(kms_display);
  654. if (!kdpy)
  655. return NULL;
  656. kdpy->event_handler = event_handler;
  657. kdpy->api = api;
  658. if (!kdpy->api) {
  659. _eglLog(_EGL_WARNING, "failed to create DRM API");
  660. free(kdpy);
  661. return NULL;
  662. }
  663. kdpy->fd = -1;
  664. if (!kms_display_init_screen(&kdpy->base)) {
  665. kms_display_destroy(&kdpy->base);
  666. return NULL;
  667. }
  668. /* resources are fixed, unlike crtc, connector, or encoder */
  669. kdpy->resources = drmModeGetResources(kdpy->fd);
  670. if (!kdpy->resources) {
  671. kms_display_destroy(&kdpy->base);
  672. return NULL;
  673. }
  674. kdpy->saved_crtcs =
  675. calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs));
  676. if (!kdpy->saved_crtcs) {
  677. kms_display_destroy(&kdpy->base);
  678. return NULL;
  679. }
  680. kdpy->shown_surfaces =
  681. calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces));
  682. if (!kdpy->shown_surfaces) {
  683. kms_display_destroy(&kdpy->base);
  684. return NULL;
  685. }
  686. kdpy->base.destroy = kms_display_destroy;
  687. kdpy->base.get_param = kms_display_get_param;
  688. kdpy->base.get_configs = kms_display_get_configs;
  689. kdpy->base.create_pbuffer_surface = kms_display_create_pbuffer_surface;
  690. kdpy->base.modeset = &kms_display_modeset;
  691. return &kdpy->base;
  692. }
  693. struct native_probe *
  694. native_create_probe(EGLNativeDisplayType dpy)
  695. {
  696. return NULL;
  697. }
  698. enum native_probe_result
  699. native_get_probe_result(struct native_probe *nprobe)
  700. {
  701. return NATIVE_PROBE_UNKNOWN;
  702. }
  703. /* the api is destroyed with the native display */
  704. static struct drm_api *drm_api;
  705. const char *
  706. native_get_name(void)
  707. {
  708. static char kms_name[32];
  709. if (!drm_api)
  710. drm_api = drm_api_create();
  711. if (drm_api)
  712. snprintf(kms_name, sizeof(kms_name), "KMS/%s", drm_api->name);
  713. else
  714. snprintf(kms_name, sizeof(kms_name), "KMS");
  715. return kms_name;
  716. }
  717. struct native_display *
  718. native_create_display(EGLNativeDisplayType dpy,
  719. struct native_event_handler *event_handler)
  720. {
  721. struct native_display *ndpy = NULL;
  722. if (!drm_api)
  723. drm_api = drm_api_create();
  724. if (drm_api)
  725. ndpy = kms_create_display(dpy, event_handler, drm_api);
  726. return ndpy;
  727. }