Subversion Repositories Kolibri OS

Rev

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-2011 Chia-I Wu 
5
 * Copyright (C) 2010-2011 LunarG Inc.
6
 *
7
 * Based on platform_x11, which has
8
 *
9
 * Copyright © 2011 Intel Corporation
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a
12
 * copy of this software and associated documentation files (the "Software"),
13
 * to deal in the Software without restriction, including without limitation
14
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
 * and/or sell copies of the Software, and to permit persons to whom the
16
 * Software is furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included
19
 * in all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
 * DEALINGS IN THE SOFTWARE.
28
 */
29
 
30
#include 
31
#include 
32
 
33
#if ANDROID_VERSION >= 0x402
34
#include 
35
#endif
36
 
37
/* for droid_get_pci_id */
38
#include 
39
#include 
40
#include 
41
 
42
#include "egl_dri2.h"
43
#include "gralloc_drm.h"
44
 
45
static int
46
get_format_bpp(int native)
47
{
48
   int bpp;
49
 
50
   switch (native) {
51
   case HAL_PIXEL_FORMAT_RGBA_8888:
52
   case HAL_PIXEL_FORMAT_RGBX_8888:
53
   case HAL_PIXEL_FORMAT_BGRA_8888:
54
      bpp = 4;
55
      break;
56
   case HAL_PIXEL_FORMAT_RGB_888:
57
      bpp = 3;
58
      break;
59
   case HAL_PIXEL_FORMAT_RGB_565:
60
   case HAL_PIXEL_FORMAT_RGBA_5551:
61
   case HAL_PIXEL_FORMAT_RGBA_4444:
62
      bpp = 2;
63
      break;
64
   default:
65
      bpp = 0;
66
      break;
67
   }
68
 
69
   return bpp;
70
}
71
 
72
static int
73
get_native_buffer_name(struct ANativeWindowBuffer *buf)
74
{
75
   return gralloc_drm_get_gem_handle(buf->handle);
76
}
77
 
78
static EGLBoolean
79
droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf)
80
{
81
#if ANDROID_VERSION >= 0x0402
82
   int fence_fd;
83
 
84
   if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer,
85
                                        &fence_fd))
86
      return EGL_FALSE;
87
 
88
   /* If access to the buffer is controlled by a sync fence, then block on the
89
    * fence.
90
    *
91
    * It may be more performant to postpone blocking until there is an
92
    * immediate need to write to the buffer. But doing so would require adding
93
    * hooks to the DRI2 loader.
94
    *
95
    * From the ANativeWindow::dequeueBuffer documentation:
96
    *
97
    *    The libsync fence file descriptor returned in the int pointed to by
98
    *    the fenceFd argument will refer to the fence that must signal
99
    *    before the dequeued buffer may be written to.  A value of -1
100
    *    indicates that the caller may access the buffer immediately without
101
    *    waiting on a fence.  If a valid file descriptor is returned (i.e.
102
    *    any value except -1) then the caller is responsible for closing the
103
    *    file descriptor.
104
    */
105
    if (fence_fd >= 0) {
106
       /* From the SYNC_IOC_WAIT documentation in :
107
        *
108
        *    Waits indefinitely if timeout < 0.
109
        */
110
        int timeout = -1;
111
        sync_wait(fence_fd, timeout);
112
        close(fence_fd);
113
   }
114
 
115
   dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common);
116
#else
117
   if (dri2_surf->window->dequeueBuffer(dri2_surf->window, &dri2_surf->buffer))
118
      return EGL_FALSE;
119
 
120
   dri2_surf->buffer->common.incRef(&dri2_surf->buffer->common);
121
   dri2_surf->window->lockBuffer(dri2_surf->window, dri2_surf->buffer);
122
#endif
123
 
124
   return EGL_TRUE;
125
}
126
 
