Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Copyright © 2011 Intel Corporation
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
23
 *
24
 * Authors:
25
 *    Kristian Høgsberg 
26
 */
27
 
28
#include 
29
#include 
30
#include 
31
#include 
32
//#include 
33
#include 
34
#include 
35
#include 
36
#include 
37
#include 
38
#include 
39
 
40
#define EGL_EGLEXT_PROTOTYPES
41
#include 
42
#include 
43
 
44
#include "egl_dri2.h"
45
 
4373 Serge 46
void* load_library(const char *name);
47
void *get_proc_address(void *module, char *proc_name);
48
 
49
int (*blit_bitmap_from_handle)(bitmap_t *bitmap, uint32_t handle);
50
void (*blit_set_bo_handle)(bitmap_t *bitmap, int handle);
4378 Serge 51
int (*blit_blit_tex)(bitmap_t *bitmap, int scale, int vsync, int dst_x, int dst_y,
4358 Serge 52
                  int w, int h, int src_x, int src_y);
53
 
54
static struct gbm_bo *
55
lock_front_buffer(struct gbm_surface *_surf)
56
{
57
   struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
58
   struct dri2_egl_surface *dri2_surf = surf->dri_private;
59
   struct gbm_bo *bo;
60
 
61
   if (dri2_surf->current == NULL) {
62
      _eglError(EGL_BAD_SURFACE, "no front buffer");
63
      return NULL;
64
   }
65
 
66
   bo = dri2_surf->current->bo;
67
   dri2_surf->current->locked = 1;
68
   dri2_surf->current = NULL;
69
 
70
   return bo;
71
}
72
 
73
static void
74
release_buffer(struct gbm_surface *_surf, struct gbm_bo *bo)
75
{
76
   struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
77
   struct dri2_egl_surface *dri2_surf = surf->dri_private;
78
   int i;
79
 
80
   for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
81
      if (dri2_surf->color_buffers[i].bo == bo) {
82
	 dri2_surf->color_buffers[i].locked = 0;
83
      }
84
   }
85
}
86
 
87
static int
88
has_free_buffers(struct gbm_surface *_surf)
89
{
90
   struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
91
   struct dri2_egl_surface *dri2_surf = surf->dri_private;
92
   int i;
93
 
94
   for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
95
      if (!dri2_surf->color_buffers[i].locked)
96
	 return 1;
97
 
98
   return 0;
99
}
100
 
101
static _EGLSurface *
102
dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
103
		    _EGLConfig *conf, EGLNativeWindowType window,
104
		    const EGLint *attrib_list)
105
{
106
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
107
   struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
108
   struct dri2_egl_surface *dri2_surf;
109
   struct gbm_dri_surface *surf;
110
 
111
   (void) drv;
112
 
113
   dri2_surf = calloc(1, sizeof *dri2_surf);
114
   if (!dri2_surf) {
115
      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
116
      return NULL;
117
   }
118
 
119
   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
120
      goto cleanup_surf;
121
 
122
   switch (type) {
123
   case EGL_WINDOW_BIT:
124
      if (!window)
125
         return NULL;
126
      surf = gbm_dri_surface((struct gbm_surface *) window);
127
      dri2_surf->gbm_surf = surf;
128
      dri2_surf->base.Width =  surf->base.width;
129
      dri2_surf->base.Height = surf->base.height;
130
      surf->dri_private = dri2_surf;
131
      break;
132
   default:
133
      goto cleanup_surf;
134
   }
135
 
136
   dri2_surf->dri_drawable =
137
      (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
138
					    dri2_conf->dri_double_config,
139
					    dri2_surf->gbm_surf);
140
 
141
   if (dri2_surf->dri_drawable == NULL) {
142
      _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
143
      goto cleanup_surf;
144
   }
145
 
146
   return &dri2_surf->base;
147
 
148
 cleanup_surf:
149
   free(dri2_surf);
150
 
151
   return NULL;
152
}
153
 
154
static _EGLSurface *
155
dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
156
			   _EGLConfig *conf, EGLNativeWindowType window,
157
			   const EGLint *attrib_list)
158
{
159
   return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
160
			      window, attrib_list);
161
}
162
 
163
static EGLBoolean
164
dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
165
{
166
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
167
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
168
   int i;
169
 
170
   if (!_eglPutSurface(surf))
171
      return EGL_TRUE;
172
 
173
   (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
174
 
175
   for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
176
      if (dri2_surf->color_buffers[i].bo)
177
	 gbm_bo_destroy(dri2_surf->color_buffers[i].bo);
178
   }
179
 
180
   for (i = 0; i < __DRI_BUFFER_COUNT; i++) {
181
      if (dri2_surf->dri_buffers[i])
182
         dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
183
                                       dri2_surf->dri_buffers[i]);
184
   }
