Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright 2009, VMware, Inc.
5
 * All Rights Reserved.
6
 * Copyright (C) 2010 LunarG Inc.
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a
9
 * copy of this software and associated documentation files (the "Software"),
10
 * to deal in the Software without restriction, including without limitation
11
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
 * and/or sell copies of the Software, and to permit persons to whom the
13
 * Software is furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included
16
 * in all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
 * OTHER DEALINGS IN THE SOFTWARE.
25
 *
26
 * Authors:
27
 *    Keith Whitwell  Jakob Bornecrantz
28
 *     Chia-I Wu 
29
 */
30
 
31
#include 
32
#include 
33
#include "util/u_memory.h"
34
#include "util/u_inlines.h"
35
#include "util/u_format.h"
36
#include "util/u_debug.h"
37
#include "state_tracker/drm_driver.h"
38
#include "state_tracker/st_texture.h"
39
#include "state_tracker/st_context.h"
40
#include "pipe-loader/pipe_loader.h"
41
#include "main/texobj.h"
42
 
43
#include "dri_screen.h"
44
#include "dri_context.h"
45
#include "dri_drawable.h"
46
#include "dri_query_renderer.h"
47
#include "dri2_buffer.h"
48
 
49
static int convert_fourcc(int format, int *dri_components_p)
50
{
51
   int dri_components;
52
   switch(format) {
53
   case __DRI_IMAGE_FOURCC_RGB565:
54
      format = __DRI_IMAGE_FORMAT_RGB565;
55
      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
56
      break;
57
   case __DRI_IMAGE_FOURCC_ARGB8888:
58
      format = __DRI_IMAGE_FORMAT_ARGB8888;
59
      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
60
      break;
61
   case __DRI_IMAGE_FOURCC_XRGB8888:
62
      format = __DRI_IMAGE_FORMAT_XRGB8888;
63
      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
64
      break;
65
   case __DRI_IMAGE_FOURCC_ABGR8888:
66
      format = __DRI_IMAGE_FORMAT_ABGR8888;
67
      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
68
      break;
69
   case __DRI_IMAGE_FOURCC_XBGR8888:
70
      format = __DRI_IMAGE_FORMAT_XBGR8888;
71
      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
72
      break;
73
   default:
74
      return -1;
75
   }
76
   *dri_components_p = dri_components;
77
   return format;
78
}
79
 
80
static int convert_to_fourcc(int format)
81
{
82
   switch(format) {
83
   case __DRI_IMAGE_FORMAT_RGB565:
84
      format = __DRI_IMAGE_FOURCC_RGB565;
85
      break;
86
   case __DRI_IMAGE_FORMAT_ARGB8888:
87
      format = __DRI_IMAGE_FOURCC_ARGB8888;
88
      break;
89
   case __DRI_IMAGE_FORMAT_XRGB8888:
90
      format = __DRI_IMAGE_FOURCC_XRGB8888;
91
      break;
92
   case __DRI_IMAGE_FORMAT_ABGR8888:
93
      format = __DRI_IMAGE_FOURCC_ABGR8888;
94
      break;
95
   case __DRI_IMAGE_FORMAT_XBGR8888:
96
      format = __DRI_IMAGE_FOURCC_XBGR8888;
97
      break;
98
   default:
99
      return -1;
100
   }
101
   return format;
102
}
103
 
104
/**
105
 * DRI2 flush extension.
106
 */
107
static void
108
dri2_flush_drawable(__DRIdrawable *dPriv)
109
{
110
   dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);
111
}
112
 
113
static void
114
dri2_invalidate_drawable(__DRIdrawable *dPriv)
115
{
116
   struct dri_drawable *drawable = dri_drawable(dPriv);
117
 
118
   dri2InvalidateDrawable(dPriv);
119
   drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
120
 
121
   p_atomic_inc(&drawable->base.stamp);
122
}
123
 
124
static const __DRI2flushExtension dri2FlushExtension = {
125
    .base = { __DRI2_FLUSH, 4 },
126
 
127
    .flush                = dri2_flush_drawable,
128
    .invalidate           = dri2_invalidate_drawable,
129
    .flush_with_flags     = dri_flush,
130
};
131
 
132
/**
133
 * Retrieve __DRIbuffer from the DRI loader.
134
 */
135
static __DRIbuffer *
136
dri2_drawable_get_buffers(struct dri_drawable *drawable,
137
                          const enum st_attachment_type *atts,
138
                          unsigned *count)
139
{
140
   __DRIdrawable *dri_drawable = drawable->dPriv;
141
   const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
142
   boolean with_format;
143
   __DRIbuffer *buffers;
144
   int num_buffers;
145
   unsigned attachments[10];
146
   unsigned num_attachments, i;
147
 
148
   assert(loader);
149
   with_format = dri_with_format(drawable->sPriv);
150
 
151
   num_attachments = 0;
152
 
153
   /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
154
   if (!with_format)
155
      attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
156
 
157
   for (i = 0; i < *count; i++) {
158
      enum pipe_format format;
159
      unsigned bind;
160
      int att, depth;
161
 
162
      dri_drawable_get_format(drawable, atts[i], &format, &bind);
163
      if (format == PIPE_FORMAT_NONE)
164
         continue;
165
 
166
      switch (atts[i]) {
167
      case ST_ATTACHMENT_FRONT_LEFT:
168
         /* already added */
169
         if (!with_format)
170
            continue;
171
         att = __DRI_BUFFER_FRONT_LEFT;
172
         break;
173
      case ST_ATTACHMENT_BACK_LEFT:
174
         att = __DRI_BUFFER_BACK_LEFT;
175
         break;
176
      case ST_ATTACHMENT_FRONT_RIGHT:
177
         att = __DRI_BUFFER_FRONT_RIGHT;
178
         break;
179
      case ST_ATTACHMENT_BACK_RIGHT:
180
         att = __DRI_BUFFER_BACK_RIGHT;
181
         break;
182
      default:
183
         continue;
184
      }
185
 
186
      /*
187
       * In this switch statement we must support all formats that
188
       * may occur as the stvis->color_format.
189
       */
190
      switch(format) {
191
      case PIPE_FORMAT_B8G8R8A8_UNORM:
192
	 depth = 32;
193
	 break;
194
      case PIPE_FORMAT_B8G8R8X8_UNORM:
195
	 depth = 24;
196
	 break;
197
      case PIPE_FORMAT_B5G6R5_UNORM:
198
	 depth = 16;
199
	 break;
200
      default:
201
	 depth = util_format_get_blocksizebits(format);
202
	 assert(!"Unexpected format in dri2_drawable_get_buffers()");
203
      }
204
 
205
      attachments[num_attachments++] = att;
206
      if (with_format) {
207
         attachments[num_attachments++] = depth;
208
      }
209
   }
210
 
211
   if (with_format) {
212
      num_attachments /= 2;
213
      buffers = loader->getBuffersWithFormat(dri_drawable,
214
            &dri_drawable->w, &dri_drawable->h,
215
            attachments, num_attachments,
216
            &num_buffers, dri_drawable->loaderPrivate);
217
   }
218
   else {
219
      buffers = loader->getBuffers(dri_drawable,
220
            &dri_drawable->w, &dri_drawable->h,
221
            attachments, num_attachments,
222
            &num_buffers, dri_drawable->loaderPrivate);
223
   }
224
 
225
   if (buffers)
226
      *count = num_buffers;
227
 
228
   return buffers;
229
}
230
 