127
static EGLBoolean
128
droid_window_enqueue_buffer(struct dri2_egl_surface *dri2_surf)
129
{
130
#if ANDROID_VERSION >= 0x0402
131
   /* Queue the buffer without a sync fence. This informs the ANativeWindow
132
    * that it may access the buffer immediately.
133
    *
134
    * From ANativeWindow::dequeueBuffer:
135
    *
136
    *    The fenceFd argument specifies a libsync fence file descriptor for
137
    *    a fence that must signal before the buffer can be accessed.  If
138
    *    the buffer can be accessed immediately then a value of -1 should
139
    *    be used.  The caller must not use the file descriptor after it
140
    *    is passed to queueBuffer, and the ANativeWindow implementation
141
    *    is responsible for closing it.
142
    */
143
   int fence_fd = -1;
144
   dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer,
145
                                  fence_fd);
146
#else
147
   dri2_surf->window->queueBuffer(dri2_surf->window, dri2_surf->buffer);
148
#endif
149
 
150
   dri2_surf->buffer->common.decRef(&dri2_surf->buffer->common);
151
   dri2_surf->buffer = NULL;
152
 
153
   return EGL_TRUE;
154
}
155
 
156
static void
157
droid_window_cancel_buffer(struct dri2_egl_surface *dri2_surf)
158
{
159
   /* no cancel buffer? */
160
   droid_window_enqueue_buffer(dri2_surf);
161
}
162
 
163
static __DRIbuffer *
164
droid_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
165
                         unsigned int att, unsigned int format)
166
{
167
   struct dri2_egl_display *dri2_dpy =
168
      dri2_egl_display(dri2_surf->base.Resource.Display);
169
 
170
   if (att >= ARRAY_SIZE(dri2_surf->local_buffers))
171
      return NULL;
172
 
173
   if (!dri2_surf->local_buffers[att]) {
174
      dri2_surf->local_buffers[att] =
175
         dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format,
176
               dri2_surf->base.Width, dri2_surf->base.Height);
177
   }
178
 
179
   return dri2_surf->local_buffers[att];
180
}
181
 
182
static void
183
droid_free_local_buffers(struct dri2_egl_surface *dri2_surf)
184
{
185
   struct dri2_egl_display *dri2_dpy =
186
      dri2_egl_display(dri2_surf->base.Resource.Display);
187
   int i;
188
 
189
   for (i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) {
190
      if (dri2_surf->local_buffers[i]) {
191
         dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
192
               dri2_surf->local_buffers[i]);
193
         dri2_surf->local_buffers[i] = NULL;
194
      }
195
   }
196
}
197
 
198
static _EGLSurface *
199
droid_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
200
		    _EGLConfig *conf, EGLNativeWindowType window,
201
		    const EGLint *attrib_list)
202
{
203
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
204
   struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
205
   struct dri2_egl_surface *dri2_surf;
206
   dri2_surf = calloc(1, sizeof *dri2_surf);
207
   if (!dri2_surf) {
208
      _eglError(EGL_BAD_ALLOC, "droid_create_surface");
209
      return NULL;
210
   }
211
 
212
   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
213
      goto cleanup_surface;
214
 
215
   if (type == EGL_WINDOW_BIT) {
216
      int format;
217
 
218
      if (!window || window->common.magic != ANDROID_NATIVE_WINDOW_MAGIC) {
219
         _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
220
         goto cleanup_surface;
221
      }
222
      if (window->query(window, NATIVE_WINDOW_FORMAT, &format)) {
223
         _eglError(EGL_BAD_NATIVE_WINDOW, "droid_create_surface");
224
         goto cleanup_surface;
225
      }
226
 
227
      if (format != dri2_conf->base.NativeVisualID) {
228
         _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x",
229
               format, dri2_conf->base.NativeVisualID);
230
      }
231
 
232
      window->query(window, NATIVE_WINDOW_WIDTH, &dri2_surf->base.Width);
233
      window->query(window, NATIVE_WINDOW_HEIGHT, &dri2_surf->base.Height);
234
   }
235
 
236
   dri2_surf->dri_drawable =
237
      (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen,
238
					   dri2_conf->dri_double_config,
239
                                           dri2_surf);
