Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4358 Serge 1
/*
2
 * 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
 
46
int sna_bitmap_from_handle(bitmap_t *bitmap, uint32_t handle);
47
void sna_set_bo_handle(bitmap_t *bitmap, int handle);
48
int sna_blit_tex(bitmap_t *bitmap, int scale, int dst_x, int dst_y,
49
                  int w, int h, int src_x, int src_y);
50
 
51
static struct gbm_bo *
52
lock_front_buffer(struct gbm_surface *_surf)
53
{
54
   struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
55
   struct dri2_egl_surface *dri2_surf = surf->dri_private;
56
   struct gbm_bo *bo;
57
 
58
   if (dri2_surf->current == NULL) {
59
      _eglError(EGL_BAD_SURFACE, "no front buffer");
60
      return NULL;
61
   }
62
 
63
   bo = dri2_surf->current->bo;
64
   dri2_surf->current->locked = 1;
65
   dri2_surf->current = NULL;
66
 
67
   return bo;
68
}
69
 
70
static void
71
release_buffer(struct gbm_surface *_surf, struct gbm_bo *bo)
72
{
73
   struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
74
   struct dri2_egl_surface *dri2_surf = surf->dri_private;
75
   int i;
76
 
77
   for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
78
      if (dri2_surf->color_buffers[i].bo == bo) {
79
	 dri2_surf->color_buffers[i].locked = 0;
80
      }
81
   }
82
}
83
 
84
static int
85
has_free_buffers(struct gbm_surface *_surf)
86
{
87
   struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
88
   struct dri2_egl_surface *dri2_surf = surf->dri_private;
89
   int i;
90
 
91
   for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
92
      if (!dri2_surf->color_buffers[i].locked)
93
	 return 1;
94
 
95
   return 0;
96
}
97
 
98
static _EGLSurface *
99
dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
100
		    _EGLConfig *conf, EGLNativeWindowType window,
101
		    const EGLint *attrib_list)
102
{
103
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
104
   struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
105
   struct dri2_egl_surface *dri2_surf;
106
   struct gbm_dri_surface *surf;
107
 
108
   (void) drv;
109
 
110
   dri2_surf = calloc(1, sizeof *dri2_surf);
111
   if (!dri2_surf) {
112
      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
113
      return NULL;
114
   }
115
 
116
   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
117
      goto cleanup_surf;
118
 
119
   switch (type) {
120
   case EGL_WINDOW_BIT:
121
      if (!window)
122
         return NULL;
123
      surf = gbm_dri_surface((struct gbm_surface *) window);
124
      dri2_surf->gbm_surf = surf;
125
      dri2_surf->base.Width =  surf->base.width;
126
      dri2_surf->base.Height = surf->base.height;
127
      surf->dri_private = dri2_surf;
128
      break;
129
   default:
130
      goto cleanup_surf;
131
   }
132
 
133
   dri2_surf->dri_drawable =
134
      (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
135
					    dri2_conf->dri_double_config,
136
					    dri2_surf->gbm_surf);
137
 
138
   if (dri2_surf->dri_drawable == NULL) {
139
      _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
140
      goto cleanup_surf;
141
   }
142
 
143
   return &dri2_surf->base;
144
 
145
 cleanup_surf:
146
   free(dri2_surf);
147
 
148
   return NULL;
149
}
150
 
151
static _EGLSurface *
152
dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
153
			   _EGLConfig *conf, EGLNativeWindowType window,
154
			   const EGLint *attrib_list)
155
{
156
   return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
157
			      window, attrib_list);
158
}
159
 
160
static EGLBoolean
161
dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
162
{
163
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
164
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
165
   int i;
166
 
167
   if (!_eglPutSurface(surf))
168
      return EGL_TRUE;
169
 
170
   (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
171
 
172
   for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
173
      if (dri2_surf->color_buffers[i].bo)
174
	 gbm_bo_destroy(dri2_surf->color_buffers[i].bo);
175
   }
176
 
177
   for (i = 0; i < __DRI_BUFFER_COUNT; i++) {
178
      if (dri2_surf->dri_buffers[i])
179
         dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
180
                                       dri2_surf->dri_buffers[i]);
181
   }
182
 
183
   free(surf);
184
 
185
   return EGL_TRUE;
186
}
187
 
188
static int
189
get_back_bo(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
190
{
191
   struct dri2_egl_display *dri2_dpy =
192
      dri2_egl_display(dri2_surf->base.Resource.Display);
193
   struct gbm_dri_bo *bo;
194
   struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
195
   int i, name, pitch;
196
 
197
   if (dri2_surf->back == NULL)
198
   {
199
      for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
200
      {
201
        if(dri2_surf->color_buffers[i].locked)
202
        {
203
            dri2_surf->color_buffers[i].locked = 0;
204
            continue;
205
        }
206
        dri2_surf->back = &dri2_surf->color_buffers[i];
207
      }
208
   }
209
 
210
    if (dri2_surf->back == NULL)
211
        return -1;
212
    if (dri2_surf->back->bo == NULL)
213
        dri2_surf->back->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base.base,
214
					  surf->base.width, surf->base.height,
215
					  surf->base.format, surf->base.flags);
216
    if (dri2_surf->back->bo == NULL)
217
        return -1;
218
 
219
    bo = (struct gbm_dri_bo *) dri2_surf->back->bo;
220
 
221
    dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_NAME, &name);
222
    dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
223
 
224
    buffer->attachment = __DRI_BUFFER_BACK_LEFT;
225
    buffer->name = name;
226
    buffer->pitch = pitch;
227
    buffer->cpp = 4;
228
    buffer->flags = 0;
229
 
230
    dri2_surf->back->locked = 1;
231
 
232
    return 0;
233
}
234
 
235
static int
236
get_aux_bo(struct dri2_egl_surface *dri2_surf,
237
	   unsigned int attachment, unsigned int format, __DRIbuffer *buffer)
238
{
239
   struct dri2_egl_display *dri2_dpy =
240
      dri2_egl_display(dri2_surf->base.Resource.Display);
241
   __DRIbuffer *b = dri2_surf->dri_buffers[attachment];
242
 
243
   if (b == NULL) {
244
      b = dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
245
					 attachment, format,
246
					 dri2_surf->base.Width,
247
					 dri2_surf->base.Height);
248
      dri2_surf->dri_buffers[attachment] = b;
249
   }
250
   if (b == NULL)
251
      return -1;
252
 
253
   memcpy(buffer, b, sizeof *buffer);
254
 
255
   return 0;
256
}
257
 
258
static __DRIbuffer *
259
dri2_get_buffers_with_format(__DRIdrawable *driDrawable,
260
			     int *width, int *height,
261
			     unsigned int *attachments, int count,
262
			     int *out_count, void *loaderPrivate)
263
{
264
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
265
   int i, j;
266
 
267
//   printf("dri2_get_buffers_with_format count %d\n", count);
268
 
269
   dri2_surf->buffer_count = 0;
270
   for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
271
      assert(attachments[i] < __DRI_BUFFER_COUNT);
272
      assert(dri2_surf->buffer_count < 5);
273
 
274
//      printf("attachments %d\n",attachments[i]);
275
 
276
      switch (attachments[i]) {
277
      case __DRI_BUFFER_BACK_LEFT:
278
        if (get_back_bo(dri2_surf, &dri2_surf->buffers[j]) < 0) {
279
            _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
280
            return NULL;
281
        }
282
        break;
283
      default:
284
        if (get_aux_bo(dri2_surf, attachments[i], attachments[i + 1],
285
			&dri2_surf->buffers[j]) < 0) {
286
            _eglError(EGL_BAD_ALLOC, "failed to allocate aux buffer");
287
            return NULL;
288
        }
289
        break;
290
      }
291
   }
292
 
293
   *out_count = j;
294
   if (j == 0)
295
      return NULL;
296
 
297
   *width = dri2_surf->base.Width;
298
   *height = dri2_surf->base.Height;
299
 
300
   return dri2_surf->buffers;
301
}
302
 
303
static __DRIbuffer *
304
dri2_get_buffers(__DRIdrawable * driDrawable,
305
		 int *width, int *height,
306
		 unsigned int *attachments, int count,
307
		 int *out_count, void *loaderPrivate)
308
{
309
   unsigned int *attachments_with_format;
310
   __DRIbuffer *buffer;
311
   const unsigned int format = 32;
312
   int i;
313
 
314
   attachments_with_format = calloc(count * 2, sizeof(unsigned int));
315
   if (!attachments_with_format) {
316
      *out_count = 0;
317
      return NULL;
318
   }
319
 
320
   for (i = 0; i < count; ++i) {
321
      attachments_with_format[2*i] = attachments[i];
322
      attachments_with_format[2*i + 1] = format;
323
   }
324
 
325
   buffer =
326
      dri2_get_buffers_with_format(driDrawable,
327
				   width, height,
328
				   attachments_with_format, count,
329
				   out_count, loaderPrivate);
330
 
331
   free(attachments_with_format);
332
 
333
   return buffer;
334
}
335
 
336
static void
337
dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
338
{
339
   (void) driDrawable;
340
   (void) loaderPrivate;
341
}
342
 
343
static EGLBoolean
344
dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
345
{
346
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
347
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
348
   __DRIbuffer buffer;
349
   static bitmap_t bm;
350
 
351
   int i;
352
 
353
   if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
354
      if (dri2_surf->current)
355
        _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers");
356
      for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
357
         if (dri2_surf->color_buffers[i].age > 0)
358
            dri2_surf->color_buffers[i].age++;
359
 
360
#if 1
361
 
362
      if ( (dri2_surf->back != NULL) &&
363
           (dri2_surf->back->bo != NULL))
364
      {
365
        struct gbm_dri_bo *bo;
366
        bo = (struct gbm_dri_bo *)dri2_surf->back->bo;
367
 
368
        if(bm.width == 0)
369
        {
370
//            printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n",
371
//                __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width,
372
 //                             bo->base.base.height, (int)bo->base.base.stride,
373
//                              bo->base.base.format);
374
 
375
            bm.width      = bo->base.base.width;
376
            bm.height     = bo->base.base.height;
377
            bm.pitch      = (int)bo->base.base.stride;
378
            bm.max_width  = bo->base.base.width;
379
            bm.max_height = bo->base.base.height;
380
            bm.flags      = HW_TEX_BLIT;
381
 
382
            if( sna_bitmap_from_handle(&bm, bo->base.base.handle.s32))
383
            {
384
                printf("sna_bitmap_from_handle failed\n");
385
            }
386
        }
387
        if( bm.handle != 0)
388
        {
389
//           printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n",
390
//                __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width,
391
//                              bo->base.base.height, (int)bo->base.base.stride,
392
//                              bo->base.base.format);
393
 
394
            sna_set_bo_handle(&bm, bo->base.base.handle.s32);
395
            sna_blit_tex(&bm, 0, 5, 20, bm.width, bm.height, 0, 0);
396
        }
397
      }
398
#endif
399
 
400
      dri2_surf->current = dri2_surf->back;
401
      dri2_surf->current->age = 1;
402
      dri2_surf->back = NULL;
403
   }
404
 
405
   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
406
   (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
407
 
408
   return EGL_TRUE;
409
}
410
 
411
static EGLint
412
dri2_query_buffer_age(_EGLDriver *drv,
413
                      _EGLDisplay *disp, _EGLSurface *surface)
414
{
415
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
416
   __DRIbuffer buffer;
417
 
418
   if (get_back_bo(dri2_surf, &buffer) < 0) {
419
      _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
420
      return 0;
421
   }
422
 
423
   return dri2_surf->back->age;
424
}
425
 
426
static _EGLImage *
427
dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
428
			     EGLClientBuffer buffer, const EGLint *attr_list)
429
{
430
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
431
   struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *) buffer);
432
   struct dri2_egl_image *dri2_img;
433
 
434
   dri2_img = malloc(sizeof *dri2_img);
435
   if (!dri2_img) {
436
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
437
      return NULL;
438
   }
439
 
440
   if (!_eglInitImage(&dri2_img->base, disp)) {
441
      free(dri2_img);
442
      return NULL;
443
   }
444
 
445
   dri2_img->dri_image = dri2_dpy->image->dupImage(dri_bo->image, dri2_img);
446
   if (dri2_img->dri_image == NULL) {
447
      free(dri2_img);
448
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
449
      return NULL;
450
   }
451
 
452
   return &dri2_img->base;
453
}
454
 
455
static _EGLImage *
456
dri2_drm_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
457
                          _EGLContext *ctx, EGLenum target,
458
                          EGLClientBuffer buffer, const EGLint *attr_list)
459
{
460
   (void) drv;
461
 
462
   switch (target) {
463
   case EGL_NATIVE_PIXMAP_KHR:
464
      return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
465
   default:
466
      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
467
   }
468
}
469
 
470
#if 0
471
static int
472
dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
473
{
474
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
475
 
476
   return drmAuthMagic(dri2_dpy->fd, id);
477
}
478
#endif
479
 
480
EGLBoolean
481
dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
482
{
483
   struct dri2_egl_display *dri2_dpy;
484
   struct gbm_device *gbm;
485
   int fd = -1;
486
   int i;
487
 
488
   dri2_dpy = calloc(1, sizeof *dri2_dpy);
489
   if (!dri2_dpy)
490
      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
491
 
492
   disp->DriverData = (void *) dri2_dpy;
493
 
494
   gbm = disp->PlatformDisplay;
495
   if (gbm == NULL) {
496
      fd = get_service("DISPLAY");
497
      dri2_dpy->own_device = 1;
498
      gbm = gbm_create_device(fd);
499
      if (gbm == NULL)
500
         return EGL_FALSE;
501
   }
502
 
503
   if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) {
504
      free(dri2_dpy);
505
      return EGL_FALSE;
506
   }
507
 
508
   dri2_dpy->gbm_dri = gbm_dri_device(gbm);
509
   if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) {
510
      free(dri2_dpy);
511
      return EGL_FALSE;
512
   }
513
 
514
   dri2_dpy->fd = fd;
515
   dri2_dpy->device_name = strdup("drm device"); //dri2_get_device_name_for_fd(dri2_dpy->fd);
516
   dri2_dpy->driver_name = dri2_dpy->gbm_dri->base.driver_name;
517
 
518
   dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen;
519
   dri2_dpy->core = dri2_dpy->gbm_dri->core;
520
   dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2;
521
   dri2_dpy->image = dri2_dpy->gbm_dri->image;
522
   dri2_dpy->flush = dri2_dpy->gbm_dri->flush;
523
   dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs;
524
 
525
   dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image;
526
   dri2_dpy->gbm_dri->lookup_user_data = disp;
527
 
528
   dri2_dpy->gbm_dri->get_buffers = dri2_get_buffers;
529
   dri2_dpy->gbm_dri->flush_front_buffer = dri2_flush_front_buffer;
530
   dri2_dpy->gbm_dri->get_buffers_with_format = dri2_get_buffers_with_format;
531
 
532
   dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer;
533
   dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer;
534
   dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers;
535
 
536
   dri2_setup_screen(disp);
537
 
538
   for (i = 0; dri2_dpy->driver_configs[i]; i++)
539
      dri2_add_config(disp, dri2_dpy->driver_configs[i],
540
                      i + 1, 0, EGL_WINDOW_BIT, NULL, NULL);
541
 
542
   drv->API.CreateWindowSurface = dri2_create_window_surface;
543
   drv->API.DestroySurface = dri2_destroy_surface;
544
   drv->API.SwapBuffers = dri2_swap_buffers;
545
   drv->API.CreateImageKHR = dri2_drm_create_image_khr;
546
   drv->API.QueryBufferAge = dri2_query_buffer_age;
547
 
548
   disp->Extensions.EXT_buffer_age = EGL_TRUE;
549
 
550
#ifdef HAVE_WAYLAND_PLATFORM
551
   disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
552
#endif
553
//   dri2_dpy->authenticate = dri2_drm_authenticate;
554
 
555
   /* we're supporting EGL 1.4 */
556
   disp->VersionMajor = 1;
557
   disp->VersionMinor = 4;
558
 
559
   return EGL_TRUE;
560
}