231
static bool
232
dri_image_drawable_get_buffers(struct dri_drawable *drawable,
233
                               struct __DRIimageList *images,
234
                               const enum st_attachment_type *statts,
235
                               unsigned statts_count)
236
{
237
   __DRIdrawable *dPriv = drawable->dPriv;
238
   __DRIscreen *sPriv = drawable->sPriv;
239
   unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;
240
   enum pipe_format pf;
241
   uint32_t buffer_mask = 0;
242
   unsigned i, bind;
243
 
244
   for (i = 0; i < statts_count; i++) {
245
      dri_drawable_get_format(drawable, statts[i], &pf, &bind);
246
      if (pf == PIPE_FORMAT_NONE)
247
         continue;
248
 
249
      switch (statts[i]) {
250
      case ST_ATTACHMENT_FRONT_LEFT:
251
         buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
252
         break;
253
      case ST_ATTACHMENT_BACK_LEFT:
254
         buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
255
         break;
256
      default:
257
         continue;
258
      }
259
 
260
      switch (pf) {
261
      case PIPE_FORMAT_B5G6R5_UNORM:
262
         image_format = __DRI_IMAGE_FORMAT_RGB565;
263
         break;
264
      case PIPE_FORMAT_B8G8R8X8_UNORM:
265
         image_format = __DRI_IMAGE_FORMAT_XRGB8888;
266
         break;
267
      case PIPE_FORMAT_B8G8R8A8_UNORM:
268
         image_format = __DRI_IMAGE_FORMAT_ARGB8888;
269
         break;
270
      case PIPE_FORMAT_R8G8B8A8_UNORM:
271
         image_format = __DRI_IMAGE_FORMAT_ABGR8888;
272
         break;
273
      default:
274
         image_format = __DRI_IMAGE_FORMAT_NONE;
275
         break;
276
      }
277
   }
278
 
279
   return (*sPriv->image.loader->getBuffers) (dPriv, image_format,
280
                                       (uint32_t *) &drawable->base.stamp,
281
                                       dPriv->loaderPrivate, buffer_mask,
282
                                       images);
283
}
284
 
285
static __DRIbuffer *
286
dri2_allocate_buffer(__DRIscreen *sPriv,
287
                     unsigned attachment, unsigned format,
288
                     int width, int height)
289
{
290
   struct dri_screen *screen = dri_screen(sPriv);
291
   struct dri2_buffer *buffer;
292
   struct pipe_resource templ;
293
   enum pipe_format pf;
294
   unsigned bind = 0;
295
   struct winsys_handle whandle;
296
 
297
   switch (attachment) {
298
      case __DRI_BUFFER_FRONT_LEFT:
299
      case __DRI_BUFFER_FAKE_FRONT_LEFT:
300
         bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
301
         break;
302
      case __DRI_BUFFER_BACK_LEFT:
303
         bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
304
         break;
305
      case __DRI_BUFFER_DEPTH:
306
      case __DRI_BUFFER_DEPTH_STENCIL:
307
      case __DRI_BUFFER_STENCIL:
308
            bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
309
         break;
310
   }
311
 
312
   /* because we get the handle and stride */
313
   bind |= PIPE_BIND_SHARED;
314
 
315
   switch (format) {
316
      case 32:
317
         pf = PIPE_FORMAT_B8G8R8A8_UNORM;
318
         break;
319
      case 24:
320
         pf = PIPE_FORMAT_B8G8R8X8_UNORM;
321
         break;
322
      case 16:
323
         pf = PIPE_FORMAT_Z16_UNORM;
324
         break;
325
      default:
326
         return NULL;
327
   }
328
 
329
   buffer = CALLOC_STRUCT(dri2_buffer);
330
   if (!buffer)
331
      return NULL;
332
 
333
   memset(&templ, 0, sizeof(templ));
334
   templ.bind = bind;
335
   templ.format = pf;
336
   templ.target = PIPE_TEXTURE_2D;
337
   templ.last_level = 0;
338
   templ.width0 = width;
339
   templ.height0 = height;
340
   templ.depth0 = 1;
341
   templ.array_size = 1;
342
 
343
   buffer->resource =
344
      screen->base.screen->resource_create(screen->base.screen, &templ);
345
   if (!buffer->resource) {
346
      FREE(buffer);
347
      return NULL;
348
   }
349
 
350
   memset(&whandle, 0, sizeof(whandle));
351
   if (screen->can_share_buffer)
352
      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
353
   else
354
      whandle.type = DRM_API_HANDLE_TYPE_KMS;
355
 
356
   screen->base.screen->resource_get_handle(screen->base.screen,
357
         buffer->resource, &whandle);
358
 
359
   buffer->base.attachment = attachment;
360
   buffer->base.name = whandle.handle;
361
   buffer->base.cpp = util_format_get_blocksize(pf);
362
   buffer->base.pitch = whandle.stride;
363
 
364
   return &buffer->base;
365
}
366
 
367
static void
368
dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
369
{
370
   struct dri2_buffer *buffer = dri2_buffer(bPriv);
371
 
372
   pipe_resource_reference(&buffer->resource, NULL);
373
   FREE(buffer);
374
}
375
 
376
/*
377
 * Backend functions for st_framebuffer interface.
378
 */
379
 
380
static void
381
dri2_allocate_textures(struct dri_context *ctx,
382
                       struct dri_drawable *drawable,
383
                       const enum st_attachment_type *statts,
384
                       unsigned statts_count)
385
{
386
   __DRIscreen *sPriv = drawable->sPriv;
387
   __DRIdrawable *dri_drawable = drawable->dPriv;
388
   struct dri_screen *screen = dri_screen(sPriv);
389
   struct pipe_resource templ;
390
   boolean alloc_depthstencil = FALSE;
391
   unsigned i, j, bind;
392
   const __DRIimageLoaderExtension *image = sPriv->image.loader;
393
   /* Image specific variables */
394
   struct __DRIimageList images;
395
   /* Dri2 specific variables */
396
   __DRIbuffer *buffers = NULL;
397
   struct winsys_handle whandle;
398
   unsigned num_buffers = statts_count;
399
 
400
   /* First get the buffers from the loader */
401
   if (image) {
402
      if (!dri_image_drawable_get_buffers(drawable, &images,
403
                                          statts, statts_count))
404
         return;
405
   }
406
   else {
407
      buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
408
      if (!buffers || (drawable->old_num == num_buffers &&
409
                       drawable->old_w == dri_drawable->w &&
410
                       drawable->old_h == dri_drawable->h &&
411
                       memcmp(drawable->old, buffers,
412
                              sizeof(__DRIbuffer) * num_buffers) == 0))
413
         return;
414
   }
415
 
416
   /* Second clean useless resources*/
417
 
418
   /* See if we need a depth-stencil buffer. */
419
   for (i = 0; i < statts_count; i++) {
420
      if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
421
         alloc_depthstencil = TRUE;
422
         break;
423
      }
424
   }
425
 
426
   /* Delete the resources we won't need. */
427
   for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
428
      /* Don't delete the depth-stencil buffer, we can reuse it. */
429
      if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
430
         continue;
431
 
432
      /* Flush the texture before unreferencing, so that other clients can
433
       * see what the driver has rendered.
434
       */
