Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 "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: */
  1641.