Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 2010 LunarG Inc.
5
 * Copyright (C) 2011 VMware Inc. All rights reserved.
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
 * Authors:
26
 *    Chia-I Wu 
27
 *    Thomas Hellstrom 
28
 */
29
 
30
#include "util/u_memory.h"
31
#include "util/u_inlines.h"
32
#include "egllog.h"
33
 
34
#include "native_drm.h"
35
 
36
static boolean
37
drm_surface_validate(struct native_surface *nsurf, uint attachment_mask,
38
                     unsigned int *seq_num, struct pipe_resource **textures,
39
                     int *width, int *height)
40
{
41
   struct drm_surface *drmsurf = drm_surface(nsurf);
42
 
43
   if (!resource_surface_add_resources(drmsurf->rsurf, attachment_mask))
44
      return FALSE;
45
   if (textures)
46
      resource_surface_get_resources(drmsurf->rsurf, textures, attachment_mask);
47
 
48
   if (seq_num)
49
      *seq_num = drmsurf->sequence_number;
50
   if (width)
51
      *width = drmsurf->width;
52
   if (height)
53
      *height = drmsurf->height;
54
 
55
   return TRUE;
56
}
57
 
58
/**
59
 * Add textures as DRM framebuffers.
60
 */
61
static boolean
62
drm_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
63
{
64
   struct drm_surface *drmsurf = drm_surface(nsurf);
65
   struct drm_display *drmdpy = drmsurf->drmdpy;
66
   int num_framebuffers = (need_back) ? 2 : 1;
67
   int i, err;
68
 
69
   for (i = 0; i < num_framebuffers; i++) {
70
      struct drm_framebuffer *fb;
71
      enum native_attachment natt;
72
      struct winsys_handle whandle;
73
      uint block_bits;
74
 
75
      if (i == 0) {
76
         fb = &drmsurf->front_fb;
77
         natt = NATIVE_ATTACHMENT_FRONT_LEFT;
78
      }
79
      else {
80
         fb = &drmsurf->back_fb;
81
         natt = NATIVE_ATTACHMENT_BACK_LEFT;
82
      }
83
 
84
      if (!fb->texture) {
85
         /* make sure the texture has been allocated */
86
         resource_surface_add_resources(drmsurf->rsurf, 1 << natt);
87
         fb->texture =
88
            resource_surface_get_single_resource(drmsurf->rsurf, natt);
89
         if (!fb->texture)
90
            return FALSE;
91
      }
92
 
93
      /* already initialized */
94
      if (fb->buffer_id)
95
         continue;
96
 
97
      /* TODO detect the real value */
98
      fb->is_passive = TRUE;
99
 
100
      memset(&whandle, 0, sizeof(whandle));
101
      whandle.type = DRM_API_HANDLE_TYPE_KMS;
102
 
103
      if (!drmdpy->base.screen->resource_get_handle(drmdpy->base.screen,
104
               fb->texture, &whandle))
105
         return FALSE;
106
 
107
      block_bits = util_format_get_blocksizebits(drmsurf->color_format);
108
      err = drmModeAddFB(drmdpy->fd, drmsurf->width, drmsurf->height,
109
            block_bits, block_bits, whandle.stride, whandle.handle,
110
            &fb->buffer_id);
111
      if (err) {
112
         fb->buffer_id = 0;
113
         return FALSE;
114
      }
115
   }
116
 
117
   return TRUE;
118
}
119
 
120
static boolean
121
drm_surface_flush_frontbuffer(struct native_surface *nsurf)
122
{
123
#ifdef DRM_MODE_FEATURE_DIRTYFB
124
   struct drm_surface *drmsurf = drm_surface(nsurf);
125
   struct drm_display *drmdpy = drmsurf->drmdpy;
126
 
127
   if (drmsurf->front_fb.is_passive)
128
      drmModeDirtyFB(drmdpy->fd, drmsurf->front_fb.buffer_id, NULL, 0);
129
#endif
130
 
131
   return TRUE;
132
}
133
 
134
static boolean
135
drm_surface_copy_swap(struct native_surface *nsurf)
136
{
137
   struct drm_surface *drmsurf = drm_surface(nsurf);
138
   struct drm_display *drmdpy = drmsurf->drmdpy;
139
 
140
   (void) resource_surface_throttle(drmsurf->rsurf);
141
   if (!resource_surface_copy_swap(drmsurf->rsurf, &drmdpy->base))
142
      return FALSE;
143
 
144
   (void) resource_surface_flush(drmsurf->rsurf, &drmdpy->base);
145
   if (!drm_surface_flush_frontbuffer(nsurf))
146
      return FALSE;
147
 
148
   drmsurf->sequence_number++;
149
 
150
   return TRUE;
151
}
152
 
