Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4379 Serge 1
/*
4358 Serge 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
 
4401 Serge 49
int (*blit_bitmap_from_handle)(bitmap_t *bitmap, uint32_t handle);
50
void (*blit_set_bo_handle)(bitmap_t *bitmap, int handle);
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
   dri2_surf->buffer_count = 0;
271
   for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
272
      assert(attachments[i] < __DRI_BUFFER_COUNT);
273
      assert(dri2_surf->buffer_count < 5);
274
 
275
      switch (attachments[i]) {
276
      case __DRI_BUFFER_BACK_LEFT:
277
        if (get_back_bo(dri2_surf, &dri2_surf->buffers[j]) < 0) {
278
            _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
279
            return NULL;
280
        }
281
        break;
282
      default:
283
        if (get_aux_bo(dri2_surf, attachments[i], attachments[i + 1],
284
			&dri2_surf->buffers[j]) < 0) {
285
            _eglError(EGL_BAD_ALLOC, "failed to allocate aux buffer");
286
            return NULL;
287
        }
288
        break;
289
      }
290
   }
291
 
292
   *out_count = j;
293
   if (j == 0)
294
      return NULL;
295
 
296
   *width = dri2_surf->base.Width;
297
   *height = dri2_surf->base.Height;
298
 
299
   return dri2_surf->buffers;
300
}
301
 
302
static __DRIbuffer *
303
dri2_get_buffers(__DRIdrawable * driDrawable,
304
		 int *width, int *height,
305
		 unsigned int *attachments, int count,
306
		 int *out_count, void *loaderPrivate)
307
{
308
   unsigned int *attachments_with_format;
309
   __DRIbuffer *buffer;
310
   const unsigned int format = 32;
311
   int i;
312
 
313
   attachments_with_format = calloc(count * 2, sizeof(unsigned int));
314
   if (!attachments_with_format) {
315
      *out_count = 0;
316
      return NULL;
317
   }
318
 
319
   for (i = 0; i < count; ++i) {
320
      attachments_with_format[2*i] = attachments[i];
321
      attachments_with_format[2*i + 1] = format;
322
   }
323
 
324
   buffer =
325
      dri2_get_buffers_with_format(driDrawable,
326
				   width, height,
327
				   attachments_with_format, count,
328
				   out_count, loaderPrivate);
329
 
330
   free(attachments_with_format);
331
 
332
   return buffer;
333
}
334
 
335
static void
336
dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
337
{
338
   (void) driDrawable;
339
   (void) loaderPrivate;
340
}
341
 
342
static EGLBoolean
343
dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
344
{
345
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
346
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
347
   __DRIbuffer buffer;
348
   static bitmap_t bm;
349
 
350
   int i;
351
 
352
   if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
353
      if (dri2_surf->current)
354
        _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers");
355
      for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
356
         if (dri2_surf->color_buffers[i].age > 0)
357
            dri2_surf->color_buffers[i].age++;
358
 
359
#if 1
360
 
361
      if ( (dri2_surf->back != NULL) &&
362
           (dri2_surf->back->bo != NULL))
363
      {
364
        struct gbm_dri_bo *bo;
365
        bo = (struct gbm_dri_bo *)dri2_surf->back->bo;
366
 
367
        if(bm.width == 0)
368
        {
369
//            printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n",
370
//                __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width,
371
 //                             bo->base.base.height, (int)bo->base.base.stride,
372
//                              bo->base.base.format);
373
 
374
            bm.width      = bo->base.base.width;
375
            bm.height     = bo->base.base.height;
376
            bm.pitch      = (int)bo->base.base.stride;
377
            bm.max_width  = bo->base.base.width;
378
            bm.max_height = bo->base.base.height;
379
            bm.flags      = HW_TEX_BLIT;
380
 
4373 Serge 381
            if( blit_bitmap_from_handle(&bm, bo->base.base.handle.s32))
4358 Serge 382
            {
383
                printf("sna_bitmap_from_handle failed\n");
384
            }
385
        }
386
        if( bm.handle != 0)
387
        {
388
//           printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n",
389
//                __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width,
390
//                              bo->base.base.height, (int)bo->base.base.stride,
391
//                              bo->base.base.format);
392
 
4373 Serge 393
            blit_set_bo_handle(&bm, bo->base.base.handle.s32);
4378 Serge 394
            blit_blit_tex(&bm, 0, 0, 5, 20, bm.width, bm.height, 0, 0);
4358 Serge 395
        }
396
      }
397
#endif
398
 
399
      dri2_surf->current = dri2_surf->back;
400
      dri2_surf->current->age = 1;
401
      dri2_surf->back = NULL;
402
   }
403
 
404
   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
405
   (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
406
 
407
   return EGL_TRUE;
408
}
409
 
410
static EGLint
411
dri2_query_buffer_age(_EGLDriver *drv,
412
                      _EGLDisplay *disp, _EGLSurface *surface)
413
{
414
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
415
   __DRIbuffer buffer;
416
 
417
   if (get_back_bo(dri2_surf, &buffer) < 0) {
418
      _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
419
      return 0;
420
   }
421
 
422
   return dri2_surf->back->age;
423
}
424
 
425
static _EGLImage *
426
dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
427
			     EGLClientBuffer buffer, const EGLint *attr_list)
428
{
429
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
430
   struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *) buffer);
431
   struct dri2_egl_image *dri2_img;
432
 
433
   dri2_img = malloc(sizeof *dri2_img);
434
   if (!dri2_img) {
435
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
436
      return NULL;
437
   }
438
 
439
   if (!_eglInitImage(&dri2_img->base, disp)) {
440
      free(dri2_img);
441
      return NULL;
442
   }
443
 
444
   dri2_img->dri_image = dri2_dpy->image->dupImage(dri_bo->image, dri2_img);
445
   if (dri2_img->dri_image == NULL) {
446
      free(dri2_img);
447
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
448
      return NULL;
449
   }
450
 
451
   return &dri2_img->base;
452
}
453
 
454
static _EGLImage *
455
dri2_drm_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
456
                          _EGLContext *ctx, EGLenum target,
457
                          EGLClientBuffer buffer, const EGLint *attr_list)
458
{
459
   (void) drv;
460
 
461
   switch (target) {
462
   case EGL_NATIVE_PIXMAP_KHR:
463
      return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
464
   default:
465
      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
466
   }
467
}
468
 
469
#if 0
470
static int
471
dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
472
{
473
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
474
 
475
   return drmAuthMagic(dri2_dpy->fd, id);
476
}
477
#endif
478
 
479
EGLBoolean
480
dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
481
{
482
   struct dri2_egl_display *dri2_dpy;
483
   struct gbm_device *gbm;
4373 Serge 484
   void *lib;
485
 
4358 Serge 486
   int fd = -1;
487
   int i;
488
 
489
   dri2_dpy = calloc(1, sizeof *dri2_dpy);
490
   if (!dri2_dpy)
491
      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
492
 
493
   disp->DriverData = (void *) dri2_dpy;
494
 
495
   gbm = disp->PlatformDisplay;
496
   if (gbm == NULL) {
497
      fd = get_service("DISPLAY");
498
      dri2_dpy->own_device = 1;
499
      gbm = gbm_create_device(fd);
500
      if (gbm == NULL)
501
         return EGL_FALSE;
502
   }
503
 
504
   if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) {
505
      free(dri2_dpy);
506
      return EGL_FALSE;
507
   }
508
 
509
   dri2_dpy->gbm_dri = gbm_dri_device(gbm);
510
   if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) {
511
      free(dri2_dpy);
512
      return EGL_FALSE;
513
   }
514
 
4373 Serge 515
 
516
   lib = load_library("intel-sna.drv");
517
   if(lib)
518
   {
519
       blit_bitmap_from_handle = get_proc_address(lib,"sna_bitmap_from_handle");
520
       blit_set_bo_handle = get_proc_address(lib,"sna_set_bo_handle");
521
       blit_blit_tex = get_proc_address(lib,"sna_blit_tex");
522
   }
523
   else
524
   {
525
       lib = load_library("intel-uxa.drv");
526
       if(lib)
527
       {
528
           blit_bitmap_from_handle = get_proc_address(lib,"uxa_bitmap_from_handle");
529
           blit_set_bo_handle = get_proc_address(lib,"uxa_set_bo_handle");
530
           blit_blit_tex = get_proc_address(lib,"uxa_blit_tex");
531
       }
532
       else return EGL_FALSE;
533
   }
534
 
4358 Serge 535
   dri2_dpy->fd = fd;
536
   dri2_dpy->device_name = strdup("drm device"); //dri2_get_device_name_for_fd(dri2_dpy->fd);
537
   dri2_dpy->driver_name = dri2_dpy->gbm_dri->base.driver_name;
538
 
539
   dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen;
540
   dri2_dpy->core = dri2_dpy->gbm_dri->core;
541
   dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2;
542
   dri2_dpy->image = dri2_dpy->gbm_dri->image;
543
   dri2_dpy->flush = dri2_dpy->gbm_dri->flush;
544
   dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs;
545
 
546
   dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image;
547
   dri2_dpy->gbm_dri->lookup_user_data = disp;
548
 
549
   dri2_dpy->gbm_dri->get_buffers = dri2_get_buffers;
550
   dri2_dpy->gbm_dri->flush_front_buffer = dri2_flush_front_buffer;
551
   dri2_dpy->gbm_dri->get_buffers_with_format = dri2_get_buffers_with_format;
552
 
553
   dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer;
554
   dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer;
555
   dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers;
556
 
557
   dri2_setup_screen(disp);
558
 
559
   for (i = 0; dri2_dpy->driver_configs[i]; i++)
560
      dri2_add_config(disp, dri2_dpy->driver_configs[i],
561
                      i + 1, 0, EGL_WINDOW_BIT, NULL, NULL);
562
 
563
   drv->API.CreateWindowSurface = dri2_create_window_surface;
564
   drv->API.DestroySurface = dri2_destroy_surface;
565
   drv->API.SwapBuffers = dri2_swap_buffers;
566
   drv->API.CreateImageKHR = dri2_drm_create_image_khr;
567
   drv->API.QueryBufferAge = dri2_query_buffer_age;
568
 
569
   disp->Extensions.EXT_buffer_age = EGL_TRUE;
570
 
571
#ifdef HAVE_WAYLAND_PLATFORM
572
   disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
573
#endif
574
//   dri2_dpy->authenticate = dri2_drm_authenticate;
575
 
576
   /* we're supporting EGL 1.4 */
577
   disp->VersionMajor = 1;
578
   disp->VersionMinor = 4;
579
 
580
   return EGL_TRUE;
581
}