Subversion Repositories Kolibri OS

Rev

Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 2009-2010 Chia-I Wu 
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included
14
 * in all copies or substantial portions of the 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 NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS 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
#include "util/u_memory.h"
26
#include "util/u_math.h"
27
#include "util/u_format.h"
28
#include "util/u_inlines.h"
29
#include "util/u_hash_table.h"
30
#include "pipe/p_compiler.h"
31
#include "pipe/p_screen.h"
32
#include "pipe/p_context.h"
33
#include "pipe/p_state.h"
34
#include "state_tracker/drm_driver.h"
35
#include "egllog.h"
36
 
37
#include "native_x11.h"
38
#include "x11_screen.h"
39
 
40
#include "common/native_helper.h"
41
#ifdef HAVE_WAYLAND_BACKEND
42
#include "common/native_wayland_drm_bufmgr_helper.h"
43
#endif
44
 
45
#ifdef GLX_DIRECT_RENDERING
46
 
47
struct dri2_display {
48
   struct native_display base;
49
   Display *dpy;
50
   boolean own_dpy;
51
 
52
   const struct native_event_handler *event_handler;
53
 
54
   struct x11_screen *xscr;
55
   int xscr_number;
56
   const char *dri_driver;
57
   int dri_major, dri_minor;
58
 
59
   struct dri2_config *configs;
60
   int num_configs;
61
 
62
   struct util_hash_table *surfaces;
63
#ifdef HAVE_WAYLAND_BACKEND
64
   struct wl_drm *wl_server_drm; /* for EGL_WL_bind_wayland_display */
65
#endif
66
};
67
 
68
struct dri2_surface {
69
   struct native_surface base;
70
   Drawable drawable;
71
   enum pipe_format color_format;
72
   struct dri2_display *dri2dpy;
73
 
74
   unsigned int server_stamp;
75
   unsigned int client_stamp;
76
   int width, height;
77
   struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
78
   uint valid_mask;
79
 
80
   boolean have_back, have_fake;
81
 
82
   struct x11_drawable_buffer *last_xbufs;
83
   int last_num_xbufs;
84
};
85
 
86
struct dri2_config {
87
   struct native_config base;
88
};
89
 
90
static INLINE struct dri2_display *
91
dri2_display(const struct native_display *ndpy)
92
{
93
   return (struct dri2_display *) ndpy;
94
}
95
 
96
static INLINE struct dri2_surface *
97
dri2_surface(const struct native_surface *nsurf)
98
{
99
   return (struct dri2_surface *) nsurf;
100
}
101
 
102
static INLINE struct dri2_config *
103
dri2_config(const struct native_config *nconf)
104
{
105
   return (struct dri2_config *) nconf;
106
}
107
 
108
/**
109
 * Process the buffers returned by the server.
110
 */
111
static void
112
dri2_surface_process_drawable_buffers(struct native_surface *nsurf,
113
                                      struct x11_drawable_buffer *xbufs,
114
                                      int num_xbufs)
115
{
116
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
117
   struct dri2_display *dri2dpy = dri2surf->dri2dpy;
118
   struct pipe_resource templ;
119
   struct winsys_handle whandle;
120
   uint valid_mask;
121
   int i;
122
 
123
   /* free the old textures */
124
   for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++)
125
      pipe_resource_reference(&dri2surf->textures[i], NULL);
126
   dri2surf->valid_mask = 0x0;
127
 
128
   dri2surf->have_back = FALSE;
129
   dri2surf->have_fake = FALSE;
130
 
131
   if (!xbufs)
132
      return;
133
 
134
   memset(&templ, 0, sizeof(templ));
135
   templ.target = PIPE_TEXTURE_2D;
136
   templ.last_level = 0;
137
   templ.width0 = dri2surf->width;
138
   templ.height0 = dri2surf->height;
139
   templ.depth0 = 1;
140
   templ.array_size = 1;
141
   templ.format = dri2surf->color_format;