435
      if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {
436
         struct pipe_context *pipe = ctx->st->pipe;
437
         pipe->flush_resource(pipe, drawable->textures[i]);
438
      }
439
 
440
      pipe_resource_reference(&drawable->textures[i], NULL);
441
   }
442
 
443
   if (drawable->stvis.samples > 1) {
444
      for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
445
         boolean del = TRUE;
446
 
447
         /* Don't delete MSAA resources for the attachments which are enabled,
448
          * we can reuse them. */
449
         for (j = 0; j < statts_count; j++) {
450
            if (i == statts[j]) {
451
               del = FALSE;
452
               break;
453
            }
454
         }
455
 
456
         if (del) {
457
            pipe_resource_reference(&drawable->msaa_textures[i], NULL);
458
         }
459
      }
460
   }
461
 
462
   /* Third use the buffers retrieved to fill the drawable info */
463
 
464
   memset(&templ, 0, sizeof(templ));
465
   templ.target = screen->target;
466
   templ.last_level = 0;
467
   templ.depth0 = 1;
468
   templ.array_size = 1;
469
 
470
   if (image) {
471
      if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
472
         struct pipe_resource **buf =
473
            &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
474
         struct pipe_resource *texture = images.front->texture;
475
 
476
         dri_drawable->w = texture->width0;
477
         dri_drawable->h = texture->height0;
478
 
479
         pipe_resource_reference(buf, texture);
480
      }
481
 
482
      if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
483
         struct pipe_resource **buf =
484
            &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
485
         struct pipe_resource *texture = images.back->texture;
486
 
487
         dri_drawable->w = texture->width0;
488
         dri_drawable->h = texture->height0;
489
 
490
         pipe_resource_reference(buf, texture);
491
      }
492
 
493
      /* Note: if there is both a back and a front buffer,
494
       * then they have the same size.
495
       */
496
      templ.width0 = dri_drawable->w;
497
      templ.height0 = dri_drawable->h;
498
   }
499
   else {
500
      memset(&whandle, 0, sizeof(whandle));
501
 
502
      /* Process DRI-provided buffers and get pipe_resources. */
503
      for (i = 0; i < num_buffers; i++) {
504
         __DRIbuffer *buf = &buffers[i];
505
         enum st_attachment_type statt;
506
         enum pipe_format format;
507
 
508
         switch (buf->attachment) {
509
         case __DRI_BUFFER_FRONT_LEFT:
510
            if (!screen->auto_fake_front) {
511
               continue; /* invalid attachment */
512
            }
513
            /* fallthrough */
514
         case __DRI_BUFFER_FAKE_FRONT_LEFT:
515
            statt = ST_ATTACHMENT_FRONT_LEFT;
516
            break;
517
         case __DRI_BUFFER_BACK_LEFT:
518
            statt = ST_ATTACHMENT_BACK_LEFT;
519
            break;
520
         default:
521
            continue; /* invalid attachment */
522
         }
523
 
524
         dri_drawable_get_format(drawable, statt, &format, &bind);
525
         if (format == PIPE_FORMAT_NONE)
526
            continue;
527
 
528
         /* dri2_drawable_get_buffers has already filled dri_drawable->w
529
          * and dri_drawable->h */
530
         templ.width0 = dri_drawable->w;
531
         templ.height0 = dri_drawable->h;
532
         templ.format = format;
533
         templ.bind = bind;
534
         whandle.handle = buf->name;
535
         whandle.stride = buf->pitch;
536
         if (screen->can_share_buffer)
537
            whandle.type = DRM_API_HANDLE_TYPE_SHARED;
538
         else
539
            whandle.type = DRM_API_HANDLE_TYPE_KMS;
540
         drawable->textures[statt] =
541
            screen->base.screen->resource_from_handle(screen->base.screen,
542
                  &templ, &whandle);
543
         assert(drawable->textures[statt]);
544
      }
545
   }
546
 
547
   /* Allocate private MSAA colorbuffers. */
548
   if (drawable->stvis.samples > 1) {
549
      for (i = 0; i < statts_count; i++) {
550
         enum st_attachment_type statt = statts[i];
551
 
552
         if (statt == ST_ATTACHMENT_DEPTH_STENCIL)
553
            continue;
554
 
555
         if (drawable->textures[statt]) {
556
            templ.format = drawable->textures[statt]->format;
557
            templ.bind = drawable->textures[statt]->bind;
558
            templ.nr_samples = drawable->stvis.samples;
559
 
560
            /* Try to reuse the resource.
561
             * (the other resource parameters should be constant)
562
             */
563
            if (!drawable->msaa_textures[statt] ||
564
                drawable->msaa_textures[statt]->width0 != templ.width0 ||
565
                drawable->msaa_textures[statt]->height0 != templ.height0) {
566
               /* Allocate a new one. */
567
               pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
568
 
569
               drawable->msaa_textures[statt] =
570
                  screen->base.screen->resource_create(screen->base.screen,
571
                                                       &templ);
572
               assert(drawable->msaa_textures[statt]);
573
 
574
               /* If there are any MSAA resources, we should initialize them
575
                * such that they contain the same data as the single-sample
576
                * resources we just got from the X server.
577
                *
578
                * The reason for this is that the state tracker (and
579
                * therefore the app) can access the MSAA resources only.
580
                * The single-sample resources are not exposed
581
                * to the state tracker.
582
                *
583
                */
584
               dri_pipe_blit(ctx->st->pipe,
585
                             drawable->msaa_textures[statt],
586
                             drawable->textures[statt]);
587
            }
588
         }
589
         else {
590
            pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
591
         }
592
      }
593
   }
594
 
595
   /* Allocate a private depth-stencil buffer. */
596
   if (alloc_depthstencil) {
597
      enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;
598
      struct pipe_resource **zsbuf;
599
      enum pipe_format format;
600
      unsigned bind;
601
 
602
      dri_drawable_get_format(drawable, statt, &format, &bind);
603
 
604
      if (format) {
605
         templ.format = format;
606
         templ.bind = bind;
607
 
608
         if (drawable->stvis.samples > 1) {
609
            templ.nr_samples = drawable->stvis.samples;
610
            zsbuf = &drawable->msaa_textures[statt];
611
         }
612
         else {
613
            templ.nr_samples = 0;
614
            zsbuf = &drawable->textures[statt];
615
         }
616
 
617
         /* Try to reuse the resource.
618
          * (the other resource parameters should be constant)
619
          */
620
         if (!*zsbuf ||
621
             (*zsbuf)->width0 != templ.width0 ||
622
             (*zsbuf)->height0 != templ.height0) {
623
            /* Allocate a new one. */
624
            pipe_resource_reference(zsbuf, NULL);
625
            *zsbuf = screen->base.screen->resource_create(screen->base.screen,
626
                                                          &templ);
627
            assert(*zsbuf);
628
         }
629
      }
630
      else {
631
         pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
632
         pipe_resource_reference(&drawable->textures[statt], NULL);
633
      }
634
   }
635
 
636
   /* For DRI2, we may get the same buffers again from the server.
637
    * To prevent useless imports of gem names, drawable->old* is used
638
    * to bypass the import if we get the same buffers. This doesn't apply
639
    * to DRI3/Wayland, users of image.loader, since the buffer is managed
640
    * by the client (no import), and the back buffer is going to change
641
    * at every redraw.
642
    */
