OSDN Git Service

st/dri: add note about GL interop version checks
[android-x86/external-mesa.git] / src / gallium / state_trackers / dri / dri2.c
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 <keithw@vmware.com> Jakob Bornecrantz
28  *    <wallbraker@gmail.com> Chia-I Wu <olv@lunarg.com>
29  */
30
31 #include <xf86drm.h>
32 #include <dlfcn.h>
33 #include "GL/mesa_glinterop.h"
34 #include "util/u_memory.h"
35 #include "util/u_inlines.h"
36 #include "util/u_format.h"
37 #include "util/u_debug.h"
38 #include "state_tracker/drm_driver.h"
39 #include "state_tracker/st_cb_bufferobjects.h"
40 #include "state_tracker/st_cb_fbo.h"
41 #include "state_tracker/st_cb_texture.h"
42 #include "state_tracker/st_texture.h"
43 #include "state_tracker/st_context.h"
44 #include "pipe-loader/pipe_loader.h"
45 #include "main/bufferobj.h"
46 #include "main/texobj.h"
47
48 #include "dri_screen.h"
49 #include "dri_context.h"
50 #include "dri_drawable.h"
51 #include "dri_query_renderer.h"
52 #include "dri2_buffer.h"
53
54 static int convert_fourcc(int format, int *dri_components_p)
55 {
56    int dri_components;
57    switch(format) {
58    case __DRI_IMAGE_FOURCC_RGB565:
59       format = __DRI_IMAGE_FORMAT_RGB565;
60       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
61       break;
62    case __DRI_IMAGE_FOURCC_ARGB8888:
63       format = __DRI_IMAGE_FORMAT_ARGB8888;
64       dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
65       break;
66    case __DRI_IMAGE_FOURCC_XRGB8888:
67       format = __DRI_IMAGE_FORMAT_XRGB8888;
68       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
69       break;
70    case __DRI_IMAGE_FOURCC_ABGR8888:
71       format = __DRI_IMAGE_FORMAT_ABGR8888;
72       dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
73       break;
74    case __DRI_IMAGE_FOURCC_XBGR8888:
75       format = __DRI_IMAGE_FORMAT_XBGR8888;
76       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
77       break;
78    default:
79       return -1;
80    }
81    *dri_components_p = dri_components;
82    return format;
83 }
84
85 static int convert_to_fourcc(int format)
86 {
87    switch(format) {
88    case __DRI_IMAGE_FORMAT_RGB565:
89       format = __DRI_IMAGE_FOURCC_RGB565;
90       break;
91    case __DRI_IMAGE_FORMAT_ARGB8888:
92       format = __DRI_IMAGE_FOURCC_ARGB8888;
93       break;
94    case __DRI_IMAGE_FORMAT_XRGB8888:
95       format = __DRI_IMAGE_FOURCC_XRGB8888;
96       break;
97    case __DRI_IMAGE_FORMAT_ABGR8888:
98       format = __DRI_IMAGE_FOURCC_ABGR8888;
99       break;
100    case __DRI_IMAGE_FORMAT_XBGR8888:
101       format = __DRI_IMAGE_FOURCC_XBGR8888;
102       break;
103    default:
104       return -1;
105    }
106    return format;
107 }
108
109 static enum pipe_format dri2_format_to_pipe_format (int format)
110 {
111    enum pipe_format pf;
112
113    switch (format) {
114    case __DRI_IMAGE_FORMAT_RGB565:
115       pf = PIPE_FORMAT_B5G6R5_UNORM;
116       break;
117    case __DRI_IMAGE_FORMAT_XRGB8888:
118       pf = PIPE_FORMAT_BGRX8888_UNORM;
119       break;
120    case __DRI_IMAGE_FORMAT_ARGB8888:
121       pf = PIPE_FORMAT_BGRA8888_UNORM;
122       break;
123    case __DRI_IMAGE_FORMAT_ABGR8888:
124       pf = PIPE_FORMAT_RGBA8888_UNORM;
125       break;
126    default:
127       pf = PIPE_FORMAT_NONE;
128       break;
129    }
130
131    return pf;
132 }
133
134 /**
135  * DRI2 flush extension.
136  */
137 static void
138 dri2_flush_drawable(__DRIdrawable *dPriv)
139 {
140    dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);
141 }
142
143 static void
144 dri2_invalidate_drawable(__DRIdrawable *dPriv)
145 {
146    struct dri_drawable *drawable = dri_drawable(dPriv);
147
148    dri2InvalidateDrawable(dPriv);
149    drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
150
151    p_atomic_inc(&drawable->base.stamp);
152 }
153
154 static const __DRI2flushExtension dri2FlushExtension = {
155     .base = { __DRI2_FLUSH, 4 },
156
157     .flush                = dri2_flush_drawable,
158     .invalidate           = dri2_invalidate_drawable,
159     .flush_with_flags     = dri_flush,
160 };
161
162 /**
163  * Retrieve __DRIbuffer from the DRI loader.
164  */
165 static __DRIbuffer *
166 dri2_drawable_get_buffers(struct dri_drawable *drawable,
167                           const enum st_attachment_type *atts,
168                           unsigned *count)
169 {
170    __DRIdrawable *dri_drawable = drawable->dPriv;
171    const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
172    boolean with_format;
173    __DRIbuffer *buffers;
174    int num_buffers;
175    unsigned attachments[10];
176    unsigned num_attachments, i;
177
178    assert(loader);
179    with_format = dri_with_format(drawable->sPriv);
180
181    num_attachments = 0;
182
183    /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
184    if (!with_format)
185       attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
186
187    for (i = 0; i < *count; i++) {
188       enum pipe_format format;
189       unsigned bind;
190       int att, depth;
191
192       dri_drawable_get_format(drawable, atts[i], &format, &bind);
193       if (format == PIPE_FORMAT_NONE)
194          continue;
195
196       switch (atts[i]) {
197       case ST_ATTACHMENT_FRONT_LEFT:
198          /* already added */
199          if (!with_format)
200             continue;
201          att = __DRI_BUFFER_FRONT_LEFT;
202          break;
203       case ST_ATTACHMENT_BACK_LEFT:
204          att = __DRI_BUFFER_BACK_LEFT;
205          break;
206       case ST_ATTACHMENT_FRONT_RIGHT:
207          att = __DRI_BUFFER_FRONT_RIGHT;
208          break;
209       case ST_ATTACHMENT_BACK_RIGHT:
210          att = __DRI_BUFFER_BACK_RIGHT;
211          break;
212       default:
213          continue;
214       }
215
216       /*
217        * In this switch statement we must support all formats that
218        * may occur as the stvis->color_format.
219        */
220       switch(format) {
221       case PIPE_FORMAT_BGRA8888_UNORM:
222          depth = 32;
223          break;
224       case PIPE_FORMAT_BGRX8888_UNORM:
225          depth = 24;
226          break;
227       case PIPE_FORMAT_B5G6R5_UNORM:
228          depth = 16;
229          break;
230       default:
231          depth = util_format_get_blocksizebits(format);
232          assert(!"Unexpected format in dri2_drawable_get_buffers()");
233       }
234
235       attachments[num_attachments++] = att;
236       if (with_format) {
237          attachments[num_attachments++] = depth;
238       }
239    }
240
241    if (with_format) {
242       num_attachments /= 2;
243       buffers = loader->getBuffersWithFormat(dri_drawable,
244             &dri_drawable->w, &dri_drawable->h,
245             attachments, num_attachments,
246             &num_buffers, dri_drawable->loaderPrivate);
247    }
248    else {
249       buffers = loader->getBuffers(dri_drawable,
250             &dri_drawable->w, &dri_drawable->h,
251             attachments, num_attachments,
252             &num_buffers, dri_drawable->loaderPrivate);
253    }
254
255    if (buffers)
256       *count = num_buffers;
257
258    return buffers;
259 }
260
261 static bool
262 dri_image_drawable_get_buffers(struct dri_drawable *drawable,
263                                struct __DRIimageList *images,
264                                const enum st_attachment_type *statts,
265                                unsigned statts_count)
266 {
267    __DRIdrawable *dPriv = drawable->dPriv;
268    __DRIscreen *sPriv = drawable->sPriv;
269    unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;
270    enum pipe_format pf;
271    uint32_t buffer_mask = 0;
272    unsigned i, bind;
273
274    for (i = 0; i < statts_count; i++) {
275       dri_drawable_get_format(drawable, statts[i], &pf, &bind);
276       if (pf == PIPE_FORMAT_NONE)
277          continue;
278
279       switch (statts[i]) {
280       case ST_ATTACHMENT_FRONT_LEFT:
281          buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
282          break;
283       case ST_ATTACHMENT_BACK_LEFT:
284          buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
285          break;
286       default:
287          continue;
288       }
289
290       switch (pf) {
291       case PIPE_FORMAT_B5G6R5_UNORM:
292          image_format = __DRI_IMAGE_FORMAT_RGB565;
293          break;
294       case PIPE_FORMAT_BGRX8888_UNORM:
295          image_format = __DRI_IMAGE_FORMAT_XRGB8888;
296          break;
297       case PIPE_FORMAT_BGRA8888_UNORM:
298          image_format = __DRI_IMAGE_FORMAT_ARGB8888;
299          break;
300       case PIPE_FORMAT_RGBA8888_UNORM:
301          image_format = __DRI_IMAGE_FORMAT_ABGR8888;
302          break;
303       default:
304          image_format = __DRI_IMAGE_FORMAT_NONE;
305          break;
306       }
307    }
308
309    return (*sPriv->image.loader->getBuffers) (dPriv, image_format,
310                                        (uint32_t *) &drawable->base.stamp,
311                                        dPriv->loaderPrivate, buffer_mask,
312                                        images);
313 }
314
315 static __DRIbuffer *
316 dri2_allocate_buffer(__DRIscreen *sPriv,
317                      unsigned attachment, unsigned format,
318                      int width, int height)
319 {
320    struct dri_screen *screen = dri_screen(sPriv);
321    struct dri2_buffer *buffer;
322    struct pipe_resource templ;
323    enum pipe_format pf;
324    unsigned bind = 0;
325    struct winsys_handle whandle;
326
327    switch (attachment) {
328       case __DRI_BUFFER_FRONT_LEFT:
329       case __DRI_BUFFER_FAKE_FRONT_LEFT:
330          bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
331          break;
332       case __DRI_BUFFER_BACK_LEFT:
333          bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
334          break;
335       case __DRI_BUFFER_DEPTH:
336       case __DRI_BUFFER_DEPTH_STENCIL:
337       case __DRI_BUFFER_STENCIL:
338             bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
339          break;
340    }
341
342    /* because we get the handle and stride */
343    bind |= PIPE_BIND_SHARED;
344
345    switch (format) {
346       case 32:
347          pf = PIPE_FORMAT_BGRA8888_UNORM;
348          break;
349       case 24:
350          pf = PIPE_FORMAT_BGRX8888_UNORM;
351          break;
352       case 16:
353          pf = PIPE_FORMAT_Z16_UNORM;
354          break;
355       default:
356          return NULL;
357    }
358
359    buffer = CALLOC_STRUCT(dri2_buffer);
360    if (!buffer)
361       return NULL;
362
363    memset(&templ, 0, sizeof(templ));
364    templ.bind = bind;
365    templ.format = pf;
366    templ.target = PIPE_TEXTURE_2D;
367    templ.last_level = 0;
368    templ.width0 = width;
369    templ.height0 = height;
370    templ.depth0 = 1;
371    templ.array_size = 1;
372
373    buffer->resource =
374       screen->base.screen->resource_create(screen->base.screen, &templ);
375    if (!buffer->resource) {
376       FREE(buffer);
377       return NULL;
378    }
379
380    memset(&whandle, 0, sizeof(whandle));
381    if (screen->can_share_buffer)
382       whandle.type = DRM_API_HANDLE_TYPE_SHARED;
383    else
384       whandle.type = DRM_API_HANDLE_TYPE_KMS;
385
386    screen->base.screen->resource_get_handle(screen->base.screen,
387          buffer->resource, &whandle,
388          PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ);
389
390    buffer->base.attachment = attachment;
391    buffer->base.name = whandle.handle;
392    buffer->base.cpp = util_format_get_blocksize(pf);
393    buffer->base.pitch = whandle.stride;
394
395    return &buffer->base;
396 }
397
398 static void
399 dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
400 {
401    struct dri2_buffer *buffer = dri2_buffer(bPriv);
402
403    pipe_resource_reference(&buffer->resource, NULL);
404    FREE(buffer);
405 }
406
407 /*
408  * Backend functions for st_framebuffer interface.
409  */
410
411 static void
412 dri2_allocate_textures(struct dri_context *ctx,
413                        struct dri_drawable *drawable,
414                        const enum st_attachment_type *statts,
415                        unsigned statts_count)
416 {
417    __DRIscreen *sPriv = drawable->sPriv;
418    __DRIdrawable *dri_drawable = drawable->dPriv;
419    struct dri_screen *screen = dri_screen(sPriv);
420    struct pipe_resource templ;
421    boolean alloc_depthstencil = FALSE;
422    unsigned i, j, bind;
423    const __DRIimageLoaderExtension *image = sPriv->image.loader;
424    /* Image specific variables */
425    struct __DRIimageList images;
426    /* Dri2 specific variables */
427    __DRIbuffer *buffers = NULL;
428    struct winsys_handle whandle;
429    unsigned num_buffers = statts_count;
430
431    /* First get the buffers from the loader */
432    if (image) {
433       if (!dri_image_drawable_get_buffers(drawable, &images,
434                                           statts, statts_count))
435          return;
436    }
437    else {
438       buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
439       if (!buffers || (drawable->old_num == num_buffers &&
440                        drawable->old_w == dri_drawable->w &&
441                        drawable->old_h == dri_drawable->h &&
442                        memcmp(drawable->old, buffers,
443                               sizeof(__DRIbuffer) * num_buffers) == 0))
444          return;
445    }
446
447    /* Second clean useless resources*/
448
449    /* See if we need a depth-stencil buffer. */
450    for (i = 0; i < statts_count; i++) {
451       if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
452          alloc_depthstencil = TRUE;
453          break;
454       }
455    }
456
457    /* Delete the resources we won't need. */
458    for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
459       /* Don't delete the depth-stencil buffer, we can reuse it. */
460       if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
461          continue;
462
463       /* Flush the texture before unreferencing, so that other clients can
464        * see what the driver has rendered.
465        */
466       if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {
467          struct pipe_context *pipe = ctx->st->pipe;
468          pipe->flush_resource(pipe, drawable->textures[i]);
469       }
470
471       pipe_resource_reference(&drawable->textures[i], NULL);
472    }
473
474    if (drawable->stvis.samples > 1) {
475       for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
476          boolean del = TRUE;
477
478          /* Don't delete MSAA resources for the attachments which are enabled,
479           * we can reuse them. */
480          for (j = 0; j < statts_count; j++) {
481             if (i == statts[j]) {
482                del = FALSE;
483                break;
484             }
485          }
486
487          if (del) {
488             pipe_resource_reference(&drawable->msaa_textures[i], NULL);
489          }
490       }
491    }
492
493    /* Third use the buffers retrieved to fill the drawable info */
494
495    memset(&templ, 0, sizeof(templ));
496    templ.target = screen->target;
497    templ.last_level = 0;
498    templ.depth0 = 1;
499    templ.array_size = 1;
500
501    if (image) {
502       if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
503          struct pipe_resource **buf =
504             &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
505          struct pipe_resource *texture = images.front->texture;
506
507          dri_drawable->w = texture->width0;
508          dri_drawable->h = texture->height0;
509
510          pipe_resource_reference(buf, texture);
511       }
512
513       if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
514          struct pipe_resource **buf =
515             &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
516          struct pipe_resource *texture = images.back->texture;
517
518          dri_drawable->w = texture->width0;
519          dri_drawable->h = texture->height0;
520
521          pipe_resource_reference(buf, texture);
522       }
523
524       /* Note: if there is both a back and a front buffer,
525        * then they have the same size.
526        */
527       templ.width0 = dri_drawable->w;
528       templ.height0 = dri_drawable->h;
529    }
530    else {
531       memset(&whandle, 0, sizeof(whandle));
532
533       /* Process DRI-provided buffers and get pipe_resources. */
534       for (i = 0; i < num_buffers; i++) {
535          __DRIbuffer *buf = &buffers[i];
536          enum st_attachment_type statt;
537          enum pipe_format format;
538
539          switch (buf->attachment) {
540          case __DRI_BUFFER_FRONT_LEFT:
541             if (!screen->auto_fake_front) {
542                continue; /* invalid attachment */
543             }
544             /* fallthrough */
545          case __DRI_BUFFER_FAKE_FRONT_LEFT:
546             statt = ST_ATTACHMENT_FRONT_LEFT;
547             break;
548          case __DRI_BUFFER_BACK_LEFT:
549             statt = ST_ATTACHMENT_BACK_LEFT;
550             break;
551          default:
552             continue; /* invalid attachment */
553          }
554
555          dri_drawable_get_format(drawable, statt, &format, &bind);
556          if (format == PIPE_FORMAT_NONE)
557             continue;
558
559          /* dri2_drawable_get_buffers has already filled dri_drawable->w
560           * and dri_drawable->h */
561          templ.width0 = dri_drawable->w;
562          templ.height0 = dri_drawable->h;
563          templ.format = format;
564          templ.bind = bind;
565          whandle.handle = buf->name;
566          whandle.stride = buf->pitch;
567          whandle.offset = 0;
568          if (screen->can_share_buffer)
569             whandle.type = DRM_API_HANDLE_TYPE_SHARED;
570          else
571             whandle.type = DRM_API_HANDLE_TYPE_KMS;
572          drawable->textures[statt] =
573             screen->base.screen->resource_from_handle(screen->base.screen,
574                   &templ, &whandle,
575                   PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ);
576          assert(drawable->textures[statt]);
577       }
578    }
579
580    /* Allocate private MSAA colorbuffers. */
581    if (drawable->stvis.samples > 1) {
582       for (i = 0; i < statts_count; i++) {
583          enum st_attachment_type statt = statts[i];
584
585          if (statt == ST_ATTACHMENT_DEPTH_STENCIL)
586             continue;
587
588          if (drawable->textures[statt]) {
589             templ.format = drawable->textures[statt]->format;
590             templ.bind = drawable->textures[statt]->bind & ~PIPE_BIND_SCANOUT;
591             templ.nr_samples = drawable->stvis.samples;
592
593             /* Try to reuse the resource.
594              * (the other resource parameters should be constant)
595              */
596             if (!drawable->msaa_textures[statt] ||
597                 drawable->msaa_textures[statt]->width0 != templ.width0 ||
598                 drawable->msaa_textures[statt]->height0 != templ.height0) {
599                /* Allocate a new one. */
600                pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
601
602                drawable->msaa_textures[statt] =
603                   screen->base.screen->resource_create(screen->base.screen,
604                                                        &templ);
605                assert(drawable->msaa_textures[statt]);
606
607                /* If there are any MSAA resources, we should initialize them
608                 * such that they contain the same data as the single-sample
609                 * resources we just got from the X server.
610                 *
611                 * The reason for this is that the state tracker (and
612                 * therefore the app) can access the MSAA resources only.
613                 * The single-sample resources are not exposed
614                 * to the state tracker.
615                 *
616                 */
617                dri_pipe_blit(ctx->st->pipe,
618                              drawable->msaa_textures[statt],
619                              drawable->textures[statt]);
620             }
621          }
622          else {
623             pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
624          }
625       }
626    }
627
628    /* Allocate a private depth-stencil buffer. */
629    if (alloc_depthstencil) {
630       enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;
631       struct pipe_resource **zsbuf;
632       enum pipe_format format;
633       unsigned bind;
634
635       dri_drawable_get_format(drawable, statt, &format, &bind);
636
637       if (format) {
638          templ.format = format;
639          templ.bind = bind;
640
641          if (drawable->stvis.samples > 1) {
642             templ.nr_samples = drawable->stvis.samples;
643             zsbuf = &drawable->msaa_textures[statt];
644          }
645          else {
646             templ.nr_samples = 0;
647             zsbuf = &drawable->textures[statt];
648          }
649
650          /* Try to reuse the resource.
651           * (the other resource parameters should be constant)
652           */
653          if (!*zsbuf ||
654              (*zsbuf)->width0 != templ.width0 ||
655              (*zsbuf)->height0 != templ.height0) {
656             /* Allocate a new one. */
657             pipe_resource_reference(zsbuf, NULL);
658             *zsbuf = screen->base.screen->resource_create(screen->base.screen,
659                                                           &templ);
660             assert(*zsbuf);
661          }
662       }
663       else {
664          pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
665          pipe_resource_reference(&drawable->textures[statt], NULL);
666       }
667    }
668
669    /* For DRI2, we may get the same buffers again from the server.
670     * To prevent useless imports of gem names, drawable->old* is used
671     * to bypass the import if we get the same buffers. This doesn't apply
672     * to DRI3/Wayland, users of image.loader, since the buffer is managed
673     * by the client (no import), and the back buffer is going to change
674     * at every redraw.
675     */
676    if (!image) {
677       drawable->old_num = num_buffers;
678       drawable->old_w = dri_drawable->w;
679       drawable->old_h = dri_drawable->h;
680       memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);
681    }
682 }
683
684 static void
685 dri2_flush_frontbuffer(struct dri_context *ctx,
686                        struct dri_drawable *drawable,
687                        enum st_attachment_type statt)
688 {
689    __DRIdrawable *dri_drawable = drawable->dPriv;
690    const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
691    const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
692    struct pipe_context *pipe = ctx->st->pipe;
693
694    if (statt != ST_ATTACHMENT_FRONT_LEFT)
695       return;
696
697    if (drawable->stvis.samples > 1) {
698       /* Resolve the front buffer. */
699       dri_pipe_blit(ctx->st->pipe,
700                     drawable->textures[ST_ATTACHMENT_FRONT_LEFT],
701                     drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]);
702    }
703
704    if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) {
705       pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]);
706    }
707
708    pipe->flush(pipe, NULL, 0);
709
710    if (image) {
711       image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
712    }
713    else if (loader->flushFrontBuffer) {
714       loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
715    }
716 }
717
718 static void
719 dri2_update_tex_buffer(struct dri_drawable *drawable,
720                        struct dri_context *ctx,
721                        struct pipe_resource *res)
722 {
723    /* no-op */
724 }
725
726 static __DRIimage *
727 dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
728 {
729    const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
730    __DRIimage *img;
731
732    if (!loader->lookupEGLImage)
733       return NULL;
734
735    img = loader->lookupEGLImage(screen->sPriv,
736                                 handle, screen->sPriv->loaderPrivate);
737
738    return img;
739 }
740
741 static __DRIimage *
742 dri2_create_image_from_winsys(__DRIscreen *_screen,
743                               int width, int height, int format,
744                               struct winsys_handle *whandle,
745                               void *loaderPrivate)
746 {
747    struct dri_screen *screen = dri_screen(_screen);
748    __DRIimage *img;
749    struct pipe_resource templ;
750    unsigned tex_usage;
751    enum pipe_format pf;
752
753    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
754
755    pf = dri2_format_to_pipe_format (format);
756    if (pf == PIPE_FORMAT_NONE)
757       return NULL;
758
759    img = CALLOC_STRUCT(__DRIimageRec);
760    if (!img)
761       return NULL;
762
763    memset(&templ, 0, sizeof(templ));
764    templ.bind = tex_usage;
765    templ.format = pf;
766    templ.target = screen->target;
767    templ.last_level = 0;
768    templ.width0 = width;
769    templ.height0 = height;
770    templ.depth0 = 1;
771    templ.array_size = 1;
772
773    whandle->offset = 0;
774
775    img->texture = screen->base.screen->resource_from_handle(screen->base.screen,
776          &templ, whandle, PIPE_HANDLE_USAGE_READ_WRITE);
777    if (!img->texture) {
778       FREE(img);
779       return NULL;
780    }
781
782    img->level = 0;
783    img->layer = 0;
784    img->dri_format = format;
785    img->use = 0;
786    img->loader_private = loaderPrivate;
787
788    return img;
789 }
790
791 static __DRIimage *
792 dri2_create_image_from_name(__DRIscreen *_screen,
793                             int width, int height, int format,
794                             int name, int pitch, void *loaderPrivate)
795 {
796    struct winsys_handle whandle;
797    enum pipe_format pf;
798
799    memset(&whandle, 0, sizeof(whandle));
800    whandle.type = DRM_API_HANDLE_TYPE_SHARED;
801    whandle.handle = name;
802
803    pf = dri2_format_to_pipe_format (format);
804    if (pf == PIPE_FORMAT_NONE)
805       return NULL;
806
807    whandle.stride = pitch * util_format_get_blocksize(pf);
808
809    return dri2_create_image_from_winsys(_screen, width, height, format,
810                                         &whandle, loaderPrivate);
811 }
812
813 static __DRIimage *
814 dri2_create_image_from_fd(__DRIscreen *_screen,
815                           int width, int height, int format,
816                           int fd, int stride, void *loaderPrivate)
817 {
818    struct winsys_handle whandle;
819
820    if (fd < 0)
821       return NULL;
822
823    memset(&whandle, 0, sizeof(whandle));
824    whandle.type = DRM_API_HANDLE_TYPE_FD;
825    whandle.handle = (unsigned)fd;
826    whandle.stride = stride;
827
828    return dri2_create_image_from_winsys(_screen, width, height, format,
829                                         &whandle, loaderPrivate);
830 }
831
832 static __DRIimage *
833 dri2_create_image_from_renderbuffer(__DRIcontext *context,
834                                     int renderbuffer, void *loaderPrivate)
835 {
836    struct dri_context *ctx = dri_context(context);
837
838    if (!ctx->st->get_resource_for_egl_image)
839       return NULL;
840
841    /* TODO */
842    return NULL;
843 }
844
845 static __DRIimage *
846 dri2_create_image(__DRIscreen *_screen,
847                    int width, int height, int format,
848                    unsigned int use, void *loaderPrivate)
849 {
850    struct dri_screen *screen = dri_screen(_screen);
851    __DRIimage *img;
852    struct pipe_resource templ;
853    unsigned tex_usage;
854    enum pipe_format pf;
855
856    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
857    if (use & __DRI_IMAGE_USE_SCANOUT)
858       tex_usage |= PIPE_BIND_SCANOUT;
859    if (use & __DRI_IMAGE_USE_SHARE)
860       tex_usage |= PIPE_BIND_SHARED;
861    if (use & __DRI_IMAGE_USE_LINEAR)
862       tex_usage |= PIPE_BIND_LINEAR;
863    if (use & __DRI_IMAGE_USE_CURSOR) {
864       if (width != 64 || height != 64)
865          return NULL;
866       tex_usage |= PIPE_BIND_CURSOR;
867    }
868
869    pf = dri2_format_to_pipe_format (format);
870    if (pf == PIPE_FORMAT_NONE)
871       return NULL;
872
873    img = CALLOC_STRUCT(__DRIimageRec);
874    if (!img)
875       return NULL;
876
877    memset(&templ, 0, sizeof(templ));
878    templ.bind = tex_usage;
879    templ.format = pf;
880    templ.target = PIPE_TEXTURE_2D;
881    templ.last_level = 0;
882    templ.width0 = width;
883    templ.height0 = height;
884    templ.depth0 = 1;
885    templ.array_size = 1;
886
887    img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
888    if (!img->texture) {
889       FREE(img);
890       return NULL;
891    }
892
893    img->level = 0;
894    img->layer = 0;
895    img->dri_format = format;
896    img->dri_components = 0;
897    img->use = use;
898
899    img->loader_private = loaderPrivate;
900    return img;
901 }
902
903 static GLboolean
904 dri2_query_image(__DRIimage *image, int attrib, int *value)
905 {
906    struct winsys_handle whandle;
907    unsigned usage;
908
909    if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
910       usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
911    else
912       usage = PIPE_HANDLE_USAGE_READ_WRITE;
913
914    memset(&whandle, 0, sizeof(whandle));
915
916    switch (attrib) {
917    case __DRI_IMAGE_ATTRIB_STRIDE:
918       whandle.type = DRM_API_HANDLE_TYPE_KMS;
919       image->texture->screen->resource_get_handle(image->texture->screen,
920             image->texture, &whandle, usage);
921       *value = whandle.stride;
922       return GL_TRUE;
923    case __DRI_IMAGE_ATTRIB_HANDLE:
924       whandle.type = DRM_API_HANDLE_TYPE_KMS;
925       image->texture->screen->resource_get_handle(image->texture->screen,
926          image->texture, &whandle, usage);
927       *value = whandle.handle;
928       return GL_TRUE;
929    case __DRI_IMAGE_ATTRIB_NAME:
930       whandle.type = DRM_API_HANDLE_TYPE_SHARED;
931       image->texture->screen->resource_get_handle(image->texture->screen,
932          image->texture, &whandle, usage);
933       *value = whandle.handle;
934       return GL_TRUE;
935    case __DRI_IMAGE_ATTRIB_FD:
936       whandle.type= DRM_API_HANDLE_TYPE_FD;
937       image->texture->screen->resource_get_handle(image->texture->screen,
938          image->texture, &whandle, usage);
939       *value = whandle.handle;
940       return GL_TRUE;
941    case __DRI_IMAGE_ATTRIB_FORMAT:
942       *value = image->dri_format;
943       return GL_TRUE;
944    case __DRI_IMAGE_ATTRIB_WIDTH:
945       *value = image->texture->width0;
946       return GL_TRUE;
947    case __DRI_IMAGE_ATTRIB_HEIGHT:
948       *value = image->texture->height0;
949       return GL_TRUE;
950    case __DRI_IMAGE_ATTRIB_COMPONENTS:
951       if (image->dri_components == 0)
952          return GL_FALSE;
953       *value = image->dri_components;
954       return GL_TRUE;
955    case __DRI_IMAGE_ATTRIB_FOURCC:
956       *value = convert_to_fourcc(image->dri_format);
957       return GL_TRUE;
958    case __DRI_IMAGE_ATTRIB_NUM_PLANES:
959       *value = 1;
960       return GL_TRUE;
961    default:
962       return GL_FALSE;
963    }
964 }
965
966 static __DRIimage *
967 dri2_dup_image(__DRIimage *image, void *loaderPrivate)
968 {
969    __DRIimage *img;
970
971    img = CALLOC_STRUCT(__DRIimageRec);
972    if (!img)
973       return NULL;
974
975    img->texture = NULL;
976    pipe_resource_reference(&img->texture, image->texture);
977    img->level = image->level;
978    img->layer = image->layer;
979    img->dri_format = image->dri_format;
980    /* This should be 0 for sub images, but dup is also used for base images. */
981    img->dri_components = image->dri_components;
982    img->loader_private = loaderPrivate;
983
984    return img;
985 }
986
987 static GLboolean
988 dri2_validate_usage(__DRIimage *image, unsigned int use)
989 {
990    /*
991     * Gallium drivers are bad at adding usages to the resources
992     * once opened again in another process, which is the main use
993     * case for this, so we have to lie.
994     */
995    if (image != NULL)
996       return GL_TRUE;
997    else
998       return GL_FALSE;
999 }
1000
1001 static __DRIimage *
1002 dri2_from_names(__DRIscreen *screen, int width, int height, int format,
1003                 int *names, int num_names, int *strides, int *offsets,
1004                 void *loaderPrivate)
1005 {
1006    __DRIimage *img;
1007    int dri_components;
1008    struct winsys_handle whandle;
1009
1010    if (num_names != 1)
1011       return NULL;
1012    if (offsets[0] != 0)
1013       return NULL;
1014
1015    format = convert_fourcc(format, &dri_components);
1016    if (format == -1)
1017       return NULL;
1018
1019    memset(&whandle, 0, sizeof(whandle));
1020    whandle.type = DRM_API_HANDLE_TYPE_SHARED;
1021    whandle.handle = names[0];
1022    whandle.stride = strides[0];
1023
1024    img = dri2_create_image_from_winsys(screen, width, height, format,
1025                                        &whandle, loaderPrivate);
1026    if (img == NULL)
1027       return NULL;
1028
1029    img->dri_components = dri_components;
1030    return img;
1031 }
1032
1033 static __DRIimage *
1034 dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
1035 {
1036    __DRIimage *img;
1037
1038    if (plane != 0)
1039       return NULL;
1040
1041    if (image->dri_components == 0)
1042       return NULL;
1043
1044    img = dri2_dup_image(image, loaderPrivate);
1045    if (img == NULL)
1046       return NULL;
1047
1048    /* set this to 0 for sub images. */
1049    img->dri_components = 0;
1050    return img;
1051 }
1052
1053 static __DRIimage *
1054 dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
1055                          int depth, int level, unsigned *error,
1056                          void *loaderPrivate)
1057 {
1058    __DRIimage *img;
1059    struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
1060    struct gl_texture_object *obj;
1061    struct pipe_resource *tex;
1062    GLuint face = 0;
1063
1064    obj = _mesa_lookup_texture(ctx, texture);
1065    if (!obj || obj->Target != target) {
1066       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1067       return NULL;
1068    }
1069
1070    tex = st_get_texobj_resource(obj);
1071    if (!tex) {
1072       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1073       return NULL;
1074    }
1075
1076    if (target == GL_TEXTURE_CUBE_MAP)
1077       face = depth;
1078
1079    _mesa_test_texobj_completeness(ctx, obj);
1080    if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
1081       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1082       return NULL;
1083    }
1084
1085    if (level < obj->BaseLevel || level > obj->_MaxLevel) {
1086       *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1087       return NULL;
1088    }
1089
1090    if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
1091       *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1092       return NULL;
1093    }
1094
1095    img = CALLOC_STRUCT(__DRIimageRec);
1096    if (!img) {
1097       *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
1098       return NULL;
1099    }
1100
1101    img->level = level;
1102    img->layer = depth;
1103    img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
1104
1105    img->loader_private = loaderPrivate;
1106
1107    if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
1108       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1109       free(img);
1110       return NULL;
1111    }
1112
1113    pipe_resource_reference(&img->texture, tex);
1114
1115    *error = __DRI_IMAGE_ERROR_SUCCESS;
1116    return img;
1117 }
1118
1119 static __DRIimage *
1120 dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
1121               int *fds, int num_fds, int *strides, int *offsets,
1122               void *loaderPrivate)
1123 {
1124    __DRIimage *img;
1125    int format, dri_components;
1126
1127    if (num_fds != 1)
1128       return NULL;
1129    if (offsets[0] != 0)
1130       return NULL;
1131
1132    format = convert_fourcc(fourcc, &dri_components);
1133    if (format == -1)
1134       return NULL;
1135
1136    img = dri2_create_image_from_fd(screen, width, height, format,
1137                                    fds[0], strides[0], loaderPrivate);
1138    if (img == NULL)
1139       return NULL;
1140
1141    img->dri_components = dri_components;
1142    return img;
1143 }
1144
1145 static __DRIimage *
1146 dri2_from_dma_bufs(__DRIscreen *screen,
1147                    int width, int height, int fourcc,
1148                    int *fds, int num_fds,
1149                    int *strides, int *offsets,
1150                    enum __DRIYUVColorSpace yuv_color_space,
1151                    enum __DRISampleRange sample_range,
1152                    enum __DRIChromaSiting horizontal_siting,
1153                    enum __DRIChromaSiting vertical_siting,
1154                    unsigned *error,
1155                    void *loaderPrivate)
1156 {
1157    __DRIimage *img;
1158    int format, dri_components;
1159
1160    if (num_fds != 1 || offsets[0] != 0) {
1161       *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1162       return NULL;
1163    }
1164
1165    format = convert_fourcc(fourcc, &dri_components);
1166    if (format == -1) {
1167       *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1168       return NULL;
1169    }
1170
1171    img = dri2_create_image_from_fd(screen, width, height, format,
1172                                    fds[0], strides[0], loaderPrivate);
1173    if (img == NULL) {
1174       *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
1175       return NULL;
1176    }
1177
1178    img->yuv_color_space = yuv_color_space;
1179    img->sample_range = sample_range;
1180    img->horizontal_siting = horizontal_siting;
1181    img->vertical_siting = vertical_siting;
1182    img->dri_components = dri_components;
1183
1184    *error = __DRI_IMAGE_ERROR_SUCCESS;
1185    return img;
1186 }
1187
1188 static void
1189 dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
1190                 int dstx0, int dsty0, int dstwidth, int dstheight,
1191                 int srcx0, int srcy0, int srcwidth, int srcheight,
1192                 int flush_flag)
1193 {
1194    struct dri_context *ctx = dri_context(context);
1195    struct pipe_context *pipe = ctx->st->pipe;
1196    struct pipe_screen *screen;
1197    struct pipe_fence_handle *fence;
1198    struct pipe_blit_info blit;
1199
1200    if (!dst || !src)
1201       return;
1202
1203    memset(&blit, 0, sizeof(blit));
1204    blit.dst.resource = dst->texture;
1205    blit.dst.box.x = dstx0;
1206    blit.dst.box.y = dsty0;
1207    blit.dst.box.width = dstwidth;
1208    blit.dst.box.height = dstheight;
1209    blit.dst.box.depth = 1;
1210    blit.dst.format = dst->texture->format;
1211    blit.src.resource = src->texture;
1212    blit.src.box.x = srcx0;
1213    blit.src.box.y = srcy0;
1214    blit.src.box.width = srcwidth;
1215    blit.src.box.height = srcheight;
1216    blit.src.box.depth = 1;
1217    blit.src.format = src->texture->format;
1218    blit.mask = PIPE_MASK_RGBA;
1219    blit.filter = PIPE_TEX_FILTER_NEAREST;
1220
1221    pipe->blit(pipe, &blit);
1222
1223    if (flush_flag == __BLIT_FLAG_FLUSH) {
1224       pipe->flush_resource(pipe, dst->texture);
1225       ctx->st->flush(ctx->st, 0, NULL);
1226    } else if (flush_flag == __BLIT_FLAG_FINISH) {
1227       screen = dri_screen(ctx->sPriv)->base.screen;
1228       pipe->flush_resource(pipe, dst->texture);
1229       ctx->st->flush(ctx->st, 0, &fence);
1230       (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
1231       screen->fence_reference(screen, &fence, NULL);
1232    }
1233 }
1234
1235 static void *
1236 dri2_map_image(__DRIcontext *context, __DRIimage *image,
1237                 int x0, int y0, int width, int height,
1238                 unsigned int flags, int *stride, void **data)
1239 {
1240    struct dri_context *ctx = dri_context(context);
1241    struct pipe_context *pipe = ctx->st->pipe;
1242    enum pipe_transfer_usage pipe_access = 0;
1243    struct pipe_transfer *trans;
1244    void *map;
1245
1246    if (!image || !data || *data)
1247       return NULL;
1248
1249    if (flags & __DRI_IMAGE_TRANSFER_READ)
1250          pipe_access |= PIPE_TRANSFER_READ;
1251    if (flags & __DRI_IMAGE_TRANSFER_WRITE)
1252          pipe_access |= PIPE_TRANSFER_WRITE;
1253
1254    map = pipe_transfer_map(pipe, image->texture,
1255                            0, 0, pipe_access, x0, y0, width, height,
1256                            &trans);
1257    if (map) {
1258       *data = trans;
1259       *stride = trans->stride;
1260    }
1261
1262    return map;
1263 }
1264
1265 static void
1266 dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
1267 {
1268    struct dri_context *ctx = dri_context(context);
1269    struct pipe_context *pipe = ctx->st->pipe;
1270
1271    pipe_transfer_unmap(pipe, (struct pipe_transfer *)data);
1272 }
1273
1274 static void
1275 dri2_destroy_image(__DRIimage *img)
1276 {
1277    pipe_resource_reference(&img->texture, NULL);
1278    FREE(img);
1279 }
1280
1281 static int
1282 dri2_get_capabilities(__DRIscreen *_screen)
1283 {
1284    struct dri_screen *screen = dri_screen(_screen);
1285
1286    return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
1287 }
1288
1289 /* The extension is modified during runtime if DRI_PRIME is detected */
1290 static __DRIimageExtension dri2ImageExtension = {
1291     .base = { __DRI_IMAGE, 12 },
1292
1293     .createImageFromName          = dri2_create_image_from_name,
1294     .createImageFromRenderbuffer  = dri2_create_image_from_renderbuffer,
1295     .destroyImage                 = dri2_destroy_image,
1296     .createImage                  = dri2_create_image,
1297     .queryImage                   = dri2_query_image,
1298     .dupImage                     = dri2_dup_image,
1299     .validateUsage                = dri2_validate_usage,
1300     .createImageFromNames         = dri2_from_names,
1301     .fromPlanar                   = dri2_from_planar,
1302     .createImageFromTexture       = dri2_create_from_texture,
1303     .createImageFromFds           = NULL,
1304     .createImageFromDmaBufs       = NULL,
1305     .blitImage                    = dri2_blit_image,
1306     .getCapabilities              = dri2_get_capabilities,
1307     .mapImage                     = dri2_map_image,
1308     .unmapImage                   = dri2_unmap_image,
1309 };
1310
1311
1312 static bool
1313 dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen)
1314 {
1315    return screen->opencl_dri_event_add_ref &&
1316           screen->opencl_dri_event_release &&
1317           screen->opencl_dri_event_wait &&
1318           screen->opencl_dri_event_get_fence;
1319 }
1320
1321 static bool
1322 dri2_load_opencl_interop(struct dri_screen *screen)
1323 {
1324 #if defined(RTLD_DEFAULT)
1325    bool success;
1326
1327    pipe_mutex_lock(screen->opencl_func_mutex);
1328
1329    if (dri2_is_opencl_interop_loaded_locked(screen)) {
1330       pipe_mutex_unlock(screen->opencl_func_mutex);
1331       return true;
1332    }
1333
1334    screen->opencl_dri_event_add_ref =
1335       dlsym(RTLD_DEFAULT, "opencl_dri_event_add_ref");
1336    screen->opencl_dri_event_release =
1337       dlsym(RTLD_DEFAULT, "opencl_dri_event_release");
1338    screen->opencl_dri_event_wait =
1339       dlsym(RTLD_DEFAULT, "opencl_dri_event_wait");
1340    screen->opencl_dri_event_get_fence =
1341       dlsym(RTLD_DEFAULT, "opencl_dri_event_get_fence");
1342
1343    success = dri2_is_opencl_interop_loaded_locked(screen);
1344    pipe_mutex_unlock(screen->opencl_func_mutex);
1345    return success;
1346 #else
1347    return false;
1348 #endif
1349 }
1350
1351 struct dri2_fence {
1352    struct dri_screen *driscreen;
1353    struct pipe_fence_handle *pipe_fence;
1354    void *cl_event;
1355 };
1356
1357 static void *
1358 dri2_create_fence(__DRIcontext *_ctx)
1359 {
1360    struct pipe_context *ctx = dri_context(_ctx)->st->pipe;
1361    struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence);
1362
1363    if (!fence)
1364       return NULL;
1365
1366    ctx->flush(ctx, &fence->pipe_fence, 0);
1367
1368    if (!fence->pipe_fence) {
1369       FREE(fence);
1370       return NULL;
1371    }
1372
1373    fence->driscreen = dri_screen(_ctx->driScreenPriv);
1374    return fence;
1375 }
1376
1377 static void *
1378 dri2_get_fence_from_cl_event(__DRIscreen *_screen, intptr_t cl_event)
1379 {
1380    struct dri_screen *driscreen = dri_screen(_screen);
1381    struct dri2_fence *fence;
1382
1383    if (!dri2_load_opencl_interop(driscreen))
1384       return NULL;
1385
1386    fence = CALLOC_STRUCT(dri2_fence);
1387    if (!fence)
1388       return NULL;
1389
1390    fence->cl_event = (void*)cl_event;
1391
1392    if (!driscreen->opencl_dri_event_add_ref(fence->cl_event)) {
1393       free(fence);
1394       return NULL;
1395    }
1396
1397    fence->driscreen = driscreen;
1398    return fence;
1399 }
1400
1401 static void
1402 dri2_destroy_fence(__DRIscreen *_screen, void *_fence)
1403 {
1404    struct dri_screen *driscreen = dri_screen(_screen);
1405    struct pipe_screen *screen = driscreen->base.screen;
1406    struct dri2_fence *fence = (struct dri2_fence*)_fence;
1407
1408    if (fence->pipe_fence)
1409       screen->fence_reference(screen, &fence->pipe_fence, NULL);
1410    else if (fence->cl_event)
1411       driscreen->opencl_dri_event_release(fence->cl_event);
1412    else
1413       assert(0);
1414
1415    FREE(fence);
1416 }
1417
1418 static GLboolean
1419 dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags,
1420                       uint64_t timeout)
1421 {
1422    struct dri2_fence *fence = (struct dri2_fence*)_fence;
1423    struct dri_screen *driscreen = fence->driscreen;
1424    struct pipe_screen *screen = driscreen->base.screen;
1425
1426    /* No need to flush. The context was flushed when the fence was created. */
1427
1428    if (fence->pipe_fence)
1429       return screen->fence_finish(screen, fence->pipe_fence, timeout);
1430    else if (fence->cl_event) {
1431       struct pipe_fence_handle *pipe_fence =
1432          driscreen->opencl_dri_event_get_fence(fence->cl_event);
1433
1434       if (pipe_fence)
1435          return screen->fence_finish(screen, pipe_fence, timeout);
1436       else
1437          return driscreen->opencl_dri_event_wait(fence->cl_event, timeout);
1438    }
1439    else {
1440       assert(0);
1441       return false;
1442    }
1443 }
1444
1445 static void
1446 dri2_server_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags)
1447 {
1448    /* AFAIK, no driver currently supports parallel context execution. */
1449 }
1450
1451 static __DRI2fenceExtension dri2FenceExtension = {
1452    .base = { __DRI2_FENCE, 1 },
1453
1454    .create_fence = dri2_create_fence,
1455    .get_fence_from_cl_event = dri2_get_fence_from_cl_event,
1456    .destroy_fence = dri2_destroy_fence,
1457    .client_wait_sync = dri2_client_wait_sync,
1458    .server_wait_sync = dri2_server_wait_sync
1459 };
1460
1461 static const __DRIrobustnessExtension dri2Robustness = {
1462    .base = { __DRI2_ROBUSTNESS, 1 }
1463 };
1464
1465 static int
1466 dri2_interop_query_device_info(__DRIcontext *_ctx,
1467                                mesa_glinterop_device_info *out)
1468 {
1469    struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen;
1470
1471    /* There is no version 0, thus we do not support it */
1472    if (out->version == 0)
1473       return MESA_GLINTEROP_INVALID_VERSION;
1474
1475    out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP);
1476    out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS);
1477    out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE);
1478    out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION);
1479
1480    out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID);
1481    out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID);
1482
1483    out->interop_version = 1;
1484
1485    return MESA_GLINTEROP_SUCCESS;
1486 }
1487
1488 static int
1489 dri2_interop_export_object(__DRIcontext *_ctx,
1490                            const mesa_glinterop_export_in *in,
1491                            mesa_glinterop_export_out *out)
1492 {
1493    struct st_context_iface *st = dri_context(_ctx)->st;
1494    struct pipe_screen *screen = st->pipe->screen;
1495    struct gl_context *ctx = ((struct st_context *)st)->ctx;
1496    struct pipe_resource *res = NULL;
1497    struct winsys_handle whandle;
1498    unsigned target, usage;
1499    boolean success;
1500
1501    /* There is no version 0, thus we do not support it */
1502    if (in->version == 0 || out->version == 0)
1503       return MESA_GLINTEROP_INVALID_VERSION;
1504
1505    /* Validate the target. */
1506    switch (in->target) {
1507    case GL_TEXTURE_BUFFER:
1508    case GL_TEXTURE_1D:
1509    case GL_TEXTURE_2D:
1510    case GL_TEXTURE_3D:
1511    case GL_TEXTURE_RECTANGLE:
1512    case GL_TEXTURE_1D_ARRAY:
1513    case GL_TEXTURE_2D_ARRAY:
1514    case GL_TEXTURE_CUBE_MAP_ARRAY:
1515    case GL_TEXTURE_CUBE_MAP:
1516    case GL_TEXTURE_2D_MULTISAMPLE:
1517    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1518    case GL_TEXTURE_EXTERNAL_OES:
1519    case GL_RENDERBUFFER:
1520    case GL_ARRAY_BUFFER:
1521       target = in->target;
1522       break;
1523    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1524    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1525    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1526    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1527    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1528    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1529       target = GL_TEXTURE_CUBE_MAP;
1530       break;
1531    default:
1532       return MESA_GLINTEROP_INVALID_TARGET;
1533    }
1534
1535    /* Validate the simple case of miplevel. */
1536    if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) &&
1537        in->miplevel != 0)
1538       return MESA_GLINTEROP_INVALID_MIP_LEVEL;
1539
1540    /* Validate the OpenGL object and get pipe_resource. */
1541    mtx_lock(&ctx->Shared->Mutex);
1542
1543    if (target == GL_ARRAY_BUFFER) {
1544       /* Buffer objects.
1545        *
1546        * The error checking is based on the documentation of
1547        * clCreateFromGLBuffer from OpenCL 2.0 SDK.
1548        */
1549       struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj);
1550
1551       /* From OpenCL 2.0 SDK, clCreateFromGLBuffer:
1552        *  "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is
1553        *   a GL buffer object but does not have an existing data store or
1554        *   the size of the buffer is 0."
1555        */
1556       if (!buf || buf->Size == 0) {
1557          mtx_unlock(&ctx->Shared->Mutex);
1558          return MESA_GLINTEROP_INVALID_OBJECT;
1559       }
1560
1561       res = st_buffer_object(buf)->buffer;
1562       if (!res) {
1563          /* this shouldn't happen */
1564          mtx_unlock(&ctx->Shared->Mutex);
1565          return MESA_GLINTEROP_INVALID_OBJECT;
1566       }
1567
1568       out->buf_offset = 0;
1569       out->buf_size = buf->Size;
1570
1571       buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
1572    } else if (target == GL_RENDERBUFFER) {
1573       /* Renderbuffers.
1574        *
1575        * The error checking is based on the documentation of
1576        * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK.
1577        */
1578       struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj);
1579
1580       /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1581        *   "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer
1582        *    object or if the width or height of renderbuffer is zero."
1583        */
1584       if (!rb || rb->Width == 0 || rb->Height == 0) {
1585          mtx_unlock(&ctx->Shared->Mutex);
1586          return MESA_GLINTEROP_INVALID_OBJECT;
1587       }
1588
1589       /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1590        *   "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL
1591        *    renderbuffer object."
1592        */
1593       if (rb->NumSamples > 1) {
1594          mtx_unlock(&ctx->Shared->Mutex);
1595          return MESA_GLINTEROP_INVALID_OPERATION;
1596       }
1597
1598       /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1599        *   "CL_OUT_OF_RESOURCES if there is a failure to allocate resources
1600        *    required by the OpenCL implementation on the device."
1601        */
1602       res = st_renderbuffer(rb)->texture;
1603       if (!res) {
1604          mtx_unlock(&ctx->Shared->Mutex);
1605          return MESA_GLINTEROP_OUT_OF_RESOURCES;
1606       }
1607
1608       out->internal_format = rb->InternalFormat;
1609       out->view_minlevel = 0;
1610       out->view_numlevels = 1;
1611       out->view_minlayer = 0;
1612       out->view_numlayers = 1;
1613    } else {
1614       /* Texture objects.
1615        *
1616        * The error checking is based on the documentation of
1617        * clCreateFromGLTexture from OpenCL 2.0 SDK.
1618        */
1619       struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj);
1620
1621       if (obj)
1622          _mesa_test_texobj_completeness(ctx, obj);
1623
1624       /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
1625        *   "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose
1626        *    type matches texture_target, if the specified miplevel of texture
1627        *    is not defined, or if the width or height of the specified
1628        *    miplevel is zero or if the GL texture object is incomplete."
1629        */
1630       if (!obj ||
1631           obj->Target != target ||
1632           !obj->_BaseComplete ||
1633           (in->miplevel > 0 && !obj->_MipmapComplete)) {
1634          mtx_unlock(&ctx->Shared->Mutex);
1635          return MESA_GLINTEROP_INVALID_OBJECT;
1636       }
1637
1638       /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
1639        *   "CL_INVALID_MIP_LEVEL if miplevel is less than the value of
1640        *    levelbase (for OpenGL implementations) or zero (for OpenGL ES
1641        *    implementations); or greater than the value of q (for both OpenGL
1642        *    and OpenGL ES). levelbase and q are defined for the texture in
1643        *    section 3.8.10 (Texture Completeness) of the OpenGL 2.1
1644        *    specification and section 3.7.10 of the OpenGL ES 2.0."
1645        */
1646       if (in->miplevel < obj->BaseLevel || in->miplevel > obj->_MaxLevel) {
1647          mtx_unlock(&ctx->Shared->Mutex);
1648          return MESA_GLINTEROP_INVALID_MIP_LEVEL;
1649       }
1650
1651       if (!st_finalize_texture(ctx, st->pipe, obj)) {
1652          mtx_unlock(&ctx->Shared->Mutex);
1653          return MESA_GLINTEROP_OUT_OF_RESOURCES;
1654       }
1655
1656       res = st_get_texobj_resource(obj);
1657       if (!res) {
1658          /* Incomplete texture buffer object? This shouldn't really occur. */
1659          mtx_unlock(&ctx->Shared->Mutex);
1660          return MESA_GLINTEROP_INVALID_OBJECT;
1661       }
1662
1663       if (target == GL_TEXTURE_BUFFER) {
1664          out->internal_format = obj->BufferObjectFormat;
1665          out->buf_offset = obj->BufferOffset;
1666          out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size :
1667                                                  obj->BufferSize;
1668
1669          obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
1670       } else {
1671          out->internal_format = obj->Image[0][0]->InternalFormat;
1672          out->view_minlevel = obj->MinLevel;
1673          out->view_numlevels = obj->NumLevels;
1674          out->view_minlayer = obj->MinLayer;
1675          out->view_numlayers = obj->NumLayers;
1676       }
1677    }
1678
1679    /* Get the handle. */
1680    switch (in->access) {
1681    case MESA_GLINTEROP_ACCESS_READ_WRITE:
1682       usage = PIPE_HANDLE_USAGE_READ_WRITE;
1683       break;
1684    case MESA_GLINTEROP_ACCESS_READ_ONLY:
1685       usage = PIPE_HANDLE_USAGE_READ;
1686       break;
1687    case MESA_GLINTEROP_ACCESS_WRITE_ONLY:
1688       usage = PIPE_HANDLE_USAGE_WRITE;
1689       break;
1690    default:
1691       usage = 0;
1692    }
1693
1694    memset(&whandle, 0, sizeof(whandle));
1695    whandle.type = DRM_API_HANDLE_TYPE_FD;
1696
1697    success = screen->resource_get_handle(screen, res, &whandle, usage);
1698    mtx_unlock(&ctx->Shared->Mutex);
1699
1700    if (!success)
1701       return MESA_GLINTEROP_OUT_OF_HOST_MEMORY;
1702
1703    out->dmabuf_fd = whandle.handle;
1704    out->out_driver_data_written = 0;
1705
1706    if (res->target == PIPE_BUFFER)
1707       out->buf_offset += whandle.offset;
1708
1709    return MESA_GLINTEROP_SUCCESS;
1710 }
1711
1712 static const __DRI2interopExtension dri2InteropExtension = {
1713    .base = { __DRI2_INTEROP, 1 },
1714    .query_device_info = dri2_interop_query_device_info,
1715    .export_object = dri2_interop_export_object
1716 };
1717
1718 /*
1719  * Backend function init_screen.
1720  */
1721
1722 static const __DRIextension *dri_screen_extensions[] = {
1723    &driTexBufferExtension.base,
1724    &dri2FlushExtension.base,
1725    &dri2ImageExtension.base,
1726    &dri2RendererQueryExtension.base,
1727    &dri2ConfigQueryExtension.base,
1728    &dri2ThrottleExtension.base,
1729    &dri2FenceExtension.base,
1730    &dri2InteropExtension.base,
1731    NULL
1732 };
1733
1734 static const __DRIextension *dri_robust_screen_extensions[] = {
1735    &driTexBufferExtension.base,
1736    &dri2FlushExtension.base,
1737    &dri2ImageExtension.base,
1738    &dri2RendererQueryExtension.base,
1739    &dri2ConfigQueryExtension.base,
1740    &dri2ThrottleExtension.base,
1741    &dri2FenceExtension.base,
1742    &dri2InteropExtension.base,
1743    &dri2Robustness.base,
1744    NULL
1745 };
1746
1747 /**
1748  * This is the driver specific part of the createNewScreen entry point.
1749  *
1750  * Returns the struct gl_config supported by this driver.
1751  */
1752 static const __DRIconfig **
1753 dri2_init_screen(__DRIscreen * sPriv)
1754 {
1755    const __DRIconfig **configs;
1756    struct dri_screen *screen;
1757    struct pipe_screen *pscreen = NULL;
1758    const struct drm_conf_ret *throttle_ret;
1759    const struct drm_conf_ret *dmabuf_ret;
1760    int fd;
1761
1762    screen = CALLOC_STRUCT(dri_screen);
1763    if (!screen)
1764       return NULL;
1765
1766    screen->sPriv = sPriv;
1767    screen->fd = sPriv->fd;
1768    pipe_mutex_init(screen->opencl_func_mutex);
1769
1770    sPriv->driverPrivate = (void *)screen;
1771
1772    if (screen->fd < 0 || (fd = dup(screen->fd)) < 0)
1773       goto free_screen;
1774
1775    if (pipe_loader_drm_probe_fd(&screen->dev, fd))
1776       pscreen = pipe_loader_create_screen(screen->dev);
1777
1778    if (!pscreen)
1779        goto release_pipe;
1780
1781    throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE);
1782    dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD);
1783
1784    if (throttle_ret && throttle_ret->val.val_int != -1) {
1785       screen->throttling_enabled = TRUE;
1786       screen->default_throttle_frames = throttle_ret->val.val_int;
1787    }
1788
1789    if (dmabuf_ret && dmabuf_ret->val.val_bool) {
1790       uint64_t cap;
1791
1792       if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
1793           (cap & DRM_PRIME_CAP_IMPORT)) {
1794          dri2ImageExtension.createImageFromFds = dri2_from_fds;
1795          dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
1796       }
1797    }
1798
1799    if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) {
1800       sPriv->extensions = dri_robust_screen_extensions;
1801       screen->has_reset_status_query = true;
1802    }
1803    else
1804       sPriv->extensions = dri_screen_extensions;
1805
1806    configs = dri_init_screen_helper(screen, pscreen, screen->dev->driver_name);
1807    if (!configs)
1808       goto destroy_screen;
1809
1810    screen->can_share_buffer = true;
1811    screen->auto_fake_front = dri_with_format(sPriv);
1812    screen->broken_invalidate = !sPriv->dri2.useInvalidate;
1813    screen->lookup_egl_image = dri2_lookup_egl_image;
1814
1815    return configs;
1816
1817 destroy_screen:
1818    dri_destroy_screen_helper(screen);
1819
1820 release_pipe:
1821    if (screen->dev)
1822       pipe_loader_release(&screen->dev, 1);
1823    else
1824       close(fd);
1825
1826 free_screen:
1827    FREE(screen);
1828    return NULL;
1829 }
1830
1831 /**
1832  * This is the driver specific part of the createNewScreen entry point.
1833  *
1834  * Returns the struct gl_config supported by this driver.
1835  */
1836 static const __DRIconfig **
1837 dri_kms_init_screen(__DRIscreen * sPriv)
1838 {
1839 #if defined(GALLIUM_SOFTPIPE)
1840    const __DRIconfig **configs;
1841    struct dri_screen *screen;
1842    struct pipe_screen *pscreen = NULL;
1843    uint64_t cap;
1844    int fd;
1845
1846    screen = CALLOC_STRUCT(dri_screen);
1847    if (!screen)
1848       return NULL;
1849
1850    screen->sPriv = sPriv;
1851    screen->fd = sPriv->fd;
1852
1853    sPriv->driverPrivate = (void *)screen;
1854
1855    if (screen->fd < 0 || (fd = dup(screen->fd)) < 0)
1856       goto free_screen;
1857
1858    if (pipe_loader_sw_probe_kms(&screen->dev, fd))
1859       pscreen = pipe_loader_create_screen(screen->dev);
1860
1861    if (!pscreen)
1862        goto release_pipe;
1863
1864    if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
1865           (cap & DRM_PRIME_CAP_IMPORT)) {
1866       dri2ImageExtension.createImageFromFds = dri2_from_fds;
1867       dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
1868    }
1869
1870    sPriv->extensions = dri_screen_extensions;
1871
1872    configs = dri_init_screen_helper(screen, pscreen, "swrast");
1873    if (!configs)
1874       goto destroy_screen;
1875
1876    screen->can_share_buffer = false;
1877    screen->auto_fake_front = dri_with_format(sPriv);
1878    screen->broken_invalidate = !sPriv->dri2.useInvalidate;
1879    screen->lookup_egl_image = dri2_lookup_egl_image;
1880
1881    return configs;
1882
1883 destroy_screen:
1884    dri_destroy_screen_helper(screen);
1885
1886 release_pipe:
1887    if (screen->dev)
1888       pipe_loader_release(&screen->dev, 1);
1889    else
1890       close(fd);
1891
1892 free_screen:
1893    FREE(screen);
1894 #endif // GALLIUM_SOFTPIPE
1895    return NULL;
1896 }
1897
1898 static boolean
1899 dri2_create_buffer(__DRIscreen * sPriv,
1900                    __DRIdrawable * dPriv,
1901                    const struct gl_config * visual, boolean isPixmap)
1902 {
1903    struct dri_drawable *drawable = NULL;
1904
1905    if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
1906       return FALSE;
1907
1908    drawable = dPriv->driverPrivate;
1909
1910    drawable->allocate_textures = dri2_allocate_textures;
1911    drawable->flush_frontbuffer = dri2_flush_frontbuffer;
1912    drawable->update_tex_buffer = dri2_update_tex_buffer;
1913
1914    return TRUE;
1915 }
1916
1917 /**
1918  * DRI driver virtual function table.
1919  *
1920  * DRI versions differ in their implementation of init_screen and swap_buffers.
1921  */
1922 const struct __DriverAPIRec galliumdrm_driver_api = {
1923    .InitScreen = dri2_init_screen,
1924    .DestroyScreen = dri_destroy_screen,
1925    .CreateContext = dri_create_context,
1926    .DestroyContext = dri_destroy_context,
1927    .CreateBuffer = dri2_create_buffer,
1928    .DestroyBuffer = dri_destroy_buffer,
1929    .MakeCurrent = dri_make_current,
1930    .UnbindContext = dri_unbind_context,
1931
1932    .AllocateBuffer = dri2_allocate_buffer,
1933    .ReleaseBuffer  = dri2_release_buffer,
1934 };
1935
1936 /**
1937  * DRI driver virtual function table.
1938  *
1939  * KMS/DRM version of the DriverAPI above sporting a different InitScreen
1940  * hook. The latter is used to explicitly initialise the kms_swrast driver
1941  * rather than selecting the approapriate driver as suggested by the loader.
1942  */
1943 const struct __DriverAPIRec dri_kms_driver_api = {
1944    .InitScreen = dri_kms_init_screen,
1945    .DestroyScreen = dri_destroy_screen,
1946    .CreateContext = dri_create_context,
1947    .DestroyContext = dri_destroy_context,
1948    .CreateBuffer = dri2_create_buffer,
1949    .DestroyBuffer = dri_destroy_buffer,
1950    .MakeCurrent = dri_make_current,
1951    .UnbindContext = dri_unbind_context,
1952
1953    .AllocateBuffer = dri2_allocate_buffer,
1954    .ReleaseBuffer  = dri2_release_buffer,
1955 };
1956
1957 /* This is the table of extensions that the loader will dlsym() for. */
1958 const __DRIextension *galliumdrm_driver_extensions[] = {
1959     &driCoreExtension.base,
1960     &driImageDriverExtension.base,
1961     &driDRI2Extension.base,
1962     &gallium_config_options.base,
1963     NULL
1964 };
1965
1966 /* vim: set sw=3 ts=8 sts=3 expandtab: */