142
   templ.bind = PIPE_BIND_RENDER_TARGET;
143
 
144
   valid_mask = 0x0;
145
   for (i = 0; i < num_xbufs; i++) {
146
      struct x11_drawable_buffer *xbuf = &xbufs[i];
147
      const char *desc;
148
      enum native_attachment natt;
149
 
150
      switch (xbuf->attachment) {
151
      case DRI2BufferFrontLeft:
152
         natt = NATIVE_ATTACHMENT_FRONT_LEFT;
153
         desc = "DRI2 Front Buffer";
154
         break;
155
      case DRI2BufferFakeFrontLeft:
156
         natt = NATIVE_ATTACHMENT_FRONT_LEFT;
157
         desc = "DRI2 Fake Front Buffer";
158
         dri2surf->have_fake = TRUE;
159
         break;
160
      case DRI2BufferBackLeft:
161
         natt = NATIVE_ATTACHMENT_BACK_LEFT;
162
         desc = "DRI2 Back Buffer";
163
         dri2surf->have_back = TRUE;
164
         break;
165
      default:
166
         desc = NULL;
167
         break;
168
      }
169
 
170
      if (!desc || dri2surf->textures[natt]) {
171
         if (!desc)
172
            _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
173
         else
174
            _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
175
         continue;
176
      }
177
 
178
      memset(&whandle, 0, sizeof(whandle));
179
      whandle.stride = xbuf->pitch;
180
      whandle.handle = xbuf->name;
181
      dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle(
182
         dri2dpy->base.screen, &templ, &whandle);
183
      if (dri2surf->textures[natt])
184
         valid_mask |= 1 << natt;
185
   }
186
 
187
   dri2surf->valid_mask = valid_mask;
188
}
189
 
190
/**
191
 * Get the buffers from the server.
192
 */
193
static void
194
dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
195
{
196
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
197
   struct dri2_display *dri2dpy = dri2surf->dri2dpy;
198
   unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS * 2];
199
   int num_ins, num_outs, att;
200
   struct x11_drawable_buffer *xbufs;
201
   uint bpp = util_format_get_blocksizebits(dri2surf->color_format);
202
   boolean with_format = FALSE; /* never ask for depth/stencil */
203
 
204
   /* We must get the front on servers which doesn't support with format
205
    * due to a silly bug in core dri2. You can't copy to/from a buffer
206
    * that you haven't requested and you recive BadValue errors */
207
   if (dri2surf->dri2dpy->dri_minor < 1) {
208
      with_format = FALSE;
209
      buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT);
210
   }
211
 
212
   /* prepare the attachments */
213
   num_ins = 0;
214
   for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
215
      if (native_attachment_mask_test(buffer_mask, att)) {
216
         unsigned int dri2att;
217
 
218
         switch (att) {
219
         case NATIVE_ATTACHMENT_FRONT_LEFT:
220
            dri2att = DRI2BufferFrontLeft;
221
            break;
222
         case NATIVE_ATTACHMENT_BACK_LEFT:
223
            dri2att = DRI2BufferBackLeft;
224
            break;
225
         case NATIVE_ATTACHMENT_FRONT_RIGHT:
226
            dri2att = DRI2BufferFrontRight;
227
            break;
228
         case NATIVE_ATTACHMENT_BACK_RIGHT:
229
            dri2att = DRI2BufferBackRight;
230
            break;
231
         default:
232
            assert(0);
233
            dri2att = 0;
234
            break;
235
         }
236
 
237
         dri2atts[num_ins++] = dri2att;
238
         if (with_format)
239
            dri2atts[num_ins++] = bpp;
240
      }
241
   }
242
   if (with_format)
243
      num_ins /= 2;
244
 
245
   xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
246
                                    &dri2surf->width, &dri2surf->height,
247
                                    dri2atts, with_format, num_ins, &num_outs);
248
 
249
   /* we should be able to do better... */