153
static boolean
154
drm_surface_swap_buffers(struct native_surface *nsurf)
155
{
156
   struct drm_surface *drmsurf = drm_surface(nsurf);
157
   struct drm_crtc *drmcrtc = &drmsurf->current_crtc;
158
   struct drm_display *drmdpy = drmsurf->drmdpy;
159
   struct drm_framebuffer tmp_fb;
160
   int err;
161
 
162
   if (!drmsurf->have_pageflip)
163
      return drm_surface_copy_swap(nsurf);
164
 
165
   if (!drmsurf->back_fb.buffer_id) {
166
      if (!drm_surface_init_framebuffers(&drmsurf->base, TRUE))
167
         return FALSE;
168
   }
169
 
170
   if (drmsurf->is_shown && drmcrtc->crtc) {
171
      err = drmModePageFlip(drmdpy->fd, drmcrtc->crtc->crtc_id,
172
			    drmsurf->back_fb.buffer_id, 0, NULL);
173
      if (err) {
174
	 drmsurf->have_pageflip = FALSE;
175
         return drm_surface_copy_swap(nsurf);
176
      }
177
   }
178
 
179
   /* swap the buffers */
180
   tmp_fb = drmsurf->front_fb;
181
   drmsurf->front_fb = drmsurf->back_fb;
182
   drmsurf->back_fb = tmp_fb;
183
 
184
   resource_surface_swap_buffers(drmsurf->rsurf,
185
         NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, FALSE);
186
   /* the front/back textures are swapped */
187
   drmsurf->sequence_number++;
188
   drmdpy->event_handler->invalid_surface(&drmdpy->base,
189
         &drmsurf->base, drmsurf->sequence_number);
190
 
191
   return TRUE;
192
}
193
 
194
static boolean
195
drm_surface_present(struct native_surface *nsurf,
196
                    const struct native_present_control *ctrl)
197
{
198
   boolean ret;
199
 
200
   if (ctrl->swap_interval)
201
      return FALSE;
202
 
203
   switch (ctrl->natt) {
204
   case NATIVE_ATTACHMENT_FRONT_LEFT:
205
      ret = drm_surface_flush_frontbuffer(nsurf);
206
      break;
207
   case NATIVE_ATTACHMENT_BACK_LEFT:
208
      if (ctrl->preserve)
209
	 ret = drm_surface_copy_swap(nsurf);
210
      else
211
	 ret = drm_surface_swap_buffers(nsurf);
212
      break;
213
   default:
214
      ret = FALSE;
215
      break;
216
   }
217
 
218
   return ret;
219
}
220
 
221
static void
222
drm_surface_wait(struct native_surface *nsurf)
223
{
224
   struct drm_surface *drmsurf = drm_surface(nsurf);
225
 
226
   resource_surface_wait(drmsurf->rsurf);
227
}
228
 
229
static void
230
drm_surface_destroy(struct native_surface *nsurf)
231
{
232
   struct drm_surface *drmsurf = drm_surface(nsurf);
233
 
234
   resource_surface_wait(drmsurf->rsurf);
235
   if (drmsurf->current_crtc.crtc)
236
         drmModeFreeCrtc(drmsurf->current_crtc.crtc);
237
 
238
   if (drmsurf->front_fb.buffer_id)
239
      drmModeRmFB(drmsurf->drmdpy->fd, drmsurf->front_fb.buffer_id);
240
   pipe_resource_reference(&drmsurf->front_fb.texture, NULL);
241
 
242
   if (drmsurf->back_fb.buffer_id)
243
      drmModeRmFB(drmsurf->drmdpy->fd, drmsurf->back_fb.buffer_id);
244
   pipe_resource_reference(&drmsurf->back_fb.texture, NULL);
245
 
246
   resource_surface_destroy(drmsurf->rsurf);
247
   FREE(drmsurf);
248
}
249
 
250
static struct drm_surface *
251
drm_display_create_surface(struct native_display *ndpy,
252
                           const struct native_config *nconf,
253
                           uint width, uint height)