240
   if (dri2_surf->dri_drawable == NULL) {
241
      _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
242
      goto cleanup_surface;
243
   }
244
 
245
   if (window) {
246
      window->common.incRef(&window->common);
247
      dri2_surf->window = window;
248
   }
249
 
250
   return &dri2_surf->base;
251
 
252
cleanup_surface:
253
   free(dri2_surf);
254
 
255
   return NULL;
256
}
257
 
258
static _EGLSurface *
259
droid_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
260
			   _EGLConfig *conf, EGLNativeWindowType window,
261
			   const EGLint *attrib_list)
262
{
263
   return droid_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
264
			      window, attrib_list);
265
}
266
 
267
static _EGLSurface *
268
droid_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
269
			   _EGLConfig *conf, EGLNativePixmapType pixmap,
270
			   const EGLint *attrib_list)
271
{
272
   return NULL;
273
}
274
 
275
static _EGLSurface *
276
droid_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
277
			    _EGLConfig *conf, const EGLint *attrib_list)
278
{
279
   return droid_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
280
			      NULL, attrib_list);
281
}
282
 
283
static EGLBoolean
284
droid_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
285
{
286
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
287
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
288
 
289
   if (!_eglPutSurface(surf))
290
      return EGL_TRUE;
291
 
292
   droid_free_local_buffers(dri2_surf);
293
 
294
   if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
295
      if (dri2_surf->buffer)
296
         droid_window_cancel_buffer(dri2_surf);
297
 
298
      dri2_surf->window->common.decRef(&dri2_surf->window->common);
299
   }
300
 
301
   (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
302
 
303
   free(dri2_surf);
304
 
305
   return EGL_TRUE;
306
}
307
 
308
static EGLBoolean
309
droid_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
310
{
311
   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
312
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
313
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
314
   _EGLContext *ctx;
315
 
316
   if (dri2_surf->base.Type != EGL_WINDOW_BIT)
317
      return EGL_TRUE;
318
 
319
   if (dri2_drv->glFlush) {
320
      ctx = _eglGetCurrentContext();
321
      if (ctx && ctx->DrawSurface == &dri2_surf->base)
322
         dri2_drv->glFlush();
323
   }
324
 
325
   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
326
 
327
   if (dri2_surf->buffer)
328
      droid_window_enqueue_buffer(dri2_surf);
329
 
330
   (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
331
 
332
   return EGL_TRUE;
333
}
334
 
335
static _EGLImage *
336
dri2_create_image_android_native_buffer(_EGLDisplay *disp, _EGLContext *ctx,
337
                                        struct ANativeWindowBuffer *buf)
338
{
339
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
340
   struct dri2_egl_image *dri2_img;
341
   int name;
342
   EGLint format;
343
 
344
   if (ctx != NULL) {
345
      /* From the EGL_ANDROID_image_native_buffer spec:
346
       *
347
       *     * If  is EGL_NATIVE_BUFFER_ANDROID and  is not
348
       *       EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated.
349
       */
350
      _eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for "
351
                "EGL_NATIVE_BUFFER_ANDROID, the context must be "
352
                "EGL_NO_CONTEXT");
353
      return NULL;
354
   }
355
 
356
   if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC ||
357
       buf->common.version != sizeof(*buf)) {
358
      _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
359
      return NULL;
360
   }
361
 
362
   name = get_native_buffer_name(buf);
363
   if (!name) {
364
      _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
365
      return NULL;
366
   }
367
 
368
   /* see the table in droid_add_configs_for_visuals */
369
   switch (buf->format) {
370
   case HAL_PIXEL_FORMAT_BGRA_8888:
371
      format = __DRI_IMAGE_FORMAT_ARGB8888;
372
      break;
373
   case HAL_PIXEL_FORMAT_RGB_565:
374
      format = __DRI_IMAGE_FORMAT_RGB565;
375
      break;
376
   case HAL_PIXEL_FORMAT_RGBA_8888:
377
      format = __DRI_IMAGE_FORMAT_ABGR8888;
378
      break;
379
   case HAL_PIXEL_FORMAT_RGBX_8888:
380
      format = __DRI_IMAGE_FORMAT_XBGR8888;
381
      break;
382
   case HAL_PIXEL_FORMAT_RGB_888:
383
   case HAL_PIXEL_FORMAT_RGBA_5551:
384
   case HAL_PIXEL_FORMAT_RGBA_4444:
385
      /* unsupported */
386
   default:
387
      _eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", buf->format);
388
      return NULL;
389
      break;
390
   }