250
   if (xbufs && dri2surf->last_num_xbufs == num_outs &&
251
       memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) {
252
      FREE(xbufs);
253
      dri2surf->client_stamp = dri2surf->server_stamp;
254
      return;
255
   }
256
 
257
   dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs);
258
 
259
   dri2surf->server_stamp++;
260
   dri2surf->client_stamp = dri2surf->server_stamp;
261
 
262
   FREE(dri2surf->last_xbufs);
263
   dri2surf->last_xbufs = xbufs;
264
   dri2surf->last_num_xbufs = num_outs;
265
}
266
 
267
/**
268
 * Update the buffers of the surface.  This is a slow function due to the
269
 * round-trip to the server.
270
 */
271
static boolean
272
dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
273
{
274
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
275
 
276
   dri2_surface_get_buffers(&dri2surf->base, buffer_mask);
277
 
278
   return ((dri2surf->valid_mask & buffer_mask) == buffer_mask);
279
}
280
 
281
/**
282
 * Return TRUE if the surface receives DRI2_InvalidateBuffers events.
283
 */
284
static INLINE boolean
285
dri2_surface_receive_events(struct native_surface *nsurf)
286
{
287
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
288
   return (dri2surf->dri2dpy->dri_minor >= 3);
289
}
290
 
291
static boolean
292
dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
293
{
294
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
295
   struct dri2_display *dri2dpy = dri2surf->dri2dpy;
296
 
297
   /* copy to real front buffer */
298
   if (dri2surf->have_fake)
299
      x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
300
            0, 0, dri2surf->width, dri2surf->height,
301
            DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
302
 
303
   /* force buffers to be updated in next validation call */
304
   if (!dri2_surface_receive_events(&dri2surf->base)) {
305
      dri2surf->server_stamp++;
306
      dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
307
            &dri2surf->base, dri2surf->server_stamp);
308
   }
309
 
310
   return TRUE;
311
}
312
 
313
static boolean
314
dri2_surface_swap_buffers(struct native_surface *nsurf, int num_rects,
315
                          const int *rects)
316
{
317
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
318
   struct dri2_display *dri2dpy = dri2surf->dri2dpy;
319
 
320
   /* copy to front buffer */
321
   if (dri2surf->have_back) {
322
      if (num_rects > 0)
323
         x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable,
324
               num_rects, rects,
325
               DRI2BufferBackLeft, DRI2BufferFrontLeft);
326
      else
327
         x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
328
               0, 0, dri2surf->width, dri2surf->height,
329
               DRI2BufferBackLeft, DRI2BufferFrontLeft);
330
   }
331
 
332
   /* and update fake front buffer */
333
   if (dri2surf->have_fake) {
334
      if (num_rects > 0)
335
         x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable,
336
               num_rects, rects,
337
               DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
338
      else
339
         x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
340
               0, 0, dri2surf->width, dri2surf->height,
341
               DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
342
   }
343
 
344
   /* force buffers to be updated in next validation call */
345
   if (!dri2_surface_receive_events(&dri2surf->base)) {
346
      dri2surf->server_stamp++;
347
      dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
348
            &dri2surf->base, dri2surf->server_stamp);
349
   }
350
 
351
   return TRUE;
352
}
353
 
354
static boolean
355
dri2_surface_present(struct native_surface *nsurf,
356
                     const struct native_present_control *ctrl)
357
{
358
   boolean ret;
359
 
360
   if (ctrl->swap_interval)
361
      return FALSE;
362
 
363
   switch (ctrl->natt) {
364
   case NATIVE_ATTACHMENT_FRONT_LEFT:
365
      ret = dri2_surface_flush_frontbuffer(nsurf);
366
      break;
367
   case NATIVE_ATTACHMENT_BACK_LEFT:
368
      ret = dri2_surface_swap_buffers(nsurf, ctrl->num_rects, ctrl->rects);
369
      break;
370
   default:
371
      ret = FALSE;
372
      break;
373
   }
374
 
375
   return ret;
376
}
377
 