185
 
186
   free(surf);
187
 
188
   return EGL_TRUE;
189
}
190
 
191
static int
192
get_back_bo(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
193
{
194
   struct dri2_egl_display *dri2_dpy =
195
      dri2_egl_display(dri2_surf->base.Resource.Display);
196
   struct gbm_dri_bo *bo;
197
   struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
198
   int i, name, pitch;
199
 
200
   if (dri2_surf->back == NULL)
201
   {
202
      for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
203
      {
204
        if(dri2_surf->color_buffers[i].locked)
205
        {
206
            dri2_surf->color_buffers[i].locked = 0;
207
            continue;
208
        }
209
        dri2_surf->back = &dri2_surf->color_buffers[i];
210
      }
211
   }
212
 
213
    if (dri2_surf->back == NULL)
214
        return -1;
215
    if (dri2_surf->back->bo == NULL)
216
        dri2_surf->back->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base.base,
217
					  surf->base.width, surf->base.height,
218
					  surf->base.format, surf->base.flags);
219
    if (dri2_surf->back->bo == NULL)
220
        return -1;
221
 
222
    bo = (struct gbm_dri_bo *) dri2_surf->back->bo;
223
 
224
    dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_NAME, &name);
225
    dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
226
 
227
    buffer->attachment = __DRI_BUFFER_BACK_LEFT;
228
    buffer->name = name;
229
    buffer->pitch = pitch;
230
    buffer->cpp = 4;
231
    buffer->flags = 0;
232
 
233
    dri2_surf->back->locked = 1;
234
 
235
    return 0;
236
}
237
 
238
static int
239
get_aux_bo(struct dri2_egl_surface *dri2_surf,
240
	   unsigned int attachment, unsigned int format, __DRIbuffer *buffer)
241
{
242
   struct dri2_egl_display *dri2_dpy =
243
      dri2_egl_display(dri2_surf->base.Resource.Display);
244
   __DRIbuffer *b = dri2_surf->dri_buffers[attachment];
245
 
246
   if (b == NULL) {
247
      b = dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
248
					 attachment, format,
249
					 dri2_surf->base.Width,
250
					 dri2_surf->base.Height);
251
      dri2_surf->dri_buffers[attachment] = b;
252
   }
253
   if (b == NULL)
254
      return -1;
255
 
256
   memcpy(buffer, b, sizeof *buffer);
257
 
258
   return 0;
259
}
260
 
261
static __DRIbuffer *
262
dri2_get_buffers_with_format(__DRIdrawable *driDrawable,
263
			     int *width, int *height,
264
			     unsigned int *attachments, int count,
265
			     int *out_count, void *loaderPrivate)
266
{
267
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
268
   int i, j;
269
 
270
//   printf("dri2_get_buffers_with_format count %d\n", count);
271
 
272
   dri2_surf->buffer_count = 0;
273
   for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
274
      assert(attachments[i] < __DRI_BUFFER_COUNT);
275
      assert(dri2_surf->buffer_count < 5);
276
 
277
//      printf("attachments %d\n",attachments[i]);
278
 
279
      switch (attachments[i]) {
280
      case __DRI_BUFFER_BACK_LEFT:
281
        if (get_back_bo(dri2_surf, &dri2_surf->buffers[j]) < 0) {
282
            _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
283
            return NULL;
284
        }
285
        break;
286
      default:
287
        if (get_aux_bo(dri2_surf, attachments[i], attachments[i + 1],
288
			&dri2_surf->buffers[j]) < 0) {
289
            _eglError(EGL_BAD_ALLOC, "failed to allocate aux buffer");
290
            return NULL;
291
        }
292
        break;
293
      }
294
   }
295
 
296
   *out_count = j;
297
   if (j == 0)
298
      return NULL;
299
 
300
   *width = dri2_surf->base.Width;
301
   *height = dri2_surf->base.Height;
302
 
303
   return dri2_surf->buffers;
304
}
305
 
306
static __DRIbuffer *
307
dri2_get_buffers(__DRIdrawable * driDrawable,
308
		 int *width, int *height,
309
		 unsigned int *attachments, int count,
310
		 int *out_count, void *loaderPrivate)