643
   if (!image) {
644
      drawable->old_num = num_buffers;
645
      drawable->old_w = dri_drawable->w;
646
      drawable->old_h = dri_drawable->h;
647
      memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);
648
   }
649
}
650
 
651
static void
652
dri2_flush_frontbuffer(struct dri_context *ctx,
653
                       struct dri_drawable *drawable,
654
                       enum st_attachment_type statt)
655
{
656
   __DRIdrawable *dri_drawable = drawable->dPriv;
657
   const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
658
   const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
659
   struct pipe_context *pipe = ctx->st->pipe;
660
 
661
   if (statt != ST_ATTACHMENT_FRONT_LEFT)
662
      return;
663
 
664
   if (drawable->stvis.samples > 1) {
665
      /* Resolve the front buffer. */
666
      dri_pipe_blit(ctx->st->pipe,
667
                    drawable->textures[ST_ATTACHMENT_FRONT_LEFT],
668
                    drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]);
669
   }
670
 
671
   if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) {
672
      pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]);
673
   }
674
 
675
   pipe->flush(pipe, NULL, 0);
676
 
677
   if (image) {
678
      image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
679
   }
680
   else if (loader->flushFrontBuffer) {
681
      loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
682
   }
683
}
684
 
685
static void
686
dri2_update_tex_buffer(struct dri_drawable *drawable,
687
                       struct dri_context *ctx,
688
                       struct pipe_resource *res)
689
{
690
   /* no-op */
691
}
692
 
693
static __DRIimage *
694
dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
695
{
696
   const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
697
   __DRIimage *img;
698
 
699
   if (!loader->lookupEGLImage)
700
      return NULL;
701
 
702
   img = loader->lookupEGLImage(screen->sPriv,
703
				handle, screen->sPriv->loaderPrivate);
704
 
705
   return img;
706
}
707
 
708
static __DRIimage *
709
dri2_create_image_from_winsys(__DRIscreen *_screen,
710
                              int width, int height, int format,
711
                              struct winsys_handle *whandle, int pitch,
712
                              void *loaderPrivate)
713
{
714
   struct dri_screen *screen = dri_screen(_screen);
715
   __DRIimage *img;
716
   struct pipe_resource templ;
717
   unsigned tex_usage;
718
   enum pipe_format pf;
719
 
720
   tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
721
 
722
   switch (format) {
723
   case __DRI_IMAGE_FORMAT_RGB565:
724
      pf = PIPE_FORMAT_B5G6R5_UNORM;
725
      break;
726
   case __DRI_IMAGE_FORMAT_XRGB8888:
727
      pf = PIPE_FORMAT_B8G8R8X8_UNORM;
728
      break;
729
   case __DRI_IMAGE_FORMAT_ARGB8888:
730
      pf = PIPE_FORMAT_B8G8R8A8_UNORM;
731
      break;
732
   case __DRI_IMAGE_FORMAT_ABGR8888:
733
      pf = PIPE_FORMAT_R8G8B8A8_UNORM;
734
      break;
735
   default:
736
      pf = PIPE_FORMAT_NONE;
737
      break;
738
   }
739
   if (pf == PIPE_FORMAT_NONE)
740
      return NULL;
741
 
742
   img = CALLOC_STRUCT(__DRIimageRec);
743
   if (!img)
744
      return NULL;
745
 
746
   memset(&templ, 0, sizeof(templ));
747
   templ.bind = tex_usage;
748
   templ.format = pf;
749
   templ.target = screen->target;
750
   templ.last_level = 0;
751
   templ.width0 = width;
752
   templ.height0 = height;
753
   templ.depth0 = 1;
754
   templ.array_size = 1;
755
 
756
   whandle->stride = pitch * util_format_get_blocksize(pf);
757
 
758
   img->texture = screen->base.screen->resource_from_handle(screen->base.screen,
759
         &templ, whandle);
760
   if (!img->texture) {
761
      FREE(img);
762
      return NULL;
763
   }
764
 
765
   img->level = 0;
766
   img->layer = 0;
767
   img->dri_format = format;
768
   img->loader_private = loaderPrivate;
769
 
770
   return img;
771
}
772
 
773
static __DRIimage *
774
dri2_create_image_from_name(__DRIscreen *_screen,
775
                            int width, int height, int format,
776
                            int name, int pitch, void *loaderPrivate)
777
{
778
   struct winsys_handle whandle;
779
 
780
   memset(&whandle, 0, sizeof(whandle));
781
   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
782
   whandle.handle = name;
783
 
784
   return dri2_create_image_from_winsys(_screen, width, height, format,
785
                                        &whandle, pitch, loaderPrivate);
786
}
787
 
788
static __DRIimage *
789
dri2_create_image_from_fd(__DRIscreen *_screen,
790
                          int width, int height, int format,
791
                          int fd, int pitch, void *loaderPrivate)
792
{
793
   struct winsys_handle whandle;
794
 
795
   if (fd < 0)
796
      return NULL;
797
 
798
   memset(&whandle, 0, sizeof(whandle));
799
   whandle.type = DRM_API_HANDLE_TYPE_FD;
800
   whandle.handle = (unsigned)fd;
801
 
802
   return dri2_create_image_from_winsys(_screen, width, height, format,
803
                                        &whandle, pitch, loaderPrivate);
804
}
805
 
806
static __DRIimage *
807
dri2_create_image_from_renderbuffer(__DRIcontext *context,
808
				    int renderbuffer, void *loaderPrivate)
809
{
810
   struct dri_context *ctx = dri_context(context);
811
 
812
   if (!ctx->st->get_resource_for_egl_image)
813
      return NULL;
814
 
815
   /* TODO */
816
   return NULL;
817
}
818
 
819
static __DRIimage *
820
dri2_create_image(__DRIscreen *_screen,
821
                   int width, int height, int format,
822
                   unsigned int use, void *loaderPrivate)
823
{
824
   struct dri_screen *screen = dri_screen(_screen);
825
   __DRIimage *img;
826
   struct pipe_resource templ;
827
   unsigned tex_usage;
828
   enum pipe_format pf;
829
 
830
   tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
831
   if (use & __DRI_IMAGE_USE_SCANOUT)
832
      tex_usage |= PIPE_BIND_SCANOUT;
833
   if (use & __DRI_IMAGE_USE_SHARE)
834
      tex_usage |= PIPE_BIND_SHARED;
835
   if (use & __DRI_IMAGE_USE_LINEAR)
836
      tex_usage |= PIPE_BIND_LINEAR;
837
   if (use & __DRI_IMAGE_USE_CURSOR) {
838
      if (width != 64 || height != 64)
839
         return NULL;
840
      tex_usage |= PIPE_BIND_CURSOR;
841
   }
842
 
843
   switch (format) {
844
   case __DRI_IMAGE_FORMAT_RGB565:
845
      pf = PIPE_FORMAT_B5G6R5_UNORM;
846
      break;
847
   case __DRI_IMAGE_FORMAT_XRGB8888:
848
      pf = PIPE_FORMAT_B8G8R8X8_UNORM;
849
      break;
850
   case __DRI_IMAGE_FORMAT_ARGB8888:
851
      pf = PIPE_FORMAT_B8G8R8A8_UNORM;
852
      break;
853
   case __DRI_IMAGE_FORMAT_ABGR8888:
854
      pf = PIPE_FORMAT_R8G8B8A8_UNORM;
855
      break;
856
   default:
857
      pf = PIPE_FORMAT_NONE;
858
      break;
859
   }
860
   if (pf == PIPE_FORMAT_NONE)
861
      return NULL;
862
 
863
   img = CALLOC_STRUCT(__DRIimageRec);
864
   if (!img)
865
      return NULL;
866
 
867
   memset(&templ, 0, sizeof(templ));
868
   templ.bind = tex_usage;
869
   templ.format = pf;
870
   templ.target = PIPE_TEXTURE_2D;
871
   templ.last_level = 0;
872
   templ.width0 = width;
873
   templ.height0 = height;
874
   templ.depth0 = 1;
875
   templ.array_size = 1;
876
 
877
   img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
878
   if (!img->texture) {
879
      FREE(img);
880
      return NULL;
881
   }
882
 
883
   img->level = 0;
884
   img->layer = 0;
885
   img->dri_format = format;
886
   img->dri_components = 0;
887
 
888
   img->loader_private = loaderPrivate;
889
   return img;
890
}
891
 