378
static boolean
379
dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
380
                      unsigned int *seq_num, struct pipe_resource **textures,
381
                      int *width, int *height)
382
{
383
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
384
 
385
   if (dri2surf->server_stamp != dri2surf->client_stamp ||
386
       (dri2surf->valid_mask & attachment_mask) != attachment_mask) {
387
      if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask))
388
         return FALSE;
389
   }
390
 
391
   if (seq_num)
392
      *seq_num = dri2surf->client_stamp;
393
 
394
   if (textures) {
395
      int att;
396
      for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
397
         if (native_attachment_mask_test(attachment_mask, att)) {
398
            struct pipe_resource *ptex = dri2surf->textures[att];
399
 
400
            textures[att] = NULL;
401
            pipe_resource_reference(&textures[att], ptex);
402
         }
403
      }
404
   }
405
 
406
   if (width)
407
      *width = dri2surf->width;
408
   if (height)
409
      *height = dri2surf->height;
410
 
411
   return TRUE;
412
}
413
 
414
static void
415
dri2_surface_wait(struct native_surface *nsurf)
416
{
417
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
418
   struct dri2_display *dri2dpy = dri2surf->dri2dpy;
419
 
420
   if (dri2surf->have_fake) {
421
      x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
422
            0, 0, dri2surf->width, dri2surf->height,
423
            DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
424
   }
425
}
426
 
427
static void
428
dri2_surface_destroy(struct native_surface *nsurf)
429
{
430
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
431
   int i;
432
 
433
   FREE(dri2surf->last_xbufs);
434
 
435
   for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
436
      struct pipe_resource *ptex = dri2surf->textures[i];
437
      pipe_resource_reference(&ptex, NULL);
438
   }
439
 
440
   if (dri2surf->drawable) {
441
      x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
442
            dri2surf->drawable, FALSE);
443
 
444
      util_hash_table_remove(dri2surf->dri2dpy->surfaces,
445
            (void *) dri2surf->drawable);
446
   }
447
   FREE(dri2surf);
448
}
449
 
450
static struct dri2_surface *
451
dri2_display_create_surface(struct native_display *ndpy,
452
                            Drawable drawable,
453
                            enum pipe_format color_format)
454
{
455
   struct dri2_display *dri2dpy = dri2_display(ndpy);
456
   struct dri2_surface *dri2surf;
457
 
458
   dri2surf = CALLOC_STRUCT(dri2_surface);
459
   if (!dri2surf)
460
      return NULL;
461
 
462
   dri2surf->dri2dpy = dri2dpy;
463
   dri2surf->drawable = drawable;
464
   dri2surf->color_format = color_format;
465
 
466
   dri2surf->base.destroy = dri2_surface_destroy;
467
   dri2surf->base.present = dri2_surface_present;
468
   dri2surf->base.validate = dri2_surface_validate;
469
   dri2surf->base.wait = dri2_surface_wait;
470
 
471
   if (drawable) {
472
      x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE);
473
      /* initialize the geometry */
474
      dri2_surface_update_buffers(&dri2surf->base, 0x0);
475
 
476
      util_hash_table_set(dri2surf->dri2dpy->surfaces,
477
            (void *) dri2surf->drawable, (void *) &dri2surf->base);
478
   }
479
 
480
   return dri2surf;
481
}
482
 
483
static struct native_surface *
484
dri2_display_create_window_surface(struct native_display *ndpy,
485
                                   EGLNativeWindowType win,
486
                                   const struct native_config *nconf)
487
{
488
   struct dri2_surface *dri2surf;
489
 
490
   dri2surf = dri2_display_create_surface(ndpy,
491
         (Drawable) win, nconf->color_format);
492
   return (dri2surf) ? &dri2surf->base : NULL;
493
}
494
 