391
 
392
   dri2_img = calloc(1, sizeof(*dri2_img));
393
   if (!dri2_img) {
394
      _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
395
      return NULL;
396
   }
397
 
398
   if (!_eglInitImage(&dri2_img->base, disp)) {
399
      free(dri2_img);
400
      return NULL;
401
   }
402
 
403
   dri2_img->dri_image =
404
      dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
405
					   buf->width,
406
					   buf->height,
407
					   format,
408
					   name,
409
					   buf->stride,
410
					   dri2_img);
411
   if (!dri2_img->dri_image) {
412
      free(dri2_img);
413
      _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm");
414
      return NULL;
415
   }
416
 
417
   return &dri2_img->base;
418
}
419
 
420
static _EGLImage *
421
droid_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
422
		       _EGLContext *ctx, EGLenum target,
423
		       EGLClientBuffer buffer, const EGLint *attr_list)
424
{
425
   switch (target) {
426
   case EGL_NATIVE_BUFFER_ANDROID:
427
      return dri2_create_image_android_native_buffer(disp, ctx,
428
            (struct ANativeWindowBuffer *) buffer);
429
   default:
430
      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
431
   }
432
}
433
 
434
static void
435
droid_init_driver_functions(_EGLDriver *drv)
436
{
437
   drv->API.CreateWindowSurface = droid_create_window_surface;
438
   drv->API.CreatePixmapSurface = droid_create_pixmap_surface;
439
   drv->API.CreatePbufferSurface = droid_create_pbuffer_surface;
440
   drv->API.DestroySurface = droid_destroy_surface;
441
   drv->API.SwapBuffers = droid_swap_buffers;
442
 
443
   drv->API.CreateImageKHR = droid_create_image_khr;
444
}
445
 
446
static void
447
droid_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
448
{
449
}
450
 
451
static int
452
droid_get_buffers_parse_attachments(struct dri2_egl_surface *dri2_surf,
453
                                    unsigned int *attachments, int count)
454
{
455
   int num_buffers = 0, i;
456
 
457
   /* fill dri2_surf->buffers */
458
   for (i = 0; i < count * 2; i += 2) {
459
      __DRIbuffer *buf, *local;
460
 
461
      assert(num_buffers < ARRAY_SIZE(dri2_surf->buffers));
462
      buf = &dri2_surf->buffers[num_buffers];
463
 
464
      switch (attachments[i]) {
465
      case __DRI_BUFFER_BACK_LEFT:
466
         if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
467
            buf->attachment = attachments[i];
468
            buf->name = get_native_buffer_name(dri2_surf->buffer);
469
            buf->cpp = get_format_bpp(dri2_surf->buffer->format);
470
            buf->pitch = dri2_surf->buffer->stride * buf->cpp;
471
            buf->flags = 0;
472
 
473
            if (buf->name)
474
               num_buffers++;
475
 
476
            break;
477
         }
478
         /* fall through for pbuffers */
479
      case __DRI_BUFFER_DEPTH:
480
      case __DRI_BUFFER_STENCIL:
481
      case __DRI_BUFFER_ACCUM:
482
      case __DRI_BUFFER_DEPTH_STENCIL:
483
      case __DRI_BUFFER_HIZ:
484
         local = droid_alloc_local_buffer(dri2_surf,
485
               attachments[i], attachments[i + 1]);
486
 
487
         if (local) {
488
            *buf = *local;
489
            num_buffers++;
490
         }
491
         break;
492
      case __DRI_BUFFER_FRONT_LEFT:
493
      case __DRI_BUFFER_FRONT_RIGHT:
494
      case __DRI_BUFFER_FAKE_FRONT_LEFT:
495
      case __DRI_BUFFER_FAKE_FRONT_RIGHT:
496
      case __DRI_BUFFER_BACK_RIGHT:
497
      default:
498
         /* no front or right buffers */
499
         break;
500
      }
501
   }