254
{
255
   struct drm_display *drmdpy = drm_display(ndpy);
256
   struct drm_config *drmconf = drm_config(nconf);
257
   struct drm_surface *drmsurf;
258
 
259
   drmsurf = CALLOC_STRUCT(drm_surface);
260
   if (!drmsurf)
261
      return NULL;
262
 
263
   drmsurf->drmdpy = drmdpy;
264
   drmsurf->color_format = drmconf->base.color_format;
265
   drmsurf->width = width;
266
   drmsurf->height = height;
267
   drmsurf->have_pageflip = TRUE;
268
 
269
   drmsurf->rsurf = resource_surface_create(drmdpy->base.screen,
270
         drmsurf->color_format,
271
         PIPE_BIND_RENDER_TARGET |
272
         PIPE_BIND_SAMPLER_VIEW |
273
         PIPE_BIND_DISPLAY_TARGET |
274
         PIPE_BIND_SCANOUT);
275
   if (!drmsurf->rsurf) {
276
      FREE(drmsurf);
277
      return NULL;
278
   }
279
 
280
   resource_surface_set_size(drmsurf->rsurf, drmsurf->width, drmsurf->height);
281
 
282
   drmsurf->base.destroy = drm_surface_destroy;
283
   drmsurf->base.present = drm_surface_present;
284
   drmsurf->base.validate = drm_surface_validate;
285
   drmsurf->base.wait = drm_surface_wait;
286
 
287
   return drmsurf;
288
}
289
 
290
struct native_surface *
291
drm_display_create_surface_from_resource(struct native_display *ndpy,
292
                                         struct pipe_resource *resource)
293
{
294
   struct drm_display *drmdpy = drm_display(ndpy);
295
   struct drm_surface *drmsurf;
296
   enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT;
297
 
298
   drmsurf = CALLOC_STRUCT(drm_surface);
299
   if (!drmsurf)
300
      return NULL;
301
 
302
   drmsurf->drmdpy = drmdpy;
303
   drmsurf->color_format = resource->format;
304
   drmsurf->width = resource->width0;
305
   drmsurf->height = resource->height0;
306
   drmsurf->have_pageflip = FALSE;
307
 
308
   drmsurf->rsurf = resource_surface_create(drmdpy->base.screen,
309
         drmsurf->color_format,
310
         PIPE_BIND_RENDER_TARGET |
311
         PIPE_BIND_SAMPLER_VIEW |
312
         PIPE_BIND_DISPLAY_TARGET |
313
         PIPE_BIND_SCANOUT);
314
 
315
   resource_surface_import_resource(drmsurf->rsurf, natt, resource);
316
 
317
   drmsurf->base.destroy = drm_surface_destroy;
318
   drmsurf->base.present = drm_surface_present;
319
   drmsurf->base.validate = drm_surface_validate;
320
   drmsurf->base.wait = drm_surface_wait;
321
 
322
   return &drmsurf->base;
323
}
324
 
325
 
326
/**
327
 * Choose a CRTC that supports all given connectors.
328
 */
329
static uint32_t
330
drm_display_choose_crtc(struct native_display *ndpy,
331
                        uint32_t *connectors, int num_connectors)
332
{
333
   struct drm_display *drmdpy = drm_display(ndpy);
334
   int idx;
335
 
336
   for (idx = 0; idx < drmdpy->resources->count_crtcs; idx++) {
337
      boolean found_crtc = TRUE;
338
      int i, j;
339
 
340
      for (i = 0; i < num_connectors; i++) {
341
         drmModeConnectorPtr connector;
342
         int encoder_idx = -1;
343
 
344
         connector = drmModeGetConnector(drmdpy->fd, connectors[i]);
345
         if (!connector) {
346
            found_crtc = FALSE;
347
            break;
348
         }
349
 
350
         /* find an encoder the CRTC supports */
351
         for (j = 0; j < connector->count_encoders; j++) {
352
            drmModeEncoderPtr encoder =
353
               drmModeGetEncoder(drmdpy->fd, connector->encoders[j]);
354
            if (encoder->possible_crtcs & (1 << idx)) {
355
               encoder_idx = j;
356
               break;
357
            }
358
            drmModeFreeEncoder(encoder);
359
         }
360
 
361
         drmModeFreeConnector(connector);
362
         if (encoder_idx < 0) {
363
            found_crtc = FALSE;
364
            break;
365
         }
366
      }
367
 
368
      if (found_crtc)
369
         break;
370
   }
371
 
372
   if (idx >= drmdpy->resources->count_crtcs) {
373
      _eglLog(_EGL_WARNING,
374
            "failed to find a CRTC that supports the given %d connectors",
375
            num_connectors);
376
      return 0;
377
   }
378
 
379
   return drmdpy->resources->crtcs[idx];
380
}
381
 