892
static GLboolean
893
dri2_query_image(__DRIimage *image, int attrib, int *value)
894
{
895
   struct winsys_handle whandle;
896
   memset(&whandle, 0, sizeof(whandle));
897
 
898
   switch (attrib) {
899
   case __DRI_IMAGE_ATTRIB_STRIDE:
900
      whandle.type = DRM_API_HANDLE_TYPE_KMS;
901
      image->texture->screen->resource_get_handle(image->texture->screen,
902
            image->texture, &whandle);
903
      *value = whandle.stride;
904
      return GL_TRUE;
905
   case __DRI_IMAGE_ATTRIB_HANDLE:
906
      whandle.type = DRM_API_HANDLE_TYPE_KMS;
907
      image->texture->screen->resource_get_handle(image->texture->screen,
908
         image->texture, &whandle);
909
      *value = whandle.handle;
910
      return GL_TRUE;
911
   case __DRI_IMAGE_ATTRIB_NAME:
912
      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
913
      image->texture->screen->resource_get_handle(image->texture->screen,
914
         image->texture, &whandle);
915
      *value = whandle.handle;
916
      return GL_TRUE;
917
   case __DRI_IMAGE_ATTRIB_FD:
918
      whandle.type= DRM_API_HANDLE_TYPE_FD;
919
      image->texture->screen->resource_get_handle(image->texture->screen,
920
         image->texture, &whandle);
921
      *value = whandle.handle;
922
      return GL_TRUE;
923
   case __DRI_IMAGE_ATTRIB_FORMAT:
924
      *value = image->dri_format;
925
      return GL_TRUE;
926
   case __DRI_IMAGE_ATTRIB_WIDTH:
927
      *value = image->texture->width0;
928
      return GL_TRUE;
929
   case __DRI_IMAGE_ATTRIB_HEIGHT:
930
      *value = image->texture->height0;
931
      return GL_TRUE;
932
   case __DRI_IMAGE_ATTRIB_COMPONENTS:
933
      if (image->dri_components == 0)
934
         return GL_FALSE;
935
      *value = image->dri_components;
936
      return GL_TRUE;
937
   case __DRI_IMAGE_ATTRIB_FOURCC:
938
      *value = convert_to_fourcc(image->dri_format);
939
      return GL_TRUE;
940
   case __DRI_IMAGE_ATTRIB_NUM_PLANES:
941
      *value = 1;
942
      return GL_TRUE;
943
   default:
944
      return GL_FALSE;
945
   }
946
}
947
 
948
static __DRIimage *
949
dri2_dup_image(__DRIimage *image, void *loaderPrivate)
950
{
951
   __DRIimage *img;
952
 
953
   img = CALLOC_STRUCT(__DRIimageRec);
954
   if (!img)
955
      return NULL;
956
 
957
   img->texture = NULL;
958
   pipe_resource_reference(&img->texture, image->texture);
959
   img->level = image->level;
960
   img->layer = image->layer;
961
   img->dri_format = image->dri_format;
962
   /* This should be 0 for sub images, but dup is also used for base images. */
963
   img->dri_components = image->dri_components;
964
   img->loader_private = loaderPrivate;
965
 
966
   return img;
967
}
968
 
969
static GLboolean
970
dri2_validate_usage(__DRIimage *image, unsigned int use)
971
{
972
   /*
973
    * Gallium drivers are bad at adding usages to the resources
974
    * once opened again in another process, which is the main use
975
    * case for this, so we have to lie.
976
    */
977
   if (image != NULL)
978
      return GL_TRUE;
979
   else
980
      return GL_FALSE;
981
}
982
 
983
static __DRIimage *
984
dri2_from_names(__DRIscreen *screen, int width, int height, int format,
985
                int *names, int num_names, int *strides, int *offsets,
986
                void *loaderPrivate)
987
{
988
   __DRIimage *img;
989
   int stride, dri_components;
990
 
991
   if (num_names != 1)
992
      return NULL;
993
   if (offsets[0] != 0)
994
      return NULL;
995
 
996
   format = convert_fourcc(format, &dri_components);
997
   if (format == -1)
998
      return NULL;
999
 
1000
   /* Strides are in bytes not pixels. */
1001
   stride = strides[0] /4;
1002
 
1003
   img = dri2_create_image_from_name(screen, width, height, format,
1004
                                     names[0], stride, loaderPrivate);
1005
   if (img == NULL)
1006
      return NULL;
1007
 
1008
   img->dri_components = dri_components;
1009
   return img;
1010
}
1011
 
1012
static __DRIimage *
1013
dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
1014
{
1015
   __DRIimage *img;
1016
 
1017
   if (plane != 0)
1018
      return NULL;
1019
 
1020
   if (image->dri_components == 0)
1021
      return NULL;
1022
 
1023
   img = dri2_dup_image(image, loaderPrivate);
1024
   if (img == NULL)
1025
      return NULL;
1026
 
1027
   /* set this to 0 for sub images. */
1028
   img->dri_components = 0;
1029
   return img;
1030
}
1031
 
1032
static __DRIimage *
1033
dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
1034
                         int depth, int level, unsigned *error,
1035
                         void *loaderPrivate)
1036
{
1037
   __DRIimage *img;
1038
   struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
1039
   struct gl_texture_object *obj;
1040
   struct pipe_resource *tex;
1041
   GLuint face = 0;
1042
 
1043
   obj = _mesa_lookup_texture(ctx, texture);
1044
   if (!obj || obj->Target != target) {
1045
      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1046
      return NULL;
1047
   }
1048
 
1049
   tex = st_get_texobj_resource(obj);
1050
   if (!tex) {
1051
      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1052
      return NULL;
1053
   }
1054
 
1055
   if (target == GL_TEXTURE_CUBE_MAP)
1056
      face = depth;
1057
 
1058
   _mesa_test_texobj_completeness(ctx, obj);
1059
   if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
1060
      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1061
      return NULL;
1062
   }
1063
 
1064
   if (level < obj->BaseLevel || level > obj->_MaxLevel) {
1065
      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1066
      return NULL;
1067
   }
1068
 
1069
   if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
1070
      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1071
      return NULL;
1072
   }
1073
 