502
 
503
   return num_buffers;
504
}
505
 
506
static __DRIbuffer *
507
droid_get_buffers_with_format(__DRIdrawable * driDrawable,
508
			     int *width, int *height,
509
			     unsigned int *attachments, int count,
510
			     int *out_count, void *loaderPrivate)
511
{
512
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
513
   struct dri2_egl_display *dri2_dpy =
514
      dri2_egl_display(dri2_surf->base.Resource.Display);
515
   int i;
516
 
517
   if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
518
      /* try to dequeue the next back buffer */
519
      if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf))
520
         return NULL;
521
 
522
      /* free outdated buffers and update the surface size */
523
      if (dri2_surf->base.Width != dri2_surf->buffer->width ||
524
          dri2_surf->base.Height != dri2_surf->buffer->height) {
525
         droid_free_local_buffers(dri2_surf);
526
         dri2_surf->base.Width = dri2_surf->buffer->width;
527
         dri2_surf->base.Height = dri2_surf->buffer->height;
528
      }
529
   }
530
 
531
   dri2_surf->buffer_count =
532
      droid_get_buffers_parse_attachments(dri2_surf, attachments, count);
533
 
534
   if (width)
535
      *width = dri2_surf->base.Width;
536
   if (height)
537
      *height = dri2_surf->base.Height;
538
 
539
   *out_count = dri2_surf->buffer_count;;
540
 
541
   return dri2_surf->buffers;
542
}
543
 
544
static EGLBoolean
545
droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy)
546
{
547
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
548
   const struct {
549
      int format;
550
      int size;
551
      unsigned int rgba_masks[4];
552
   } visuals[] = {
553
      { HAL_PIXEL_FORMAT_RGBA_8888, 32, { 0xff, 0xff00, 0xff0000, 0xff000000 } },
554
      { HAL_PIXEL_FORMAT_RGBX_8888, 32, { 0xff, 0xff00, 0xff0000, 0x0 } },
555
      { HAL_PIXEL_FORMAT_RGB_888,   24, { 0xff, 0xff00, 0xff0000, 0x0 } },
556
      { HAL_PIXEL_FORMAT_RGB_565,   16, { 0xf800, 0x7e0, 0x1f, 0x0 } },
557
      { HAL_PIXEL_FORMAT_BGRA_8888, 32, { 0xff0000, 0xff00, 0xff, 0xff000000 } },
558
      { 0, 0, { 0, 0, 0, 0 } }
559
   };
560
   int count, i, j;
561
 
562
   count = 0;
563
   for (i = 0; visuals[i].format; i++) {
564
      int format_count = 0;
565
 
566
      for (j = 0; dri2_dpy->driver_configs[j]; j++) {
567
         const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
568
         struct dri2_egl_config *dri2_conf;
569
         unsigned int double_buffered = 0;
570
 
571
         dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[j],
572
            __DRI_ATTRIB_DOUBLE_BUFFER, &double_buffered);
573
 
574
         /* support only double buffered configs */
575
         if (!double_buffered)
576
            continue;
577
 
578
         dri2_conf = dri2_add_config(dpy, dri2_dpy->driver_configs[j],
579
               count + 1, visuals[i].size, surface_type, NULL,
580
               visuals[i].rgba_masks);
581
         if (dri2_conf) {
582
            dri2_conf->base.NativeVisualID = visuals[i].format;
583
            dri2_conf->base.NativeVisualType = visuals[i].format;
584
            count++;
585
            format_count++;
586
         }
587
      }
588
 
589
      if (!format_count) {
590
         _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x",
591
               visuals[i].format);
592
      }
593
   }