382
/**
383
 * Remember the original CRTC status and set the CRTC
384
 */
385
static boolean
386
drm_display_set_crtc(struct native_display *ndpy, int crtc_idx,
387
                     uint32_t buffer_id, uint32_t x, uint32_t y,
388
                     uint32_t *connectors, int num_connectors,
389
                     drmModeModeInfoPtr mode)
390
{
391
   struct drm_display *drmdpy = drm_display(ndpy);
392
   struct drm_crtc *drmcrtc = &drmdpy->saved_crtcs[crtc_idx];
393
   uint32_t crtc_id;
394
   int err;
395
 
396
   if (drmcrtc->crtc) {
397
      crtc_id = drmcrtc->crtc->crtc_id;
398
   }
399
   else {
400
      int count = 0, i;
401
 
402
      /*
403
       * Choose the CRTC once.  It could be more dynamic, but let's keep it
404
       * simple for now.
405
       */
406
      crtc_id = drm_display_choose_crtc(&drmdpy->base,
407
            connectors, num_connectors);
408
 
409
      /* save the original CRTC status */
410
      drmcrtc->crtc = drmModeGetCrtc(drmdpy->fd, crtc_id);
411
      if (!drmcrtc->crtc)
412
         return FALSE;
413
 
414
      for (i = 0; i < drmdpy->num_connectors; i++) {
415
         struct drm_connector *drmconn = &drmdpy->connectors[i];
416
         drmModeConnectorPtr connector = drmconn->connector;
417
         drmModeEncoderPtr encoder;
418
 
419
         encoder = drmModeGetEncoder(drmdpy->fd, connector->encoder_id);
420
         if (encoder) {
421
            if (encoder->crtc_id == crtc_id) {
422
               drmcrtc->connectors[count++] = connector->connector_id;
423
               if (count >= Elements(drmcrtc->connectors))
424
                  break;
425
            }
426
            drmModeFreeEncoder(encoder);
427
         }
428
      }
429
 
430
      drmcrtc->num_connectors = count;
431
   }
432
 
433
   err = drmModeSetCrtc(drmdpy->fd, crtc_id, buffer_id, x, y,
434
         connectors, num_connectors, mode);
435
   if (err) {
436
      drmModeFreeCrtc(drmcrtc->crtc);
437
      drmcrtc->crtc = NULL;
438
      drmcrtc->num_connectors = 0;
439
 
440
      return FALSE;
441
   }
442
 
443
   return TRUE;
444
}
445
 
446
static boolean
447
drm_display_program(struct native_display *ndpy, int crtc_idx,
448
                    struct native_surface *nsurf, uint x, uint y,
449
                    const struct native_connector **nconns, int num_nconns,
450
                    const struct native_mode *nmode)
451
{
452
   struct drm_display *drmdpy = drm_display(ndpy);
453
   struct drm_surface *drmsurf = drm_surface(nsurf);
454
   const struct drm_mode *drmmode = drm_mode(nmode);
455
   uint32_t connector_ids[32];
456
   uint32_t buffer_id;
457
   drmModeModeInfo mode_tmp, *mode;
458
   int i;
459
 
460
   if (num_nconns > Elements(connector_ids)) {
461
      _eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns);
462
      num_nconns = Elements(connector_ids);
463
   }
464
 
465
   if (drmsurf) {
466
      if (!drm_surface_init_framebuffers(&drmsurf->base, FALSE))
467
         return FALSE;
468
 
469
      buffer_id = drmsurf->front_fb.buffer_id;
470
      /* the mode argument of drmModeSetCrtc is not constified */
471
      mode_tmp = drmmode->mode;
472
      mode = &mode_tmp;
473
   }
474
   else {
475
      /* disable the CRTC */
476
      buffer_id = 0;
477
      mode = NULL;
478
      num_nconns = 0;
479
   }
480
 
481
   for (i = 0; i < num_nconns; i++) {
482
      struct drm_connector *drmconn = drm_connector(nconns[i]);
483
      connector_ids[i] = drmconn->connector->connector_id;
484
   }
485
 
486
   if (!drm_display_set_crtc(&drmdpy->base, crtc_idx, buffer_id, x, y,
487
            connector_ids, num_nconns, mode)) {
488
      _eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx);