495
static struct native_surface *
496
dri2_display_create_pixmap_surface(struct native_display *ndpy,
497
                                   EGLNativePixmapType pix,
498
                                   const struct native_config *nconf)
499
{
500
   struct dri2_surface *dri2surf;
501
 
502
   if (!nconf) {
503
      struct dri2_display *dri2dpy = dri2_display(ndpy);
504
      uint depth, nconf_depth;
505
      int i;
506
 
507
      depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
508
      for (i = 0; i < dri2dpy->num_configs; i++) {
509
         nconf_depth = util_format_get_blocksizebits(
510
               dri2dpy->configs[i].base.color_format);
511
         /* simple depth match for now */
512
         if (depth == nconf_depth ||
513
             (depth == 24 && depth + 8 == nconf_depth)) {
514
            nconf = &dri2dpy->configs[i].base;
515
            break;
516
         }
517
      }
518
 
519
      if (!nconf)
520
         return NULL;
521
   }
522
 
523
   dri2surf = dri2_display_create_surface(ndpy,
524
         (Drawable) pix, nconf->color_format);
525
   return (dri2surf) ? &dri2surf->base : NULL;
526
}
527
 
528
static int
529
choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
530
{
531
   int count = 0;
532
 
533
   switch (mode->rgbBits) {
534
   case 32:
535
      formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
536
      formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
537
      break;
538
   case 24:
539
      formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM;
540
      formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM;
541
      formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM;
542
      formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM;
543
      break;
544
   case 16:
545
      formats[count++] = PIPE_FORMAT_B5G6R5_UNORM;
546
      break;
547
   default:
548
      break;
549
   }
550
 
551
   return count;
552
}
553
 
554
static boolean
555
is_format_supported(struct pipe_screen *screen,
556
                    enum pipe_format fmt, unsigned sample_count, boolean is_color)
557
{
558
   return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, sample_count,
559
         (is_color) ? PIPE_BIND_RENDER_TARGET :
560
         PIPE_BIND_DEPTH_STENCIL);
561
}
562
 
563
static boolean
564
dri2_display_convert_config(struct native_display *ndpy,
565
                            const __GLcontextModes *mode,
566
                            struct native_config *nconf)
567
{
568
   enum pipe_format formats[32];
569
   int num_formats, i;
570
   int sample_count = 0;
571
 
572
   if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode)
573
      return FALSE;
574
 
575
   /* only interested in native renderable configs */
576
   if (!mode->xRenderable || !mode->drawableType)
577
      return FALSE;
578
 
579
   /* fast/slow configs are probably not relevant */
580
   if (mode->visualRating == GLX_SLOW_CONFIG)
581
      return FALSE;
582
 
583
   nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT;
584
   if (mode->doubleBufferMode)
585
      nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT;
586
   if (mode->stereoMode) {
587
      nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT;
588
      if (mode->doubleBufferMode)
589
         nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_RIGHT;
590
   }
591
 
592
   /* choose color format */
593
   num_formats = choose_color_format(mode, formats);
594
   for (i = 0; i < num_formats; i++) {
595
      if (is_format_supported(ndpy->screen, formats[i], sample_count, TRUE)) {
596
         nconf->color_format = formats[i];
597
         break;
598
      }
599
   }
600
   if (nconf->color_format == PIPE_FORMAT_NONE)
601
      return FALSE;
602
 
603
   if ((mode->drawableType & GLX_WINDOW_BIT) && mode->visualID)
604
      nconf->window_bit = TRUE;
605
   if (mode->drawableType & GLX_PIXMAP_BIT)
606
      nconf->pixmap_bit = TRUE;
607
 
608
   nconf->native_visual_id = mode->visualID;