311
{
312
   unsigned int *attachments_with_format;
313
   __DRIbuffer *buffer;
314
   const unsigned int format = 32;
315
   int i;
316
 
317
   attachments_with_format = calloc(count * 2, sizeof(unsigned int));
318
   if (!attachments_with_format) {
319
      *out_count = 0;
320
      return NULL;
321
   }
322
 
323
   for (i = 0; i < count; ++i) {
324
      attachments_with_format[2*i] = attachments[i];
325
      attachments_with_format[2*i + 1] = format;
326
   }
327
 
328
   buffer =
329
      dri2_get_buffers_with_format(driDrawable,
330
				   width, height,
331
				   attachments_with_format, count,
332
				   out_count, loaderPrivate);
333
 
334
   free(attachments_with_format);
335
 
336
   return buffer;
337
}
338
 
339
static void
340
dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
341
{
342
   (void) driDrawable;
343
   (void) loaderPrivate;
344
}
345
 
346
static EGLBoolean
347
dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
348
{
349
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
350
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
351
   __DRIbuffer buffer;
352
   static bitmap_t bm;
353
 
354
   int i;
355
 
356
   if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
357
      if (dri2_surf->current)
358
        _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers");
359
      for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
360
         if (dri2_surf->color_buffers[i].age > 0)
361
            dri2_surf->color_buffers[i].age++;
362
 
363
#if 1
364
 
365
      if ( (dri2_surf->back != NULL) &&
366
           (dri2_surf->back->bo != NULL))
367
      {
368
        struct gbm_dri_bo *bo;
369
        bo = (struct gbm_dri_bo *)dri2_surf->back->bo;
370
 
371
        if(bm.width == 0)
372
        {
373
//            printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n",
374
//                __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width,
375
 //                             bo->base.base.height, (int)bo->base.base.stride,
376
//                              bo->base.base.format);
377
 
378
            bm.width      = bo->base.base.width;
379
            bm.height     = bo->base.base.height;
380
            bm.pitch      = (int)bo->base.base.stride;
381
            bm.max_width  = bo->base.base.width;
382
            bm.max_height = bo->base.base.height;
383
            bm.flags      = HW_TEX_BLIT;
384
 
4373 Serge 385
            if( blit_bitmap_from_handle(&bm, bo->base.base.handle.s32))
4358 Serge 386
            {
387
                printf("sna_bitmap_from_handle failed\n");
388
            }
389
        }
390
        if( bm.handle != 0)
391
        {
392
//           printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n",
393
//                __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width,
394
//                              bo->base.base.height, (int)bo->base.base.stride,
395
//                              bo->base.base.format);
396
 
4373 Serge 397
            blit_set_bo_handle(&bm, bo->base.base.handle.s32);
4378 Serge 398
            blit_blit_tex(&bm, 0, 0, 5, 20, bm.width, bm.height, 0, 0);
4358 Serge 399
        }
400
      }
401
#endif
402
 
403
      dri2_surf->current = dri2_surf->back;
404
      dri2_surf->current->age = 1;
405
      dri2_surf->back = NULL;
406
   }
407
 
408
   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
409
   (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
410
 
411
   return EGL_TRUE;
412
}
413
 
414
static EGLint
415
dri2_query_buffer_age(_EGLDriver *drv,
416
                      _EGLDisplay *disp, _EGLSurface *surface)
417
{
418
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
419
   __DRIbuffer buffer;
420
 
421
   if (get_back_bo(dri2_surf, &buffer) < 0) {
422
      _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
423
      return 0;
424
   }
425
 
426
   return dri2_surf->back->age;
427
}
428
 
429
static _EGLImage *
430
dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
431
			     EGLClientBuffer buffer, const EGLint *attr_list)
432
{
433
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
434
   struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *) buffer);
435
   struct dri2_egl_image *dri2_img;
436
 
437
   dri2_img = malloc(sizeof *dri2_img);
438
   if (!dri2_img) {
439
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
440
      return NULL;
441
   }
442
 
443
   if (!_eglInitImage(&dri2_img->base, disp)) {
444
      free(dri2_img);
445
      return NULL;
446
   }
447
 
448
   dri2_img->dri_image = dri2_dpy->image->dupImage(dri_bo->image, dri2_img);
449
   if (dri2_img->dri_image == NULL) {
450
      free(dri2_img);
451
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
452
      return NULL;
453
   }
454
 
455
   return &dri2_img->base;
456
}
457
 
458
static _EGLImage *
459
dri2_drm_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
460
                          _EGLContext *ctx, EGLenum target,
461
                          EGLClientBuffer buffer, const EGLint *attr_list)