489
 
490
      return FALSE;
491
   }
492
 
493
   if (drmdpy->shown_surfaces[crtc_idx])
494
      drmdpy->shown_surfaces[crtc_idx]->is_shown = FALSE;
495
   drmdpy->shown_surfaces[crtc_idx] = drmsurf;
496
 
497
   /* remember the settings for buffer swapping */
498
   if (drmsurf) {
499
      uint32_t crtc_id = drmdpy->saved_crtcs[crtc_idx].crtc->crtc_id;
500
      struct drm_crtc *drmcrtc = &drmsurf->current_crtc;
501
 
502
      if (drmcrtc->crtc)
503
         drmModeFreeCrtc(drmcrtc->crtc);
504
      drmcrtc->crtc = drmModeGetCrtc(drmdpy->fd, crtc_id);
505
 
506
      assert(num_nconns < Elements(drmcrtc->connectors));
507
      memcpy(drmcrtc->connectors, connector_ids,
508
            sizeof(*connector_ids) * num_nconns);
509
      drmcrtc->num_connectors = num_nconns;
510
 
511
      drmsurf->is_shown = TRUE;
512
   }
513
 
514
   return TRUE;
515
}
516
 
517
static const struct native_mode **
518
drm_display_get_modes(struct native_display *ndpy,
519
                      const struct native_connector *nconn,
520
                      int *num_modes)
521
{
522
   struct drm_display *drmdpy = drm_display(ndpy);
523
   struct drm_connector *drmconn = drm_connector(nconn);
524
   const struct native_mode **nmodes_return;
525
   int count, i;
526
 
527
   /* delete old data */
528
   if (drmconn->connector) {
529
      drmModeFreeConnector(drmconn->connector);
530
      FREE(drmconn->drm_modes);
531
 
532
      drmconn->connector = NULL;
533
      drmconn->drm_modes = NULL;
534
      drmconn->num_modes = 0;
535
   }
536
 
537
   /* detect again */
538
   drmconn->connector = drmModeGetConnector(drmdpy->fd, drmconn->connector_id);
539
   if (!drmconn->connector)
540
      return NULL;
541
 
542
   count = drmconn->connector->count_modes;
543
   drmconn->drm_modes = CALLOC(count, sizeof(*drmconn->drm_modes));
544
   if (!drmconn->drm_modes) {
545
      drmModeFreeConnector(drmconn->connector);
546
      drmconn->connector = NULL;
547
 
548
      return NULL;
549
   }
550
 
551
   for (i = 0; i < count; i++) {
552
      struct drm_mode *drmmode = &drmconn->drm_modes[i];
553
      drmModeModeInfoPtr mode = &drmconn->connector->modes[i];
554
 
555
      drmmode->mode = *mode;
556
 
557
      drmmode->base.desc = drmmode->mode.name;
558
      drmmode->base.width = drmmode->mode.hdisplay;
559
      drmmode->base.height = drmmode->mode.vdisplay;
560
      drmmode->base.refresh_rate = drmmode->mode.vrefresh;
561
      /* not all kernels have vrefresh = refresh_rate * 1000 */
562
      if (drmmode->base.refresh_rate < 1000)
563
         drmmode->base.refresh_rate *= 1000;
564
   }
565
 
566
   nmodes_return = MALLOC(count * sizeof(*nmodes_return));
567
   if (nmodes_return) {
568
      for (i = 0; i < count; i++)
569
         nmodes_return[i] = &drmconn->drm_modes[i].base;
570
      if (num_modes)
571
         *num_modes = count;
572
   }
573
 
574
   return nmodes_return;
575
}
576
 
577
static const struct native_connector **
578
drm_display_get_connectors(struct native_display *ndpy, int *num_connectors,
579
                           int *num_crtc)