609
   switch (mode->visualType) {
610
   case GLX_TRUE_COLOR:
611
      nconf->native_visual_type = TrueColor;
612
      break;
613
   case GLX_DIRECT_COLOR:
614
      nconf->native_visual_type = DirectColor;
615
      break;
616
   case GLX_PSEUDO_COLOR:
617
      nconf->native_visual_type = PseudoColor;
618
      break;
619
   case GLX_STATIC_COLOR:
620
      nconf->native_visual_type = StaticColor;
621
      break;
622
   case GLX_GRAY_SCALE:
623
      nconf->native_visual_type = GrayScale;
624
      break;
625
   case GLX_STATIC_GRAY:
626
      nconf->native_visual_type = StaticGray;
627
      break;
628
   }
629
   nconf->level = mode->level;
630
 
631
   if (mode->transparentPixel == GLX_TRANSPARENT_RGB) {
632
      nconf->transparent_rgb = TRUE;
633
      nconf->transparent_rgb_values[0] = mode->transparentRed;
634
      nconf->transparent_rgb_values[1] = mode->transparentGreen;
635
      nconf->transparent_rgb_values[2] = mode->transparentBlue;
636
   }
637
 
638
   return TRUE;
639
}
640
 
641
static const struct native_config **
642
dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
643
{
644
   struct dri2_display *dri2dpy = dri2_display(ndpy);
645
   const struct native_config **configs;
646
   int i;
647
 
648
   /* first time */
649
   if (!dri2dpy->configs) {
650
      const __GLcontextModes *modes;
651
      int num_modes, count;
652
 
653
      modes = x11_screen_get_glx_configs(dri2dpy->xscr);
654
      if (!modes)
655
         return NULL;
656
      num_modes = x11_context_modes_count(modes);
657
 
658
      dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs));
659
      if (!dri2dpy->configs)
660
         return NULL;
661
 
662
      count = 0;
663
      for (i = 0; i < num_modes; i++) {
664
         struct native_config *nconf = &dri2dpy->configs[count].base;
665
 
666
         if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) {
667
            int j;
668
            /* look for duplicates */
669
            for (j = 0; j < count; j++) {
670
               if (memcmp(&dri2dpy->configs[j], nconf, sizeof(*nconf)) == 0)
671
                  break;
672
            }
673
            if (j == count)
674
               count++;
675
         }
676
         modes = modes->next;
677
      }
678
 
679
      dri2dpy->num_configs = count;
680
   }
681
 
682
   configs = MALLOC(dri2dpy->num_configs * sizeof(*configs));
683
   if (configs) {
684
      for (i = 0; i < dri2dpy->num_configs; i++)
685
         configs[i] = (const struct native_config *) &dri2dpy->configs[i];
686
      if (num_configs)
687
         *num_configs = dri2dpy->num_configs;
688
   }
689
 
690
   return configs;
691
}
692
 
693
static boolean
694
dri2_display_get_pixmap_format(struct native_display *ndpy,
695
                               EGLNativePixmapType pix,
696
                               enum pipe_format *format)
697
{
698
   struct dri2_display *dri2dpy = dri2_display(ndpy);
699
   boolean ret = EGL_TRUE;
700
   uint depth;
701
 
702
   depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
703
   switch (depth) {
704
   case 32:
705
   case 24:
706
      *format = PIPE_FORMAT_B8G8R8A8_UNORM;
707
      break;
708
   case 16:
709
      *format = PIPE_FORMAT_B5G6R5_UNORM;
710
      break;
711
   default:
712
      *format = PIPE_FORMAT_NONE;
713
      ret = EGL_FALSE;
714
      break;
715
   }
716
 
717
   return ret;
718
}
719
 
720
static int
721
dri2_display_get_param(struct native_display *ndpy,
722
                       enum native_param_type param)
723
{
724
   int val;
725
 
726
   switch (param) {
727
   case NATIVE_PARAM_USE_NATIVE_BUFFER:
728
      /* DRI2GetBuffers uses the native buffers */
729
      val = TRUE;
730
      break;
731
   case NATIVE_PARAM_PRESERVE_BUFFER:
732
      /* DRI2CopyRegion is used */
733
      val = TRUE;
734
      break;
735
   case NATIVE_PARAM_PRESENT_REGION:
736
      val = TRUE;
737
      break;
738
   case NATIVE_PARAM_MAX_SWAP_INTERVAL:
739
   default:
740
      val = 0;
741
      break;
742
   }
743
 
744
   return val;
745
}
746
 