462
{
463
   (void) drv;
464
 
465
   switch (target) {
466
   case EGL_NATIVE_PIXMAP_KHR:
467
      return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
468
   default:
469
      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
470
   }
471
}
472
 
473
#if 0
474
static int
475
dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
476
{
477
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
478
 
479
   return drmAuthMagic(dri2_dpy->fd, id);
480
}
481
#endif
482
 
483
EGLBoolean
484
dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
485
{
486
   struct dri2_egl_display *dri2_dpy;
487
   struct gbm_device *gbm;
4373 Serge 488
   void *lib;
489
 
4358 Serge 490
   int fd = -1;
491
   int i;
492
 
493
   dri2_dpy = calloc(1, sizeof *dri2_dpy);
494
   if (!dri2_dpy)
495
      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
496
 
497
   disp->DriverData = (void *) dri2_dpy;
498
 
499
   gbm = disp->PlatformDisplay;
500
   if (gbm == NULL) {
501
      fd = get_service("DISPLAY");
502
      dri2_dpy->own_device = 1;
503
      gbm = gbm_create_device(fd);
504
      if (gbm == NULL)
505
         return EGL_FALSE;
506
   }
507
 
508
   if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) {
509
      free(dri2_dpy);
510
      return EGL_FALSE;
511
   }
512
 
513
   dri2_dpy->gbm_dri = gbm_dri_device(gbm);
514
   if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) {
515
      free(dri2_dpy);
516
      return EGL_FALSE;
517
   }
518
 
4373 Serge 519
 
520
   lib = load_library("intel-sna.drv");
521
   if(lib)
522
   {
523
       blit_bitmap_from_handle = get_proc_address(lib,"sna_bitmap_from_handle");
524
       blit_set_bo_handle = get_proc_address(lib,"sna_set_bo_handle");
525
       blit_blit_tex = get_proc_address(lib,"sna_blit_tex");
526
   }
527
   else
528
   {
529
       lib = load_library("intel-uxa.drv");
530
       if(lib)
531
       {
532
           blit_bitmap_from_handle = get_proc_address(lib,"uxa_bitmap_from_handle");
533
           blit_set_bo_handle = get_proc_address(lib,"uxa_set_bo_handle");
534
           blit_blit_tex = get_proc_address(lib,"uxa_blit_tex");
535
       }
536
       else return EGL_FALSE;
537
   }
538
 
4358 Serge 539
   dri2_dpy->fd = fd;
540
   dri2_dpy->device_name = strdup("drm device"); //dri2_get_device_name_for_fd(dri2_dpy->fd);
541
   dri2_dpy->driver_name = dri2_dpy->gbm_dri->base.driver_name;
542
 
543
   dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen;
544
   dri2_dpy->core = dri2_dpy->gbm_dri->core;
545
   dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2;
546
   dri2_dpy->image = dri2_dpy->gbm_dri->image;
547
   dri2_dpy->flush = dri2_dpy->gbm_dri->flush;
548
   dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs;
549
 
550
   dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image;
551
   dri2_dpy->gbm_dri->lookup_user_data = disp;
552
 
553
   dri2_dpy->gbm_dri->get_buffers = dri2_get_buffers;
554
   dri2_dpy->gbm_dri->flush_front_buffer = dri2_flush_front_buffer;
555
   dri2_dpy->gbm_dri->get_buffers_with_format = dri2_get_buffers_with_format;
556
 
557
   dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer;
558
   dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer;
559
   dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers;
560
 
561
   dri2_setup_screen(disp);
562
 
563
   for (i = 0; dri2_dpy->driver_configs[i]; i++)
564
      dri2_add_config(disp, dri2_dpy->driver_configs[i],
565
                      i + 1, 0, EGL_WINDOW_BIT, NULL, NULL);
566
 
567
   drv->API.CreateWindowSurface = dri2_create_window_surface;
568
   drv->API.DestroySurface = dri2_destroy_surface;
569
   drv->API.SwapBuffers = dri2_swap_buffers;
570
   drv->API.CreateImageKHR = dri2_drm_create_image_khr;
571
   drv->API.QueryBufferAge = dri2_query_buffer_age;
572
 
573
   disp->Extensions.EXT_buffer_age = EGL_TRUE;
574
 
575
#ifdef HAVE_WAYLAND_PLATFORM
576
   disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
577
#endif
578
//   dri2_dpy->authenticate = dri2_drm_authenticate;
579
 
580
   /* we're supporting EGL 1.4 */
581
   disp->VersionMajor = 1;
582
   disp->VersionMinor = 4;
583
 
584
   return EGL_TRUE;
585
}