594
 
595
   /* post-process configs */
596
   for (i = 0; i < dpy->Configs->Size; i++) {
597
      struct dri2_egl_config *dri2_conf = dri2_egl_config(dpy->Configs->Elements[i]);
598
 
599
      /* there is no front buffer so no OpenGL */
600
      dri2_conf->base.RenderableType &= ~EGL_OPENGL_BIT;
601
      dri2_conf->base.Conformant &= ~EGL_OPENGL_BIT;
602
   }
603
 
604
   return (count != 0);
605
}
606
 
607
static EGLBoolean
608
droid_get_pci_id(int fd, int *vendor_id, int *chip_id)
609
{
610
   drmVersionPtr version;
611
 
612
   *chip_id = -1;
613
 
614
   version = drmGetVersion(fd);
615
   if (!version) {
616
      _eglLog(_EGL_WARNING, "invalid drm fd");
617
      return EGL_FALSE;
618
   }
619
   if (!version->name) {
620
      _eglLog(_EGL_WARNING, "unable to determine the driver name");
621
      drmFreeVersion(version);
622
      return EGL_FALSE;
623
   }
624
 
625
   if (strcmp(version->name, "i915") == 0) {
626
      struct drm_i915_getparam gp;
627
      int ret;
628
 
629
      *vendor_id = 0x8086;
630
 
631
      memset(&gp, 0, sizeof(gp));
632
      gp.param = I915_PARAM_CHIPSET_ID;
633
      gp.value = chip_id;
634
      ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
635
      if (ret) {
636
         _eglLog(_EGL_WARNING, "failed to get param for i915");
637
	 *chip_id = -1;
638
      }
639
   }
640
   else if (strcmp(version->name, "radeon") == 0) {
641
      struct drm_radeon_info info;
642
      int ret;
643
 
644
      *vendor_id = 0x1002;
645
 
646
      memset(&info, 0, sizeof(info));
647
      info.request = RADEON_INFO_DEVICE_ID;
648
      info.value = (unsigned long) chip_id;
649
      ret = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
650
      if (ret) {
651
         _eglLog(_EGL_WARNING, "failed to get info for radeon");
652
	 *chip_id = -1;
653
      }
654
   }
655
   else if (strcmp(version->name, "nouveau") == 0) {
656
      *vendor_id = 0x10de;
657
      /* not used */
658
      *chip_id = 0;
659
   }
660
   else if (strcmp(version->name, "vmwgfx") == 0) {
661
      *vendor_id = 0x15ad;
662
      /* assume SVGA II */
663
      *chip_id = 0x0405;
664
   }
665
 
666
   drmFreeVersion(version);
667
 
668
   return (*chip_id >= 0);
669
}
670
 
671
#define DRIVER_MAP_DRI2_ONLY
672
#include "pci_ids/pci_id_driver_map.h"
673
static const char *
674
droid_get_driver_name(int fd)
675
{
676
   int vendor_id = -1, chip_id = -1;
677
   int idx, i;
678
   char *name;
679
 
680
   if (!droid_get_pci_id(fd, &vendor_id, &chip_id))
681
      return NULL;
682
 
683
   for (idx = 0; driver_map[idx].driver; idx++) {
684
      if (vendor_id != driver_map[idx].vendor_id)
685
         continue;
686
 
687
      if (driver_map[idx].num_chips_ids == -1)
688
         break;
689
 
690
      for (i = 0; i < driver_map[idx].num_chips_ids; i++) {
691
         if (driver_map[idx].chip_ids[i] == chip_id)
692
            break;
693
      }
694
      if (i < driver_map[idx].num_chips_ids)
695
	      break;
696
   }
697
 
698
   _eglLog(_EGL_INFO, "pci id for fd %d: %04x:%04x, driver %s",
699
         fd, vendor_id, chip_id, driver_map[idx].driver);
700
 
701
   return driver_map[idx].driver;
702
}
703
 
704
static int
705
droid_open_device(void)
706
{
707
   const hw_module_t *mod;
708
   int fd = -1, err;
709
 
710
   err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod);