747
static void
748
dri2_display_destroy(struct native_display *ndpy)
749
{
750
   struct dri2_display *dri2dpy = dri2_display(ndpy);
751
 
752
   FREE(dri2dpy->configs);
753
 
754
   if (dri2dpy->base.screen)
755
      dri2dpy->base.screen->destroy(dri2dpy->base.screen);
756
 
757
   if (dri2dpy->surfaces)
758
      util_hash_table_destroy(dri2dpy->surfaces);
759
 
760
   if (dri2dpy->xscr)
761
      x11_screen_destroy(dri2dpy->xscr);
762
   if (dri2dpy->own_dpy)
763
      XCloseDisplay(dri2dpy->dpy);
764
   FREE(dri2dpy);
765
}
766
 
767
static void
768
dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable,
769
                                void *user_data)
770
{
771
   struct native_display *ndpy = (struct native_display* ) user_data;
772
   struct dri2_display *dri2dpy = dri2_display(ndpy);
773
   struct native_surface *nsurf;
774
   struct dri2_surface *dri2surf;
775
 
776
   nsurf = (struct native_surface *)
777
      util_hash_table_get(dri2dpy->surfaces, (void *) drawable);
778
   if (!nsurf)
779
      return;
780
 
781
   dri2surf = dri2_surface(nsurf);
782
 
783
   dri2surf->server_stamp++;
784
   dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
785
         &dri2surf->base, dri2surf->server_stamp);
786
}
787
 
788
/**
789
 * Initialize DRI2 and pipe screen.
790
 */
791
static boolean
792
dri2_display_init_screen(struct native_display *ndpy)
793
{
794
   struct dri2_display *dri2dpy = dri2_display(ndpy);
795
   int fd;
796
 
797
   if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
798
       !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) {
799
      _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported");
800
      return FALSE;
801
   }
802
 
803
   dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr,
804
         &dri2dpy->dri_major, &dri2dpy->dri_minor);
805
 
806
   fd = x11_screen_enable_dri2(dri2dpy->xscr,
807
         dri2_display_invalidate_buffers, &dri2dpy->base);
808
   if (fd < 0)
809
      return FALSE;
810
 
811
   dri2dpy->base.screen =
812
      dri2dpy->event_handler->new_drm_screen(&dri2dpy->base,
813
            dri2dpy->dri_driver, fd);
814
   if (!dri2dpy->base.screen) {
815
      _eglLog(_EGL_DEBUG, "failed to create DRM screen");
816
      return FALSE;
817
   }
818
 
819
   return TRUE;
820
}
821
 
822
static unsigned
823
dri2_display_hash_table_hash(void *key)
824
{
825
   XID drawable = pointer_to_uintptr(key);
826
   return (unsigned) drawable;
827
}
828
 
829
static int
830
dri2_display_hash_table_compare(void *key1, void *key2)
831
{
832
   return ((char *) key1 - (char *) key2);
833
}
834
 
835
#ifdef HAVE_WAYLAND_BACKEND
836
 
837
static int
838
dri2_display_authenticate(void *user_data, uint32_t magic)
839
{
840
   struct native_display *ndpy = user_data;
841
   struct dri2_display *dri2dpy = dri2_display(ndpy);
842
 
843
   return x11_screen_authenticate(dri2dpy->xscr, magic);
844
}
845
 
846
static struct wayland_drm_callbacks wl_drm_callbacks = {
847
   dri2_display_authenticate,
848
   egl_g3d_wl_drm_helper_reference_buffer,
849
   egl_g3d_wl_drm_helper_unreference_buffer
850
};
851
 