1074
   img = CALLOC_STRUCT(__DRIimageRec);
1075
   if (!img) {
1076
      *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
1077
      return NULL;
1078
   }
1079
 
1080
   img->level = level;
1081
   img->layer = depth;
1082
   img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
1083
 
1084
   img->loader_private = loaderPrivate;
1085
 
1086
   if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
1087
      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1088
      free(img);
1089
      return NULL;
1090
   }
1091
 
1092
   pipe_resource_reference(&img->texture, tex);
1093
 
1094
   *error = __DRI_IMAGE_ERROR_SUCCESS;
1095
   return img;
1096
}
1097
 
1098
static __DRIimage *
1099
dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
1100
              int *fds, int num_fds, int *strides, int *offsets,
1101
              void *loaderPrivate)
1102
{
1103
   __DRIimage *img;
1104
   int format, stride, dri_components;
1105
 
1106
   if (num_fds != 1)
1107
      return NULL;
1108
   if (offsets[0] != 0)
1109
      return NULL;
1110
 
1111
   format = convert_fourcc(fourcc, &dri_components);
1112
   if (format == -1)
1113
      return NULL;
1114
 
1115
   /* Strides are in bytes not pixels. */
1116
   stride = strides[0] /4;
1117
 
1118
   img = dri2_create_image_from_fd(screen, width, height, format,
1119
                                   fds[0], stride, loaderPrivate);
1120
   if (img == NULL)
1121
      return NULL;
1122
 
1123
   img->dri_components = dri_components;
1124
   return img;
1125
}
1126
 
1127
static __DRIimage *
1128
dri2_from_dma_bufs(__DRIscreen *screen,
1129
                   int width, int height, int fourcc,
1130
                   int *fds, int num_fds,
1131
                   int *strides, int *offsets,
1132
                   enum __DRIYUVColorSpace yuv_color_space,
1133
                   enum __DRISampleRange sample_range,
1134
                   enum __DRIChromaSiting horizontal_siting,
1135
                   enum __DRIChromaSiting vertical_siting,
1136
                   unsigned *error,
1137
                   void *loaderPrivate)
1138
{
1139
   __DRIimage *img;
1140
   int format, stride, dri_components;
1141
 
1142
   if (num_fds != 1 || offsets[0] != 0) {
1143
      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1144
      return NULL;
1145
   }
1146
 
1147
   format = convert_fourcc(fourcc, &dri_components);
1148
   if (format == -1) {
1149
      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1150
      return NULL;
1151
   }
1152
 
1153
   /* Strides are in bytes not pixels. */
1154
   stride = strides[0] /4;
1155
 
1156
   img = dri2_create_image_from_fd(screen, width, height, format,
1157
                                   fds[0], stride, loaderPrivate);
1158
   if (img == NULL) {
1159
      *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
1160
      return NULL;
1161
   }
1162
 
1163
   img->yuv_color_space = yuv_color_space;
1164
   img->sample_range = sample_range;
1165
   img->horizontal_siting = horizontal_siting;
1166
   img->vertical_siting = vertical_siting;
1167
   img->dri_components = dri_components;
1168
 
1169
   *error = __DRI_IMAGE_ERROR_SUCCESS;
1170
   return img;
1171
}
1172
 
1173
static void
1174
dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
1175
                int dstx0, int dsty0, int dstwidth, int dstheight,
1176
                int srcx0, int srcy0, int srcwidth, int srcheight,
1177
                int flush_flag)
1178
{
1179
   struct dri_context *ctx = dri_context(context);
1180
   struct pipe_context *pipe = ctx->st->pipe;
1181
   struct pipe_screen *screen;
1182
   struct pipe_fence_handle *fence;
1183
   struct pipe_blit_info blit;
1184
 
1185
   if (!dst || !src)
1186
      return;
1187
 
1188
   memset(&blit, 0, sizeof(blit));
1189
   blit.dst.resource = dst->texture;
1190
   blit.dst.box.x = dstx0;
1191
   blit.dst.box.y = dsty0;
1192
   blit.dst.box.width = dstwidth;
1193
   blit.dst.box.height = dstheight;
1194
   blit.dst.box.depth = 1;
1195
   blit.dst.format = dst->texture->format;
1196
   blit.src.resource = src->texture;
1197
   blit.src.box.x = srcx0;
1198
   blit.src.box.y = srcy0;
1199
   blit.src.box.width = srcwidth;
1200
   blit.src.box.height = srcheight;
1201
   blit.src.box.depth = 1;
1202
   blit.src.format = src->texture->format;
1203
   blit.mask = PIPE_MASK_RGBA;
1204
   blit.filter = PIPE_TEX_FILTER_NEAREST;
1205
 
1206
   pipe->blit(pipe, &blit);
1207
 
1208
   if (flush_flag == __BLIT_FLAG_FLUSH) {
1209
      pipe->flush_resource(pipe, dst->texture);
1210
      ctx->st->flush(ctx->st, 0, NULL);
1211
   } else if (flush_flag == __BLIT_FLAG_FINISH) {
1212
      screen = dri_screen(ctx->sPriv)->base.screen;
1213
      pipe->flush_resource(pipe, dst->texture);
1214
      ctx->st->flush(ctx->st, 0, &fence);
1215
      (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
1216
      screen->fence_reference(screen, &fence, NULL);
1217
   }
1218
}
1219
 
1220
static void
1221
dri2_destroy_image(__DRIimage *img)
1222
{
1223
   pipe_resource_reference(&img->texture, NULL);
1224
   FREE(img);
1225
}
1226
 
1227
static int
1228
dri2_get_capabilities(__DRIscreen *_screen)
1229
{
1230
   struct dri_screen *screen = dri_screen(_screen);
1231
 
1232
   return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
1233
}
1234
 
1235
/* The extension is modified during runtime if DRI_PRIME is detected */
1236
static __DRIimageExtension dri2ImageExtension = {
1237
    .base = { __DRI_IMAGE, 11 },
1238
 
1239
    .createImageFromName          = dri2_create_image_from_name,
1240
    .createImageFromRenderbuffer  = dri2_create_image_from_renderbuffer,
1241
    .destroyImage                 = dri2_destroy_image,
1242
    .createImage                  = dri2_create_image,
1243
    .queryImage                   = dri2_query_image,
1244
    .dupImage                     = dri2_dup_image,
1245
    .validateUsage                = dri2_validate_usage,
1246
    .createImageFromNames         = dri2_from_names,
1247
    .fromPlanar                   = dri2_from_planar,
1248
    .createImageFromTexture       = dri2_create_from_texture,
1249
    .createImageFromFds           = NULL,
1250
    .createImageFromDmaBufs       = NULL,
1251
    .blitImage                    = dri2_blit_image,
1252
    .getCapabilities              = dri2_get_capabilities,
1253
};
1254
 
1255
 
1256
static bool
1257
dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen)
1258
{
1259
   return screen->opencl_dri_event_add_ref &&
1260
          screen->opencl_dri_event_release &&
1261
          screen->opencl_dri_event_wait &&
1262
          screen->opencl_dri_event_get_fence;
1263
}
1264
 
