Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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 "util/u_memory.h"
  32. #include "util/u_inlines.h"
  33. #include "util/u_format.h"
  34. #include "util/u_debug.h"
  35. #include "state_tracker/drm_driver.h"
  36.  
  37. #include "dri_screen.h"
  38. #include "dri_context.h"
  39. #include "dri_drawable.h"
  40. #include "dri2_buffer.h"
  41.  
  42. /**
  43.  * DRI2 flush extension.
  44.  */
  45. static void
  46. dri2_flush_drawable(__DRIdrawable *dPriv)
  47. {
  48.    dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);
  49. }
  50.  
  51. static void
  52. dri2_invalidate_drawable(__DRIdrawable *dPriv)
  53. {
  54.    struct dri_drawable *drawable = dri_drawable(dPriv);
  55.  
  56.    dri2InvalidateDrawable(dPriv);
  57.    drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
  58.  
  59.    p_atomic_inc(&drawable->base.stamp);
  60. }
  61.  
  62. static const __DRI2flushExtension dri2FlushExtension = {
  63.     { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
  64.     dri2_flush_drawable,
  65.     dri2_invalidate_drawable,
  66.     dri_flush,
  67. };
  68.  
  69. /**
  70.  * Retrieve __DRIbuffer from the DRI loader.
  71.  */
  72. static __DRIbuffer *
  73. dri2_drawable_get_buffers(struct dri_drawable *drawable,
  74.                           const enum st_attachment_type *atts,
  75.                           unsigned *count)
  76. {
  77.    __DRIdrawable *dri_drawable = drawable->dPriv;
  78.    struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
  79.    boolean with_format;
  80.    __DRIbuffer *buffers;
  81.    int num_buffers;
  82.    unsigned attachments[10];
  83.    unsigned num_attachments, i;
  84.  
  85.    assert(loader);
  86.    with_format = dri_with_format(drawable->sPriv);
  87.  
  88.    num_attachments = 0;
  89.  
  90.    /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
  91.    if (!with_format)
  92.       attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
  93.  
  94.    for (i = 0; i < *count; i++) {
  95.       enum pipe_format format;
  96.       unsigned bind;
  97.       int att, depth;
  98.  
  99.       dri_drawable_get_format(drawable, atts[i], &format, &bind);
  100.       if (format == PIPE_FORMAT_NONE)
  101.          continue;
  102.  
  103.       switch (atts[i]) {
  104.       case ST_ATTACHMENT_FRONT_LEFT:
  105.          /* already added */
  106.          if (!with_format)
  107.             continue;
  108.          att = __DRI_BUFFER_FRONT_LEFT;
  109.          break;
  110.       case ST_ATTACHMENT_BACK_LEFT:
  111.          att = __DRI_BUFFER_BACK_LEFT;
  112.          break;
  113.       case ST_ATTACHMENT_FRONT_RIGHT:
  114.          att = __DRI_BUFFER_FRONT_RIGHT;
  115.          break;
  116.       case ST_ATTACHMENT_BACK_RIGHT:
  117.          att = __DRI_BUFFER_BACK_RIGHT;
  118.          break;
  119.       default:
  120.          continue;
  121.       }
  122.  
  123.       /*
  124.        * In this switch statement we must support all formats that
  125.        * may occur as the stvis->color_format.
  126.        */
  127.       switch(format) {
  128.       case PIPE_FORMAT_B8G8R8A8_UNORM:
  129.          depth = 32;
  130.          break;
  131.       case PIPE_FORMAT_B8G8R8X8_UNORM:
  132.          depth = 24;
  133.          break;
  134.       case PIPE_FORMAT_B5G6R5_UNORM:
  135.          depth = 16;
  136.          break;
  137.       default:
  138.          depth = util_format_get_blocksizebits(format);
  139.          assert(!"Unexpected format in dri2_drawable_get_buffers()");
  140.       }
  141.  
  142.       attachments[num_attachments++] = att;
  143.       if (with_format) {
  144.          attachments[num_attachments++] = depth;
  145.       }
  146.    }
  147.  
  148.    if (with_format) {
  149.       num_attachments /= 2;
  150.       buffers = loader->getBuffersWithFormat(dri_drawable,
  151.             &dri_drawable->w, &dri_drawable->h,
  152.             attachments, num_attachments,
  153.             &num_buffers, dri_drawable->loaderPrivate);
  154.    }
  155.    else {
  156.       buffers = loader->getBuffers(dri_drawable,
  157.             &dri_drawable->w, &dri_drawable->h,
  158.             attachments, num_attachments,
  159.             &num_buffers, dri_drawable->loaderPrivate);
  160.    }
  161.  
  162.    if (buffers)
  163.       *count = num_buffers;
  164.  
  165.    return buffers;
  166. }
  167.  
  168. /**
  169.  * Process __DRIbuffer and convert them into pipe_resources.
  170.  */
  171. static void
  172. dri2_drawable_process_buffers(struct dri_context *ctx,
  173.                               struct dri_drawable *drawable,
  174.                               __DRIbuffer *buffers, unsigned buffer_count,
  175.                               const enum st_attachment_type *atts,
  176.                               unsigned att_count)
  177. {
  178.    struct dri_screen *screen = dri_screen(drawable->sPriv);
  179.    __DRIdrawable *dri_drawable = drawable->dPriv;
  180.    struct pipe_resource templ;
  181.    struct winsys_handle whandle;
  182.    boolean alloc_depthstencil = FALSE;
  183.    unsigned i, j, bind;
  184.  
  185.    if (drawable->old_num == buffer_count &&
  186.        drawable->old_w == dri_drawable->w &&
  187.        drawable->old_h == dri_drawable->h &&
  188.        memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * buffer_count) == 0)
  189.       return;
  190.  
  191.    /* See if we need a depth-stencil buffer. */
  192.    for (i = 0; i < att_count; i++) {
  193.       if (atts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
  194.          alloc_depthstencil = TRUE;
  195.          break;
  196.       }
  197.    }
  198.  
  199.    /* Delete the resources we won't need. */
  200.    for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
  201.       /* Don't delete the depth-stencil buffer, we can reuse it. */
  202.       if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
  203.          continue;
  204.  
  205.       pipe_resource_reference(&drawable->textures[i], NULL);
  206.    }
  207.  
  208.    if (drawable->stvis.samples > 1) {
  209.       for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
  210.          boolean del = TRUE;
  211.  
  212.          /* Don't delete MSAA resources for the attachments which are enabled,
  213.           * we can reuse them. */
  214.          for (j = 0; j < att_count; j++) {
  215.             if (i == atts[j]) {
  216.                del = FALSE;
  217.                break;
  218.             }
  219.          }
  220.  
  221.          if (del) {
  222.             pipe_resource_reference(&drawable->msaa_textures[i], NULL);
  223.          }
  224.       }
  225.    }
  226.  
  227.    memset(&templ, 0, sizeof(templ));
  228.    templ.target = screen->target;
  229.    templ.last_level = 0;
  230.    templ.width0 = dri_drawable->w;
  231.    templ.height0 = dri_drawable->h;
  232.    templ.depth0 = 1;
  233.    templ.array_size = 1;
  234.  
  235.    memset(&whandle, 0, sizeof(whandle));
  236.  
  237.    /* Process DRI-provided buffers and get pipe_resources. */
  238.    for (i = 0; i < buffer_count; i++) {
  239.       __DRIbuffer *buf = &buffers[i];
  240.       enum st_attachment_type statt;
  241.       enum pipe_format format;
  242.  
  243.       switch (buf->attachment) {
  244.       case __DRI_BUFFER_FRONT_LEFT:
  245.          if (!screen->auto_fake_front) {
  246.             continue; /* invalid attachment */
  247.          }
  248.          /* fallthrough */
  249.       case __DRI_BUFFER_FAKE_FRONT_LEFT:
  250.          statt = ST_ATTACHMENT_FRONT_LEFT;
  251.          break;
  252.       case __DRI_BUFFER_BACK_LEFT:
  253.          statt = ST_ATTACHMENT_BACK_LEFT;
  254.          break;
  255.       default:
  256.          continue; /* invalid attachment */
  257.       }
  258.  
  259.       dri_drawable_get_format(drawable, statt, &format, &bind);
  260.       if (format == PIPE_FORMAT_NONE)
  261.          continue;
  262.  
  263.       templ.format = format;
  264.       templ.bind = bind;
  265.       whandle.handle = buf->name;
  266.       whandle.stride = buf->pitch;
  267.  
  268.       drawable->textures[statt] =
  269.          screen->base.screen->resource_from_handle(screen->base.screen,
  270.                &templ, &whandle);
  271.       assert(drawable->textures[statt]);
  272.    }
  273.  
  274.    /* Allocate private MSAA colorbuffers. */
  275.    if (drawable->stvis.samples > 1) {
  276.       for (i = 0; i < att_count; i++) {
  277.          enum st_attachment_type att = atts[i];
  278.  
  279.          if (att == ST_ATTACHMENT_DEPTH_STENCIL)
  280.             continue;
  281.  
  282.          if (drawable->textures[att]) {
  283.             templ.format = drawable->textures[att]->format;
  284.             templ.bind = drawable->textures[att]->bind;
  285.             templ.nr_samples = drawable->stvis.samples;
  286.  
  287.             /* Try to reuse the resource.
  288.              * (the other resource parameters should be constant)
  289.              */
  290.             if (!drawable->msaa_textures[att] ||
  291.                 drawable->msaa_textures[att]->width0 != templ.width0 ||
  292.                 drawable->msaa_textures[att]->height0 != templ.height0) {
  293.                /* Allocate a new one. */
  294.                pipe_resource_reference(&drawable->msaa_textures[att], NULL);
  295.  
  296.                drawable->msaa_textures[att] =
  297.                   screen->base.screen->resource_create(screen->base.screen,
  298.                                                        &templ);
  299.                assert(drawable->msaa_textures[att]);
  300.  
  301.                /* If there are any MSAA resources, we should initialize them
  302.                 * such that they contain the same data as the single-sample
  303.                 * resources we just got from the X server.
  304.                 *
  305.                 * The reason for this is that the state tracker (and
  306.                 * therefore the app) can access the MSAA resources only.
  307.                 * The single-sample resources are not exposed
  308.                 * to the state tracker.
  309.                 *
  310.                 */
  311.                dri_pipe_blit(ctx->st->pipe,
  312.                              drawable->msaa_textures[att],
  313.                              drawable->textures[att]);
  314.             }
  315.          }
  316.          else {
  317.             pipe_resource_reference(&drawable->msaa_textures[att], NULL);
  318.          }
  319.       }
  320.    }
  321.  
  322.    /* Allocate a private depth-stencil buffer. */
  323.    if (alloc_depthstencil) {
  324.       enum st_attachment_type att = ST_ATTACHMENT_DEPTH_STENCIL;
  325.       struct pipe_resource **zsbuf;
  326.       enum pipe_format format;
  327.       unsigned bind;
  328.  
  329.       dri_drawable_get_format(drawable, att, &format, &bind);
  330.  
  331.       if (format) {
  332.          templ.format = format;
  333.          templ.bind = bind;
  334.  
  335.          if (drawable->stvis.samples > 1) {
  336.             templ.nr_samples = drawable->stvis.samples;
  337.             zsbuf = &drawable->msaa_textures[att];
  338.          }
  339.          else {
  340.             templ.nr_samples = 0;
  341.             zsbuf = &drawable->textures[att];
  342.          }
  343.  
  344.          /* Try to reuse the resource.
  345.           * (the other resource parameters should be constant)
  346.           */
  347.          if (!*zsbuf ||
  348.              (*zsbuf)->width0 != templ.width0 ||
  349.              (*zsbuf)->height0 != templ.height0) {
  350.             /* Allocate a new one. */
  351.             pipe_resource_reference(zsbuf, NULL);
  352.             *zsbuf = screen->base.screen->resource_create(screen->base.screen,
  353.                                                           &templ);
  354.             assert(*zsbuf);
  355.          }
  356.       }
  357.       else {
  358.          pipe_resource_reference(&drawable->msaa_textures[att], NULL);
  359.          pipe_resource_reference(&drawable->textures[att], NULL);
  360.       }
  361.    }
  362.  
  363.    drawable->old_num = buffer_count;
  364.    drawable->old_w = dri_drawable->w;
  365.    drawable->old_h = dri_drawable->h;
  366.    memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * buffer_count);
  367. }
  368.  
  369. static __DRIbuffer *
  370. dri2_allocate_buffer(__DRIscreen *sPriv,
  371.                      unsigned attachment, unsigned format,
  372.                      int width, int height)
  373. {
  374.    struct dri_screen *screen = dri_screen(sPriv);
  375.    struct dri2_buffer *buffer;
  376.    struct pipe_resource templ;
  377.    enum pipe_format pf;
  378.    unsigned bind = 0;
  379.    struct winsys_handle whandle;
  380.  
  381.    switch (attachment) {
  382.       case __DRI_BUFFER_FRONT_LEFT:
  383.       case __DRI_BUFFER_FAKE_FRONT_LEFT:
  384.          bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
  385.          break;
  386.       case __DRI_BUFFER_BACK_LEFT:
  387.          bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
  388.          break;
  389.       case __DRI_BUFFER_DEPTH:
  390.       case __DRI_BUFFER_DEPTH_STENCIL:
  391.       case __DRI_BUFFER_STENCIL:
  392.             bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
  393.          break;
  394.    }
  395.  
  396.    /* because we get the handle and stride */
  397.    bind |= PIPE_BIND_SHARED;
  398.  
  399.    switch (format) {
  400.       case 32:
  401.          pf = PIPE_FORMAT_B8G8R8A8_UNORM;
  402.          break;
  403.       case 24:
  404.          pf = PIPE_FORMAT_B8G8R8X8_UNORM;
  405.          break;
  406.       case 16:
  407.          pf = PIPE_FORMAT_Z16_UNORM;
  408.          break;
  409.       default:
  410.          return NULL;
  411.    }
  412.  
  413.    buffer = CALLOC_STRUCT(dri2_buffer);
  414.    if (!buffer)
  415.       return NULL;
  416.  
  417.    memset(&templ, 0, sizeof(templ));
  418.    templ.bind = bind;
  419.    templ.format = pf;
  420.    templ.target = PIPE_TEXTURE_2D;
  421.    templ.last_level = 0;
  422.    templ.width0 = width;
  423.    templ.height0 = height;
  424.    templ.depth0 = 1;
  425.    templ.array_size = 1;
  426.  
  427.    buffer->resource =
  428.       screen->base.screen->resource_create(screen->base.screen, &templ);
  429.    if (!buffer->resource) {
  430.       FREE(buffer);
  431.       return NULL;
  432.    }
  433.  
  434.    memset(&whandle, 0, sizeof(whandle));
  435.    whandle.type = DRM_API_HANDLE_TYPE_SHARED;
  436.    screen->base.screen->resource_get_handle(screen->base.screen,
  437.          buffer->resource, &whandle);
  438.  
  439.    buffer->base.attachment = attachment;
  440.    buffer->base.name = whandle.handle;
  441.    buffer->base.cpp = util_format_get_blocksize(pf);
  442.    buffer->base.pitch = whandle.stride;
  443.  
  444.    return &buffer->base;
  445. }
  446.  
  447. static void
  448. dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
  449. {
  450.    struct dri2_buffer *buffer = dri2_buffer(bPriv);
  451.  
  452.    pipe_resource_reference(&buffer->resource, NULL);
  453.    FREE(buffer);
  454. }
  455.  
  456. /*
  457.  * Backend functions for st_framebuffer interface.
  458.  */
  459.  
  460. static void
  461. dri2_allocate_textures(struct dri_context *ctx,
  462.                        struct dri_drawable *drawable,
  463.                        const enum st_attachment_type *statts,
  464.                        unsigned statts_count)
  465. {
  466.    __DRIbuffer *buffers;
  467.    unsigned num_buffers = statts_count;
  468.  
  469.    buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
  470.    if (buffers)
  471.       dri2_drawable_process_buffers(ctx, drawable, buffers, num_buffers,
  472.                                     statts, statts_count);
  473. }
  474.  
  475. static void
  476. dri2_flush_frontbuffer(struct dri_context *ctx,
  477.                        struct dri_drawable *drawable,
  478.                        enum st_attachment_type statt)
  479. {
  480.    __DRIdrawable *dri_drawable = drawable->dPriv;
  481.    struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
  482.  
  483.    if (statt != ST_ATTACHMENT_FRONT_LEFT)
  484.       return;
  485.  
  486.    if (drawable->stvis.samples > 1) {
  487.       struct pipe_context *pipe = ctx->st->pipe;
  488.  
  489.       /* Resolve the front buffer. */
  490.       dri_pipe_blit(ctx->st->pipe,
  491.                     drawable->textures[ST_ATTACHMENT_FRONT_LEFT],
  492.                     drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]);
  493.       pipe->flush(pipe, NULL, 0);
  494.    }
  495.  
  496.    if (loader->flushFrontBuffer) {
  497.       loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
  498.    }
  499. }
  500.  
  501. static void
  502. dri2_update_tex_buffer(struct dri_drawable *drawable,
  503.                        struct dri_context *ctx,
  504.                        struct pipe_resource *res)
  505. {
  506.    /* no-op */
  507. }
  508.  
  509. static __DRIimage *
  510. dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
  511. {
  512.    __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
  513.    __DRIimage *img;
  514.  
  515.    if (!loader->lookupEGLImage)
  516.       return NULL;
  517.  
  518.    img = loader->lookupEGLImage(screen->sPriv,
  519.                                 handle, screen->sPriv->loaderPrivate);
  520.  
  521.    return img;
  522. }
  523.  
  524. static __DRIimage *
  525. dri2_create_image_from_name(__DRIscreen *_screen,
  526.                             int width, int height, int format,
  527.                             int name, int pitch, void *loaderPrivate)
  528. {
  529.    struct dri_screen *screen = dri_screen(_screen);
  530.    __DRIimage *img;
  531.    struct pipe_resource templ;
  532.    struct winsys_handle whandle;
  533.    unsigned tex_usage;
  534.    enum pipe_format pf;
  535.  
  536.    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
  537.  
  538.    switch (format) {
  539.    case __DRI_IMAGE_FORMAT_RGB565:
  540.       pf = PIPE_FORMAT_B5G6R5_UNORM;
  541.       break;
  542.    case __DRI_IMAGE_FORMAT_XRGB8888:
  543.       pf = PIPE_FORMAT_B8G8R8X8_UNORM;
  544.       break;
  545.    case __DRI_IMAGE_FORMAT_ARGB8888:
  546.       pf = PIPE_FORMAT_B8G8R8A8_UNORM;
  547.       break;
  548.    case __DRI_IMAGE_FORMAT_ABGR8888:
  549.       pf = PIPE_FORMAT_R8G8B8A8_UNORM;
  550.       break;
  551.    default:
  552.       pf = PIPE_FORMAT_NONE;
  553.       break;
  554.    }
  555.    if (pf == PIPE_FORMAT_NONE)
  556.       return NULL;
  557.  
  558.    img = CALLOC_STRUCT(__DRIimageRec);
  559.    if (!img)
  560.       return NULL;
  561.  
  562.    memset(&templ, 0, sizeof(templ));
  563.    templ.bind = tex_usage;
  564.    templ.format = pf;
  565.    templ.target = screen->target;
  566.    templ.last_level = 0;
  567.    templ.width0 = width;
  568.    templ.height0 = height;
  569.    templ.depth0 = 1;
  570.    templ.array_size = 1;
  571.  
  572.    memset(&whandle, 0, sizeof(whandle));
  573.    whandle.handle = name;
  574.    whandle.stride = pitch * util_format_get_blocksize(pf);
  575.  
  576.    img->texture = screen->base.screen->resource_from_handle(screen->base.screen,
  577.          &templ, &whandle);
  578.    if (!img->texture) {
  579.       FREE(img);
  580.       return NULL;
  581.    }
  582.  
  583.    img->level = 0;
  584.    img->layer = 0;
  585.    img->dri_format = format;
  586.    img->loader_private = loaderPrivate;
  587.  
  588.    return img;
  589. }
  590.  
  591. static __DRIimage *
  592. dri2_create_image_from_renderbuffer(__DRIcontext *context,
  593.                                     int renderbuffer, void *loaderPrivate)
  594. {
  595.    struct dri_context *ctx = dri_context(context);
  596.  
  597.    if (!ctx->st->get_resource_for_egl_image)
  598.       return NULL;
  599.  
  600.    /* TODO */
  601.    return NULL;
  602. }
  603.  
  604. static __DRIimage *
  605. dri2_create_image(__DRIscreen *_screen,
  606.                    int width, int height, int format,
  607.                    unsigned int use, void *loaderPrivate)
  608. {
  609.    struct dri_screen *screen = dri_screen(_screen);
  610.    __DRIimage *img;
  611.    struct pipe_resource templ;
  612.    unsigned tex_usage;
  613.    enum pipe_format pf;
  614.  
  615.    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
  616.    if (use & __DRI_IMAGE_USE_SCANOUT)
  617.       tex_usage |= PIPE_BIND_SCANOUT;
  618.    if (use & __DRI_IMAGE_USE_SHARE)
  619.       tex_usage |= PIPE_BIND_SHARED;
  620.    if (use & __DRI_IMAGE_USE_CURSOR) {
  621.       if (width != 64 || height != 64)
  622.          return NULL;
  623.       tex_usage |= PIPE_BIND_CURSOR;
  624.    }
  625.  
  626.    switch (format) {
  627.    case __DRI_IMAGE_FORMAT_RGB565:
  628.       pf = PIPE_FORMAT_B5G6R5_UNORM;
  629.       break;
  630.    case __DRI_IMAGE_FORMAT_XRGB8888:
  631.       pf = PIPE_FORMAT_B8G8R8X8_UNORM;
  632.       break;
  633.    case __DRI_IMAGE_FORMAT_ARGB8888:
  634.       pf = PIPE_FORMAT_B8G8R8A8_UNORM;
  635.       break;
  636.    case __DRI_IMAGE_FORMAT_ABGR8888:
  637.       pf = PIPE_FORMAT_R8G8B8A8_UNORM;
  638.       break;
  639.    default:
  640.       pf = PIPE_FORMAT_NONE;
  641.       break;
  642.    }
  643.    if (pf == PIPE_FORMAT_NONE)
  644.       return NULL;
  645.  
  646.    img = CALLOC_STRUCT(__DRIimageRec);
  647.    if (!img)
  648.       return NULL;
  649.  
  650.    memset(&templ, 0, sizeof(templ));
  651.    templ.bind = tex_usage;
  652.    templ.format = pf;
  653.    templ.target = PIPE_TEXTURE_2D;
  654.    templ.last_level = 0;
  655.    templ.width0 = width;
  656.    templ.height0 = height;
  657.    templ.depth0 = 1;
  658.    templ.array_size = 1;
  659.  
  660.    img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
  661.    if (!img->texture) {
  662.       FREE(img);
  663.       return NULL;
  664.    }
  665.  
  666.    img->level = 0;
  667.    img->layer = 0;
  668.    img->dri_format = format;
  669.    img->dri_components = 0;
  670.  
  671.    img->loader_private = loaderPrivate;
  672.    return img;
  673. }
  674.  
  675. static GLboolean
  676. dri2_query_image(__DRIimage *image, int attrib, int *value)
  677. {
  678.    struct winsys_handle whandle;
  679.    memset(&whandle, 0, sizeof(whandle));
  680.  
  681.    switch (attrib) {
  682.    case __DRI_IMAGE_ATTRIB_STRIDE:
  683.       image->texture->screen->resource_get_handle(image->texture->screen,
  684.             image->texture, &whandle);
  685.       *value = whandle.stride;
  686.       return GL_TRUE;
  687.    case __DRI_IMAGE_ATTRIB_HANDLE:
  688.       whandle.type = DRM_API_HANDLE_TYPE_KMS;
  689.       image->texture->screen->resource_get_handle(image->texture->screen,
  690.          image->texture, &whandle);
  691.       *value = whandle.handle;
  692.       return GL_TRUE;
  693.    case __DRI_IMAGE_ATTRIB_NAME:
  694.       whandle.type = DRM_API_HANDLE_TYPE_SHARED;
  695.       image->texture->screen->resource_get_handle(image->texture->screen,
  696.          image->texture, &whandle);
  697.       *value = whandle.handle;
  698.       return GL_TRUE;
  699.    case __DRI_IMAGE_ATTRIB_FORMAT:
  700.       *value = image->dri_format;
  701.       return GL_TRUE;
  702.    case __DRI_IMAGE_ATTRIB_WIDTH:
  703.       *value = image->texture->width0;
  704.       return GL_TRUE;
  705.    case __DRI_IMAGE_ATTRIB_HEIGHT:
  706.       *value = image->texture->height0;
  707.       return GL_TRUE;
  708.    case __DRI_IMAGE_ATTRIB_COMPONENTS:
  709.       if (image->dri_components == 0)
  710.          return GL_FALSE;
  711.       *value = image->dri_components;
  712.       return GL_TRUE;
  713.    default:
  714.       return GL_FALSE;
  715.    }
  716. }
  717.  
  718. static __DRIimage *
  719. dri2_dup_image(__DRIimage *image, void *loaderPrivate)
  720. {
  721.    __DRIimage *img;
  722.  
  723.    img = CALLOC_STRUCT(__DRIimageRec);
  724.    if (!img)
  725.       return NULL;
  726.  
  727.    img->texture = NULL;
  728.    pipe_resource_reference(&img->texture, image->texture);
  729.    img->level = image->level;
  730.    img->layer = image->layer;
  731.    /* This should be 0 for sub images, but dup is also used for base images. */
  732.    img->dri_components = image->dri_components;
  733.    img->loader_private = loaderPrivate;
  734.  
  735.    return img;
  736. }
  737.  
  738. static GLboolean
  739. dri2_validate_usage(__DRIimage *image, unsigned int use)
  740. {
  741.    /*
  742.     * Gallium drivers are bad at adding usages to the resources
  743.     * once opened again in another process, which is the main use
  744.     * case for this, so we have to lie.
  745.     */
  746.    if (image != NULL)
  747.       return GL_TRUE;
  748.    else
  749.       return GL_FALSE;
  750. }
  751.  
  752. static __DRIimage *
  753. dri2_from_names(__DRIscreen *screen, int width, int height, int format,
  754.                 int *names, int num_names, int *strides, int *offsets,
  755.                 void *loaderPrivate)
  756. {
  757.    __DRIimage *img;
  758.    int stride, dri_components;
  759.  
  760.    if (num_names != 1)
  761.       return NULL;
  762.    if (offsets[0] != 0)
  763.       return NULL;
  764.  
  765.    switch(format) {
  766.    case __DRI_IMAGE_FOURCC_RGB565:
  767.       format = __DRI_IMAGE_FORMAT_RGB565;
  768.       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
  769.       break;
  770.    case __DRI_IMAGE_FOURCC_ARGB8888:
  771.       format = __DRI_IMAGE_FORMAT_ARGB8888;
  772.       dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
  773.       break;
  774.    case __DRI_IMAGE_FOURCC_XRGB8888:
  775.       format = __DRI_IMAGE_FORMAT_XRGB8888;
  776.       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
  777.       break;
  778.    case __DRI_IMAGE_FOURCC_ABGR8888:
  779.       format = __DRI_IMAGE_FORMAT_ABGR8888;
  780.       dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
  781.       break;
  782.    case __DRI_IMAGE_FOURCC_XBGR8888:
  783.       format = __DRI_IMAGE_FORMAT_XBGR8888;
  784.       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
  785.       break;
  786.    default:
  787.       return NULL;
  788.    }
  789.  
  790.    /* Strides are in bytes not pixels. */
  791.    stride = strides[0] /4;
  792.  
  793.    img = dri2_create_image_from_name(screen, width, height, format,
  794.                                      names[0], stride, loaderPrivate);
  795.    if (img == NULL)
  796.       return NULL;
  797.  
  798.    img->dri_components = dri_components;
  799.    return img;
  800. }
  801.  
  802. static __DRIimage *
  803. dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
  804. {
  805.    __DRIimage *img;
  806.  
  807.    if (plane != 0)
  808.       return NULL;
  809.  
  810.    if (image->dri_components == 0)
  811.       return NULL;
  812.  
  813.    img = dri2_dup_image(image, loaderPrivate);
  814.    if (img == NULL)
  815.       return NULL;
  816.  
  817.    /* set this to 0 for sub images. */
  818.    img->dri_components = 0;
  819.    return img;
  820. }
  821.  
  822. static void
  823. dri2_destroy_image(__DRIimage *img)
  824. {
  825.    pipe_resource_reference(&img->texture, NULL);
  826.    FREE(img);
  827. }
  828.  
  829. static struct __DRIimageExtensionRec dri2ImageExtension = {
  830.     { __DRI_IMAGE, 5 },
  831.     dri2_create_image_from_name,
  832.     dri2_create_image_from_renderbuffer,
  833.     dri2_destroy_image,
  834.     dri2_create_image,
  835.     dri2_query_image,
  836.     dri2_dup_image,
  837.     dri2_validate_usage,
  838.     dri2_from_names,
  839.     dri2_from_planar,
  840. };
  841.  
  842. /*
  843.  * Backend function init_screen.
  844.  */
  845.  
  846. static const __DRIextension *dri_screen_extensions[] = {
  847.    &driTexBufferExtension.base,
  848.    &dri2FlushExtension.base,
  849.    &dri2ImageExtension.base,
  850.    &dri2ConfigQueryExtension.base,
  851.    &dri2ThrottleExtension.base,
  852.    NULL
  853. };
  854.  
  855. /**
  856.  * This is the driver specific part of the createNewScreen entry point.
  857.  *
  858.  * Returns the struct gl_config supported by this driver.
  859.  */
  860. static const __DRIconfig **
  861. dri2_init_screen(__DRIscreen * sPriv)
  862. {
  863.    const __DRIconfig **configs;
  864.    struct dri_screen *screen;
  865.    struct pipe_screen *pscreen;
  866.    const struct drm_conf_ret *throttle_ret = NULL;
  867.  
  868.    screen = CALLOC_STRUCT(dri_screen);
  869.    if (!screen)
  870.       return NULL;
  871.  
  872.    screen->sPriv = sPriv;
  873.    screen->fd = sPriv->fd;
  874.  
  875.    sPriv->driverPrivate = (void *)screen;
  876.  
  877.    pscreen = driver_descriptor.create_screen(screen->fd);
  878.    if (driver_descriptor.configuration)
  879.       throttle_ret = driver_descriptor.configuration(DRM_CONF_THROTTLE);
  880.  
  881.    if (throttle_ret && throttle_ret->val.val_int != -1) {
  882.       screen->throttling_enabled = TRUE;
  883.       screen->default_throttle_frames = throttle_ret->val.val_int;
  884.    }
  885.  
  886.    sPriv->extensions = dri_screen_extensions;
  887.  
  888.    /* dri_init_screen_helper checks pscreen for us */
  889.  
  890.    configs = dri_init_screen_helper(screen, pscreen);
  891.    if (!configs)
  892.       goto fail;
  893.  
  894.    sPriv->api_mask = 0;
  895.    if (screen->st_api->profile_mask & ST_PROFILE_DEFAULT_MASK)
  896.       sPriv->api_mask |= 1 << __DRI_API_OPENGL;
  897.    if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES1_MASK)
  898.       sPriv->api_mask |= 1 << __DRI_API_GLES;
  899.    if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES2_MASK)
  900.       sPriv->api_mask |= 1 << __DRI_API_GLES2;
  901.  
  902.    screen->auto_fake_front = dri_with_format(sPriv);
  903.    screen->broken_invalidate = !sPriv->dri2.useInvalidate;
  904.    screen->lookup_egl_image = dri2_lookup_egl_image;
  905.  
  906.    return configs;
  907. fail:
  908.    dri_destroy_screen_helper(screen);
  909.    FREE(screen);
  910.    return NULL;
  911. }
  912.  
  913. static boolean
  914. dri2_create_buffer(__DRIscreen * sPriv,
  915.                    __DRIdrawable * dPriv,
  916.                    const struct gl_config * visual, boolean isPixmap)
  917. {
  918.    struct dri_drawable *drawable = NULL;
  919.  
  920.    if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
  921.       return FALSE;
  922.  
  923.    drawable = dPriv->driverPrivate;
  924.  
  925.    drawable->allocate_textures = dri2_allocate_textures;
  926.    drawable->flush_frontbuffer = dri2_flush_frontbuffer;
  927.    drawable->update_tex_buffer = dri2_update_tex_buffer;
  928.  
  929.    return TRUE;
  930. }
  931.  
  932. /**
  933.  * DRI driver virtual function table.
  934.  *
  935.  * DRI versions differ in their implementation of init_screen and swap_buffers.
  936.  */
  937. const struct __DriverAPIRec driDriverAPI = {
  938.    .InitScreen = dri2_init_screen,
  939.    .DestroyScreen = dri_destroy_screen,
  940.    .CreateContext = dri_create_context,
  941.    .DestroyContext = dri_destroy_context,
  942.    .CreateBuffer = dri2_create_buffer,
  943.    .DestroyBuffer = dri_destroy_buffer,
  944.    .MakeCurrent = dri_make_current,
  945.    .UnbindContext = dri_unbind_context,
  946.  
  947.    .AllocateBuffer = dri2_allocate_buffer,
  948.    .ReleaseBuffer  = dri2_release_buffer,
  949. };
  950.  
  951. /* This is the table of extensions that the loader will dlsym() for. */
  952. PUBLIC const __DRIextension *__driDriverExtensions[] = {
  953.     &driCoreExtension.base,
  954.     &driDRI2Extension.base,
  955.     NULL
  956. };
  957.  
  958. /* vim: set sw=3 ts=8 sts=3 expandtab: */
  959.