852
static boolean
853
dri2_display_bind_wayland_display(struct native_display *ndpy,
854
                                  struct wl_display *wl_dpy)
855
{
856
   struct dri2_display *dri2dpy = dri2_display(ndpy);
857
 
858
   if (dri2dpy->wl_server_drm)
859
      return FALSE;
860
 
4401 Serge 861
   ndpy->wl_server_drm = wayland_drm_init(wl_dpy,
4358 Serge 862
         x11_screen_get_device_name(dri2dpy->xscr),
863
         &wl_drm_callbacks, ndpy, 0);
864
 
865
   if (!dri2dpy->wl_server_drm)
866
      return FALSE;
867
 
868
   return TRUE;
869
}
870
 
871
static boolean
872
dri2_display_unbind_wayland_display(struct native_display *ndpy,
873
                                    struct wl_display *wl_dpy)
874
{
875
   struct dri2_display *dri2dpy = dri2_display(ndpy);
876
 
877
   if (!dri2dpy->wl_server_drm)
878
      return FALSE;
879
 
880
   wayland_drm_uninit(dri2dpy->wl_server_drm);
881
   dri2dpy->wl_server_drm = NULL;
882
 
883
   return TRUE;
884
}
885
 
886
static struct native_display_wayland_bufmgr dri2_display_wayland_bufmgr = {
887
   dri2_display_bind_wayland_display,
888
   dri2_display_unbind_wayland_display,
889
   egl_g3d_wl_drm_common_wl_buffer_get_resource,
890
   egl_g3d_wl_drm_common_query_buffer
891
};
892
 
893
#endif /* HAVE_WAYLAND_BACKEND */
894
 
895
struct native_display *
896
x11_create_dri2_display(Display *dpy,
897
                        const struct native_event_handler *event_handler)
898
{
899
   struct dri2_display *dri2dpy;
900
 
901
   dri2dpy = CALLOC_STRUCT(dri2_display);
902
   if (!dri2dpy)
903
      return NULL;
904
 
905
   dri2dpy->event_handler = event_handler;
906
 
907
   dri2dpy->dpy = dpy;
908
   if (!dri2dpy->dpy) {
909
      dri2dpy->dpy = XOpenDisplay(NULL);
910
      if (!dri2dpy->dpy) {
911
         dri2_display_destroy(&dri2dpy->base);
912
         return NULL;
913
      }
914
      dri2dpy->own_dpy = TRUE;
915
   }
916
 
917
   dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy);
918
   dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number);
919
   if (!dri2dpy->xscr) {
920
      dri2_display_destroy(&dri2dpy->base);
921
      return NULL;
922
   }
923
 
924
   dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash,
925
         dri2_display_hash_table_compare);
926
   if (!dri2dpy->surfaces) {
927
      dri2_display_destroy(&dri2dpy->base);
928
      return NULL;
929
   }
930
 
931
   dri2dpy->base.init_screen = dri2_display_init_screen;
932
   dri2dpy->base.destroy = dri2_display_destroy;
933
   dri2dpy->base.get_param = dri2_display_get_param;
934
   dri2dpy->base.get_configs = dri2_display_get_configs;
935
   dri2dpy->base.get_pixmap_format = dri2_display_get_pixmap_format;
936
   dri2dpy->base.copy_to_pixmap = native_display_copy_to_pixmap;
937
   dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
938
   dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface;
939
#ifdef HAVE_WAYLAND_BACKEND
940
   dri2dpy->base.wayland_bufmgr = &dri2_display_wayland_bufmgr;
941
#endif
942
 
943
   return &dri2dpy->base;
944
}
945
 
946
#else /* GLX_DIRECT_RENDERING */
947
 
948
struct native_display *
949
x11_create_dri2_display(Display *dpy,
950
                        const struct native_event_handler *event_handler)
951
{
952
   return NULL;
953
}
954
 
955
#endif /* GLX_DIRECT_RENDERING */