1265
static bool
1266
dri2_load_opencl_interop(struct dri_screen *screen)
1267
{
1268
#if defined(RTLD_DEFAULT)
1269
   bool success;
1270
 
1271
   pipe_mutex_lock(screen->opencl_func_mutex);
1272
 
1273
   if (dri2_is_opencl_interop_loaded_locked(screen)) {
1274
      pipe_mutex_unlock(screen->opencl_func_mutex);
1275
      return true;
1276
   }
1277
 
1278
   screen->opencl_dri_event_add_ref =
1279
      dlsym(RTLD_DEFAULT, "opencl_dri_event_add_ref");
1280
   screen->opencl_dri_event_release =
1281
      dlsym(RTLD_DEFAULT, "opencl_dri_event_release");
1282
   screen->opencl_dri_event_wait =
1283
      dlsym(RTLD_DEFAULT, "opencl_dri_event_wait");
1284
   screen->opencl_dri_event_get_fence =
1285
      dlsym(RTLD_DEFAULT, "opencl_dri_event_get_fence");
1286
 
1287
   success = dri2_is_opencl_interop_loaded_locked(screen);
1288
   pipe_mutex_unlock(screen->opencl_func_mutex);
1289
   return success;
1290
#else
1291
   return false;
1292
#endif
1293
}
1294
 
1295
struct dri2_fence {
1296
   struct pipe_fence_handle *pipe_fence;
1297
   void *cl_event;
1298
};
1299
 
1300
static void *
1301
dri2_create_fence(__DRIcontext *_ctx)
1302
{
1303
   struct pipe_context *ctx = dri_context(_ctx)->st->pipe;
1304
   struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence);
1305
 
1306
   if (!fence)
1307
      return NULL;
1308
 
1309
   ctx->flush(ctx, &fence->pipe_fence, 0);
1310
 
1311
   if (!fence->pipe_fence) {
1312
      FREE(fence);
1313
      return NULL;
1314
   }
1315
 
1316
   return fence;
1317
}
1318
 
1319
static void *
1320
dri2_get_fence_from_cl_event(__DRIscreen *_screen, intptr_t cl_event)
1321
{
1322
   struct dri_screen *driscreen = dri_screen(_screen);
1323
   struct dri2_fence *fence;
1324
 
1325
   if (!dri2_load_opencl_interop(driscreen))
1326
      return NULL;
1327
 
1328
   fence = CALLOC_STRUCT(dri2_fence);
1329
   if (!fence)
1330
      return NULL;
1331
 
1332
   fence->cl_event = (void*)cl_event;
1333
 
1334
   if (!driscreen->opencl_dri_event_add_ref(fence->cl_event)) {
1335
      free(fence);
1336
      return NULL;
1337
   }
1338
 
1339
   return fence;
1340
}
1341
 
1342
static void
1343
dri2_destroy_fence(__DRIscreen *_screen, void *_fence)
1344
{
1345
   struct dri_screen *driscreen = dri_screen(_screen);
1346
   struct pipe_screen *screen = driscreen->base.screen;
1347
   struct dri2_fence *fence = (struct dri2_fence*)_fence;
1348
 
1349
   if (fence->pipe_fence)
1350
      screen->fence_reference(screen, &fence->pipe_fence, NULL);
1351
   else if (fence->cl_event)
1352
      driscreen->opencl_dri_event_release(fence->cl_event);
1353
   else
1354
      assert(0);
1355
 
1356
   FREE(fence);
1357
}
1358
 
1359
static GLboolean
1360
dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags,
1361
                      uint64_t timeout)
1362
{
1363
   struct dri_screen *driscreen = dri_screen(_ctx->driScreenPriv);
1364
   struct pipe_screen *screen = driscreen->base.screen;
1365
   struct dri2_fence *fence = (struct dri2_fence*)_fence;
1366
 
1367
   /* No need to flush. The context was flushed when the fence was created. */
1368
 
1369
   if (fence->pipe_fence)
1370
      return screen->fence_finish(screen, fence->pipe_fence, timeout);
1371
   else if (fence->cl_event) {
1372
      struct pipe_fence_handle *pipe_fence =
1373
         driscreen->opencl_dri_event_get_fence(fence->cl_event);
1374
 
1375
      if (pipe_fence)
1376
         return screen->fence_finish(screen, pipe_fence, timeout);
1377
      else
1378
         return driscreen->opencl_dri_event_wait(fence->cl_event, timeout);
1379
   }
1380
   else {
1381
      assert(0);
1382
      return false;
1383
   }
1384
}
1385
 
1386
static void
1387
dri2_server_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags)
1388
{
1389
   /* AFAIK, no driver currently supports parallel context execution. */
1390
}
1391
 
1392
static __DRI2fenceExtension dri2FenceExtension = {
1393
   .base = { __DRI2_FENCE, 1 },
1394
 
1395
   .create_fence = dri2_create_fence,
1396
   .get_fence_from_cl_event = dri2_get_fence_from_cl_event,
1397
   .destroy_fence = dri2_destroy_fence,
1398
   .client_wait_sync = dri2_client_wait_sync,
1399
   .server_wait_sync = dri2_server_wait_sync
1400
};
1401
 
1402
static const __DRIrobustnessExtension dri2Robustness = {
1403
   .base = { __DRI2_ROBUSTNESS, 1 }
1404
};
1405
 
1406
/*
1407
 * Backend function init_screen.
1408
 */
1409
 
1410
static const __DRIextension *dri_screen_extensions[] = {
1411
   &driTexBufferExtension.base,
1412
   &dri2FlushExtension.base,
1413
   &dri2ImageExtension.base,
1414
   &dri2RendererQueryExtension.base,
1415
   &dri2ConfigQueryExtension.base,
1416
   &dri2ThrottleExtension.base,
1417
   &dri2FenceExtension.base,
1418
   NULL
1419
};
1420
 
1421
static const __DRIextension *dri_robust_screen_extensions[] = {
1422
   &driTexBufferExtension.base,
1423
   &dri2FlushExtension.base,
1424
   &dri2ImageExtension.base,
1425
   &dri2RendererQueryExtension.base,
1426
   &dri2ConfigQueryExtension.base,
1427
   &dri2ThrottleExtension.base,
1428
   &dri2FenceExtension.base,
1429
   &dri2Robustness.base,
1430
   NULL
1431
};
1432
 
1433
/**
1434
 * This is the driver specific part of the createNewScreen entry point.
1435
 *
1436
 * Returns the struct gl_config supported by this driver.
1437
 */
1438
static const __DRIconfig **
1439
dri2_init_screen(__DRIscreen * sPriv)
1440
{
1441
   const __DRIconfig **configs;
1442
   struct dri_screen *screen;
1443
   struct pipe_screen *pscreen = NULL;
1444
   const struct drm_conf_ret *throttle_ret = NULL;
1445
   const struct drm_conf_ret *dmabuf_ret = NULL;
1446
 
1447
   screen = CALLOC_STRUCT(dri_screen);
1448
   if (!screen)
1449
      return NULL;
1450
 
1451
   screen->sPriv = sPriv;
1452
   screen->fd = sPriv->fd;
1453
   pipe_mutex_init(screen->opencl_func_mutex);
1454
 
1455
   sPriv->driverPrivate = (void *)screen;
1456
 
1457
#if GALLIUM_STATIC_TARGETS
1458
   pscreen = dd_create_screen(screen->fd);
1459
 
1460
   throttle_ret = dd_configuration(DRM_CONF_THROTTLE);
1461
   dmabuf_ret = dd_configuration(DRM_CONF_SHARE_FD);
1462
#else
1463
   if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd, false)) {
1464
      pscreen = pipe_loader_create_screen(screen->dev, PIPE_SEARCH_DIR);
1465
 
1466
      throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE);