580
{
581
   struct drm_display *drmdpy = drm_display(ndpy);
582
   const struct native_connector **connectors;
583
   int i;
584
 
585
   if (!drmdpy->connectors) {
586
      drmdpy->connectors =
587
         CALLOC(drmdpy->resources->count_connectors, sizeof(*drmdpy->connectors));
588
      if (!drmdpy->connectors)
589
         return NULL;
590
 
591
      for (i = 0; i < drmdpy->resources->count_connectors; i++) {
592
         struct drm_connector *drmconn = &drmdpy->connectors[i];
593
 
594
         drmconn->connector_id = drmdpy->resources->connectors[i];
595
         /* drmconn->connector is allocated when the modes are asked */
596
      }
597
 
598
      drmdpy->num_connectors = drmdpy->resources->count_connectors;
599
   }
600
 
601
   connectors = MALLOC(drmdpy->num_connectors * sizeof(*connectors));
602
   if (connectors) {
603
      for (i = 0; i < drmdpy->num_connectors; i++)
604
         connectors[i] = &drmdpy->connectors[i].base;
605
      if (num_connectors)
606
         *num_connectors = drmdpy->num_connectors;
607
   }
608
 
609
   if (num_crtc)
610
      *num_crtc = drmdpy->resources->count_crtcs;
611
 
612
   return connectors;
613
}
614
 
615
static struct native_surface *
616
drm_display_create_scanout_surface(struct native_display *ndpy,
617
                                   const struct native_config *nconf,
618
                                   uint width, uint height)
619
{
620
   struct drm_surface *drmsurf;
621
 
622
   drmsurf = drm_display_create_surface(ndpy, nconf, width, height);
623
   return &drmsurf->base;
624
}
625
 
626
static struct native_display_modeset drm_display_modeset = {
627
   .get_connectors = drm_display_get_connectors,
628
   .get_modes = drm_display_get_modes,
629
   .create_scanout_surface = drm_display_create_scanout_surface,
630
   .program = drm_display_program
631
};
632
 
633
void
634
drm_display_fini_modeset(struct native_display *ndpy)
635
{
636
   struct drm_display *drmdpy = drm_display(ndpy);
637
   int i;
638
 
639
   if (drmdpy->connectors) {
640
      for (i = 0; i < drmdpy->num_connectors; i++) {
641
         struct drm_connector *drmconn = &drmdpy->connectors[i];
642
         if (drmconn->connector) {
643
            drmModeFreeConnector(drmconn->connector);
644
            FREE(drmconn->drm_modes);
645
         }
646
      }
647
      FREE(drmdpy->connectors);
648
   }
649
 
650
   FREE(drmdpy->shown_surfaces);
651
   drmdpy->shown_surfaces = NULL;
652
 
653
   if (drmdpy->saved_crtcs) {
654
      for (i = 0; i < drmdpy->resources->count_crtcs; i++) {
655
         struct drm_crtc *drmcrtc = &drmdpy->saved_crtcs[i];
656
 
657
         if (drmcrtc->crtc) {
658
            /* restore crtc */
659
            drmModeSetCrtc(drmdpy->fd, drmcrtc->crtc->crtc_id,
660
                  drmcrtc->crtc->buffer_id, drmcrtc->crtc->x, drmcrtc->crtc->y,
661
                  drmcrtc->connectors, drmcrtc->num_connectors,
662
                  &drmcrtc->crtc->mode);
663
 
664
            drmModeFreeCrtc(drmcrtc->crtc);
665
         }
666
      }
667
      FREE(drmdpy->saved_crtcs);
668
   }
669
 
670
   if (drmdpy->resources) {
671
      drmModeFreeResources(drmdpy->resources);
672
      drmdpy->resources = NULL;
673
   }
674
 
675
   drmdpy->base.modeset = NULL;
676
}
677
 
678
boolean
679
drm_display_init_modeset(struct native_display *ndpy)
680
{
681
   struct drm_display *drmdpy = drm_display(ndpy);
682
 
683
   /* resources are fixed, unlike crtc, connector, or encoder */
684
   drmdpy->resources = drmModeGetResources(drmdpy->fd);
685
   if (!drmdpy->resources) {
686
      _eglLog(_EGL_DEBUG, "Failed to get KMS resources.  Disable modeset.");
687
      return FALSE;
688
   }
689
 
690
   drmdpy->saved_crtcs =
691
      CALLOC(drmdpy->resources->count_crtcs, sizeof(*drmdpy->saved_crtcs));
692
   if (!drmdpy->saved_crtcs) {
693
      drm_display_fini_modeset(&drmdpy->base);
694
      return FALSE;
695
   }
696
 
697
   drmdpy->shown_surfaces =
698
      CALLOC(drmdpy->resources->count_crtcs, sizeof(*drmdpy->shown_surfaces));
699
   if (!drmdpy->shown_surfaces) {
700
      drm_display_fini_modeset(&drmdpy->base);
701
      return FALSE;
702
   }
703
 
704
   drmdpy->base.modeset = &drm_display_modeset;
705
 
706
   return TRUE;
707
}