711
   if (!err) {
712
      const gralloc_module_t *gr = (gralloc_module_t *) mod;
713
 
714
      err = -EINVAL;
715
      if (gr->perform)
716
         err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd);
717
   }
718
   if (err || fd < 0) {
719
      _eglLog(_EGL_WARNING, "fail to get drm fd");
720
      fd = -1;
721
   }
722
 
723
   return (fd >= 0) ? dup(fd) : -1;
724
}
725
 
726
/* support versions < JellyBean */
727
#ifndef ALOGW
728
#define ALOGW LOGW
729
#endif
730
#ifndef ALOGD
731
#define ALOGD LOGD
732
#endif
733
#ifndef ALOGI
734
#define ALOGI LOGI
735
#endif
736
 
737
static void
738
droid_log(EGLint level, const char *msg)
739
{
740
   switch (level) {
741
   case _EGL_DEBUG:
742
      ALOGD("%s", msg);
743
      break;
744
   case _EGL_INFO:
745
      ALOGI("%s", msg);
746
      break;
747
   case _EGL_WARNING:
748
      ALOGW("%s", msg);
749
      break;
750
   case _EGL_FATAL:
751
      LOG_FATAL("%s", msg);
752
      break;
753
   default:
754
      break;
755
   }
756
}
757
 
758
EGLBoolean
759
dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy)
760
{
761
   struct dri2_egl_display *dri2_dpy;
762
   const char *err;
763
 
764
   _eglSetLogProc(droid_log);
765
 
766
   dri2_dpy = calloc(1, sizeof(*dri2_dpy));
767
   if (!dri2_dpy)
768
      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
769
 
770
   dpy->DriverData = (void *) dri2_dpy;
771
 
772
   dri2_dpy->fd = droid_open_device();
773
   if (dri2_dpy->fd < 0) {
774
      err = "DRI2: failed to open device";
775
      goto cleanup_display;
776
   }
777
 
778
   dri2_dpy->driver_name = (char *) droid_get_driver_name(dri2_dpy->fd);
779
   if (dri2_dpy->driver_name == NULL) {
780
      err = "DRI2: failed to get driver name";
781
      goto cleanup_device;
782
   }
783
 
784
   if (!dri2_load_driver(dpy)) {
785
      err = "DRI2: failed to load driver";
786
      goto cleanup_device;
787
   }
788
 
789
   dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
790
   dri2_dpy->dri2_loader_extension.base.version = 3;
791
   dri2_dpy->dri2_loader_extension.getBuffers = NULL;
792
   dri2_dpy->dri2_loader_extension.flushFrontBuffer = droid_flush_front_buffer;
793
   dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
794
      droid_get_buffers_with_format;
795
 
796
   dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base;
797
   dri2_dpy->extensions[1] = &image_lookup_extension.base;
798
   dri2_dpy->extensions[2] = &use_invalidate.base;
799
   dri2_dpy->extensions[3] = NULL;
800
 
801
   if (!dri2_create_screen(dpy)) {
802
      err = "DRI2: failed to create screen";
803
      goto cleanup_driver;
804
   }
805
 
806
   if (!droid_add_configs_for_visuals(drv, dpy)) {
807
      err = "DRI2: failed to add configs";
808
      goto cleanup_screen;
809
   }
810
 
811
   dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
812
   dpy->Extensions.KHR_image_base = EGL_TRUE;
813
 
814
   /* we're supporting EGL 1.4 */
815
   dpy->VersionMajor = 1;
816
   dpy->VersionMinor = 4;
817
 
818
   droid_init_driver_functions(drv);
819
 
820
   return EGL_TRUE;
821
 
822
cleanup_screen:
823
   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
824
cleanup_driver:
825
   dlclose(dri2_dpy->driver);
826
cleanup_device:
827
   close(dri2_dpy->fd);
828
cleanup_display:
829
   free(dri2_dpy);
830
 
831
   return _eglError(EGL_NOT_INITIALIZED, err);
832
}