1467
      dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD);
1468
   }
1469
#endif // GALLIUM_STATIC_TARGETS
1470
 
1471
   if (throttle_ret && throttle_ret->val.val_int != -1) {
1472
      screen->throttling_enabled = TRUE;
1473
      screen->default_throttle_frames = throttle_ret->val.val_int;
1474
   }
1475
 
1476
   if (dmabuf_ret && dmabuf_ret->val.val_bool) {
1477
      uint64_t cap;
1478
 
1479
      if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
1480
          (cap & DRM_PRIME_CAP_IMPORT)) {
1481
         dri2ImageExtension.createImageFromFds = dri2_from_fds;
1482
         dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
1483
      }
1484
   }
1485
 
1486
   if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) {
1487
      sPriv->extensions = dri_robust_screen_extensions;
1488
      screen->has_reset_status_query = true;
1489
   }
1490
   else
1491
      sPriv->extensions = dri_screen_extensions;
1492
 
1493
   /* dri_init_screen_helper checks pscreen for us */
1494
 
1495
#if GALLIUM_STATIC_TARGETS
1496
   configs = dri_init_screen_helper(screen, pscreen, dd_driver_name());
1497
#else
1498
   configs = dri_init_screen_helper(screen, pscreen, screen->dev->driver_name);
1499
#endif // GALLIUM_STATIC_TARGETS
1500
   if (!configs)
1501
      goto fail;
1502
 
1503
   screen->can_share_buffer = true;
1504
   screen->auto_fake_front = dri_with_format(sPriv);
1505
   screen->broken_invalidate = !sPriv->dri2.useInvalidate;
1506
   screen->lookup_egl_image = dri2_lookup_egl_image;
1507
 
1508
   return configs;
1509
fail:
1510
   dri_destroy_screen_helper(screen);
1511
#if !GALLIUM_STATIC_TARGETS
1512
   if (screen->dev)
1513
      pipe_loader_release(&screen->dev, 1);
1514
#endif // !GALLIUM_STATIC_TARGETS
1515
   FREE(screen);
1516
   return NULL;
1517
}
1518
 
1519
/**
1520
 * This is the driver specific part of the createNewScreen entry point.
1521
 *
1522
 * Returns the struct gl_config supported by this driver.
1523
 */
1524
static const __DRIconfig **
1525
dri_kms_init_screen(__DRIscreen * sPriv)
1526
{
1527
#if GALLIUM_STATIC_TARGETS
1528
#if defined(GALLIUM_SOFTPIPE)
1529
   const __DRIconfig **configs;
1530
   struct dri_screen *screen;
1531
   struct pipe_screen *pscreen = NULL;
1532
   uint64_t cap;
1533
 
1534
   screen = CALLOC_STRUCT(dri_screen);
1535
   if (!screen)
1536
      return NULL;
1537
 
1538
   screen->sPriv = sPriv;
1539
   screen->fd = sPriv->fd;
1540
 
1541
   sPriv->driverPrivate = (void *)screen;
1542
 
1543
   pscreen = kms_swrast_create_screen(screen->fd);
1544
 
1545
   if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
1546
          (cap & DRM_PRIME_CAP_IMPORT)) {
1547
      dri2ImageExtension.createImageFromFds = dri2_from_fds;
1548
      dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
1549
   }
1550
 
1551
   sPriv->extensions = dri_screen_extensions;
1552
 
1553
   /* dri_init_screen_helper checks pscreen for us */
1554
   configs = dri_init_screen_helper(screen, pscreen, "swrast");
1555
   if (!configs)
1556
      goto fail;
1557
 
1558
   screen->can_share_buffer = false;
1559
   screen->auto_fake_front = dri_with_format(sPriv);
1560
   screen->broken_invalidate = !sPriv->dri2.useInvalidate;
1561
   screen->lookup_egl_image = dri2_lookup_egl_image;
1562
 
1563
   return configs;
1564
fail:
1565
   dri_destroy_screen_helper(screen);
1566
   FREE(screen);
1567
#endif // GALLIUM_SOFTPIPE
1568
#endif // GALLIUM_STATIC_TARGETS
1569
   return NULL;
1570
}
1571
 
1572
static boolean
1573
dri2_create_buffer(__DRIscreen * sPriv,
1574
                   __DRIdrawable * dPriv,
1575
                   const struct gl_config * visual, boolean isPixmap)
1576
{
1577
   struct dri_drawable *drawable = NULL;
1578
 
1579
   if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
1580
      return FALSE;
1581
 
1582
   drawable = dPriv->driverPrivate;
1583
 
1584
   drawable->allocate_textures = dri2_allocate_textures;
1585
   drawable->flush_frontbuffer = dri2_flush_frontbuffer;
1586
   drawable->update_tex_buffer = dri2_update_tex_buffer;
1587
 
1588
   return TRUE;
1589
}
1590
 
1591
/**
1592
 * DRI driver virtual function table.
1593
 *
1594
 * DRI versions differ in their implementation of init_screen and swap_buffers.
1595
 */
1596
const struct __DriverAPIRec galliumdrm_driver_api = {
1597
   .InitScreen = dri2_init_screen,
1598
   .DestroyScreen = dri_destroy_screen,
1599
   .CreateContext = dri_create_context,
1600
   .DestroyContext = dri_destroy_context,
1601
   .CreateBuffer = dri2_create_buffer,
1602
   .DestroyBuffer = dri_destroy_buffer,
1603
   .MakeCurrent = dri_make_current,
1604
   .UnbindContext = dri_unbind_context,
1605
 
1606
   .AllocateBuffer = dri2_allocate_buffer,
1607
   .ReleaseBuffer  = dri2_release_buffer,
1608
};
1609
 
1610
/**
1611
 * DRI driver virtual function table.
1612
 *
1613
 * KMS/DRM version of the DriverAPI above sporting a different InitScreen
1614
 * hook. The latter is used to explicitly initialise the kms_swrast driver
1615
 * rather than selecting the approapriate driver as suggested by the loader.
1616
 */
1617
const struct __DriverAPIRec dri_kms_driver_api = {
1618
   .InitScreen = dri_kms_init_screen,
1619
   .DestroyScreen = dri_destroy_screen,
1620
   .CreateContext = dri_create_context,
1621
   .DestroyContext = dri_destroy_context,
1622
   .CreateBuffer = dri2_create_buffer,
1623
   .DestroyBuffer = dri_destroy_buffer,
1624
   .MakeCurrent = dri_make_current,
1625
   .UnbindContext = dri_unbind_context,
1626
 
1627
   .AllocateBuffer = dri2_allocate_buffer,
1628
   .ReleaseBuffer  = dri2_release_buffer,
1629
};
1630
 
1631
/* This is the table of extensions that the loader will dlsym() for. */
1632
const __DRIextension *galliumdrm_driver_extensions[] = {
1633
    &driCoreExtension.base,
1634
    &driImageDriverExtension.base,
1635
    &driDRI2Extension.base,
1636
    &gallium_config_options.base,
1637
    NULL
1638
};
1639
 
1640
/* vim: set sw=3 ts=8 sts=3 expandtab: */