Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2009, VMware, Inc.
  4.  * All Rights Reserved.
  5.  * Copyright 2010 George Sapountzis <gsapountzis@gmail.com>
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the
  9.  * "Software"), to deal in the Software without restriction, including
  10.  * without limitation the rights to use, copy, modify, merge, publish,
  11.  * distribute, sub license, and/or sell copies of the Software, and to
  12.  * permit persons to whom the Software is furnished to do so, subject to
  13.  * the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice (including the
  16.  * next paragraph) shall be included in all copies or substantial portions
  17.  * of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  21.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  22.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  23.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  24.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  25.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26.  *
  27.  **************************************************************************/
  28.  
  29. /* TODO:
  30.  *
  31.  * xshm / EGLImage:
  32.  *
  33.  * Allow the loaders to use the XSHM extension. It probably requires callbacks
  34.  * for createImage/destroyImage similar to DRI2 getBuffers.
  35.  */
  36.  
  37. #include "util/u_format.h"
  38. #include "util/u_memory.h"
  39. #include "util/u_inlines.h"
  40. #include "util/u_box.h"
  41. #include "pipe/p_context.h"
  42. #include "state_tracker/drisw_api.h"
  43. #include "state_tracker/st_context.h"
  44.  
  45. #include "dri_screen.h"
  46. #include "dri_context.h"
  47. #include "dri_drawable.h"
  48. #include "dri_query_renderer.h"
  49.  
  50. DEBUG_GET_ONCE_BOOL_OPTION(swrast_no_present, "SWRAST_NO_PRESENT", FALSE);
  51. static boolean swrast_no_present = FALSE;
  52.  
  53. static INLINE void
  54. get_drawable_info(__DRIdrawable *dPriv, int *x, int *y, int *w, int *h)
  55. {
  56.    __DRIscreen *sPriv = dPriv->driScreenPriv;
  57.    const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
  58.  
  59.    loader->getDrawableInfo(dPriv,
  60.                            x, y, w, h,
  61.                            dPriv->loaderPrivate);
  62. }
  63.  
  64. static INLINE void
  65. put_image(__DRIdrawable *dPriv, void *data, unsigned width, unsigned height)
  66. {
  67.    __DRIscreen *sPriv = dPriv->driScreenPriv;
  68.    const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
  69.  
  70.    loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
  71.                     0, 0, width, height,
  72.                     data, dPriv->loaderPrivate);
  73. }
  74.  
  75. static INLINE void
  76. put_image2(__DRIdrawable *dPriv, void *data, int x, int y,
  77.            unsigned width, unsigned height, unsigned stride)
  78. {
  79.    __DRIscreen *sPriv = dPriv->driScreenPriv;
  80.    const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
  81.  
  82.    loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
  83.                      x, y, width, height, stride,
  84.                      data, dPriv->loaderPrivate);
  85. }
  86.  
  87. static INLINE void
  88. get_image(__DRIdrawable *dPriv, int x, int y, int width, int height, void *data)
  89. {
  90.    __DRIscreen *sPriv = dPriv->driScreenPriv;
  91.    const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
  92.  
  93.    loader->getImage(dPriv,
  94.                     x, y, width, height,
  95.                     data, dPriv->loaderPrivate);
  96. }
  97.  
  98. static void
  99. drisw_update_drawable_info(struct dri_drawable *drawable)
  100. {
  101.    __DRIdrawable *dPriv = drawable->dPriv;
  102.    int x, y;
  103.  
  104.    get_drawable_info(dPriv, &x, &y, &dPriv->w, &dPriv->h);
  105. }
  106.  
  107. static void
  108. drisw_put_image(struct dri_drawable *drawable,
  109.                 void *data, unsigned width, unsigned height)
  110. {
  111.    __DRIdrawable *dPriv = drawable->dPriv;
  112.  
  113.    put_image(dPriv, data, width, height);
  114. }
  115.  
  116. static void
  117. drisw_put_image2(struct dri_drawable *drawable,
  118.                  void *data, int x, int y, unsigned width, unsigned height,
  119.                  unsigned stride)
  120. {
  121.    __DRIdrawable *dPriv = drawable->dPriv;
  122.  
  123.    put_image2(dPriv, data, x, y, width, height, stride);
  124. }
  125.  
  126. static INLINE void
  127. drisw_present_texture(__DRIdrawable *dPriv,
  128.                       struct pipe_resource *ptex, struct pipe_box *sub_box)
  129. {
  130.    struct dri_drawable *drawable = dri_drawable(dPriv);
  131.    struct dri_screen *screen = dri_screen(drawable->sPriv);
  132.  
  133.    if (swrast_no_present)
  134.       return;
  135.  
  136.    screen->base.screen->flush_frontbuffer(screen->base.screen, ptex, 0, 0, drawable, sub_box);
  137. }
  138.  
  139. static INLINE void
  140. drisw_invalidate_drawable(__DRIdrawable *dPriv)
  141. {
  142.    struct dri_drawable *drawable = dri_drawable(dPriv);
  143.  
  144.    drawable->texture_stamp = dPriv->lastStamp - 1;
  145.  
  146.    p_atomic_inc(&drawable->base.stamp);
  147. }
  148.  
  149. static INLINE void
  150. drisw_copy_to_front(__DRIdrawable * dPriv,
  151.                     struct pipe_resource *ptex)
  152. {
  153.    drisw_present_texture(dPriv, ptex, NULL);
  154.  
  155.    drisw_invalidate_drawable(dPriv);
  156. }
  157.  
  158. /*
  159.  * Backend functions for st_framebuffer interface and swap_buffers.
  160.  */
  161.  
  162. static void
  163. drisw_swap_buffers(__DRIdrawable *dPriv)
  164. {
  165.    struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv);
  166.    struct dri_drawable *drawable = dri_drawable(dPriv);
  167.    struct pipe_resource *ptex;
  168.  
  169.    if (!ctx)
  170.       return;
  171.  
  172.    ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
  173.  
  174.    if (ptex) {
  175.       if (ctx->pp)
  176.          pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]);
  177.  
  178.       ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL);
  179.  
  180.       drisw_copy_to_front(dPriv, ptex);
  181.    }
  182. }
  183.  
  184. static void
  185. drisw_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y,
  186.                       int w, int h)
  187. {
  188.    struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv);
  189.    struct dri_drawable *drawable = dri_drawable(dPriv);
  190.    struct pipe_resource *ptex;
  191.    struct pipe_box box;
  192.    if (!ctx)
  193.       return;
  194.  
  195.    ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
  196.  
  197.    if (ptex) {
  198.       if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL])
  199.          pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]);
  200.  
  201.       ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL);
  202.  
  203.       u_box_2d(x, dPriv->h - y - h, w, h, &box);
  204.       drisw_present_texture(dPriv, ptex, &box);
  205.    }
  206. }
  207.  
  208. static void
  209. drisw_flush_frontbuffer(struct dri_context *ctx,
  210.                         struct dri_drawable *drawable,
  211.                         enum st_attachment_type statt)
  212. {
  213.    struct pipe_resource *ptex;
  214.  
  215.    if (!ctx)
  216.       return;
  217.  
  218.    ptex = drawable->textures[statt];
  219.  
  220.    if (ptex) {
  221.       drisw_copy_to_front(ctx->dPriv, ptex);
  222.    }
  223. }
  224.  
  225. /**
  226.  * Allocate framebuffer attachments.
  227.  *
  228.  * During fixed-size operation, the function keeps allocating new attachments
  229.  * as they are requested. Unused attachments are not removed, not until the
  230.  * framebuffer is resized or destroyed.
  231.  */
  232. static void
  233. drisw_allocate_textures(struct dri_context *stctx,
  234.                         struct dri_drawable *drawable,
  235.                         const enum st_attachment_type *statts,
  236.                         unsigned count)
  237. {
  238.    struct dri_screen *screen = dri_screen(drawable->sPriv);
  239.    struct pipe_resource templ;
  240.    unsigned width, height;
  241.    boolean resized;
  242.    unsigned i;
  243.  
  244.    width  = drawable->dPriv->w;
  245.    height = drawable->dPriv->h;
  246.  
  247.    resized = (drawable->old_w != width ||
  248.               drawable->old_h != height);
  249.  
  250.    /* remove outdated textures */
  251.    if (resized) {
  252.       for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
  253.          pipe_resource_reference(&drawable->textures[i], NULL);
  254.    }
  255.  
  256.    memset(&templ, 0, sizeof(templ));
  257.    templ.target = screen->target;
  258.    templ.width0 = width;
  259.    templ.height0 = height;
  260.    templ.depth0 = 1;
  261.    templ.array_size = 1;
  262.    templ.last_level = 0;
  263.  
  264.    for (i = 0; i < count; i++) {
  265.       enum pipe_format format;
  266.       unsigned bind;
  267.  
  268.       /* the texture already exists or not requested */
  269.       if (drawable->textures[statts[i]])
  270.          continue;
  271.  
  272.       dri_drawable_get_format(drawable, statts[i], &format, &bind);
  273.  
  274.       /* if we don't do any present, no need for display targets */
  275.       if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL && !swrast_no_present)
  276.          bind |= PIPE_BIND_DISPLAY_TARGET;
  277.  
  278.       if (format == PIPE_FORMAT_NONE)
  279.          continue;
  280.  
  281.       templ.format = format;
  282.       templ.bind = bind;
  283.  
  284.       drawable->textures[statts[i]] =
  285.          screen->base.screen->resource_create(screen->base.screen, &templ);
  286.    }
  287.  
  288.    drawable->old_w = width;
  289.    drawable->old_h = height;
  290. }
  291.  
  292. static void
  293. drisw_update_tex_buffer(struct dri_drawable *drawable,
  294.                         struct dri_context *ctx,
  295.                         struct pipe_resource *res)
  296. {
  297.    __DRIdrawable *dPriv = drawable->dPriv;
  298.  
  299.    struct st_context *st_ctx = (struct st_context *)ctx->st;
  300.    struct pipe_context *pipe = st_ctx->pipe;
  301.    struct pipe_transfer *transfer;
  302.    char *map;
  303.    int x, y, w, h;
  304.    int ximage_stride, line;
  305.    int cpp = util_format_get_blocksize(res->format);
  306.  
  307.    get_drawable_info(dPriv, &x, &y, &w, &h);
  308.  
  309.    map = pipe_transfer_map(pipe, res,
  310.                            0, 0, // level, layer,
  311.                            PIPE_TRANSFER_WRITE,
  312.                            x, y, w, h, &transfer);
  313.  
  314.    /* Copy the Drawable content to the mapped texture buffer */
  315.    get_image(dPriv, x, y, w, h, map);
  316.  
  317.    /* The pipe transfer has a pitch rounded up to the nearest 64 pixels.
  318.       get_image() has a pitch rounded up to 4 bytes.  */
  319.    ximage_stride = ((w * cpp) + 3) & -4;
  320.    for (line = h-1; line; --line) {
  321.       memmove(&map[line * transfer->stride],
  322.               &map[line * ximage_stride],
  323.               ximage_stride);
  324.    }
  325.  
  326.    pipe_transfer_unmap(pipe, transfer);
  327. }
  328.  
  329. /*
  330.  * Backend function for init_screen.
  331.  */
  332.  
  333. static const __DRIextension *drisw_screen_extensions[] = {
  334.    &driTexBufferExtension.base,
  335.    &dri2RendererQueryExtension.base,
  336.    &dri2ConfigQueryExtension.base,
  337.    NULL
  338. };
  339.  
  340. static struct drisw_loader_funcs drisw_lf = {
  341.    .put_image = drisw_put_image,
  342.    .put_image2 = drisw_put_image2
  343. };
  344.  
  345. static const __DRIconfig **
  346. drisw_init_screen(__DRIscreen * sPriv)
  347. {
  348.    const __DRIconfig **configs;
  349.    struct dri_screen *screen;
  350.    struct pipe_screen *pscreen;
  351.  
  352.    screen = CALLOC_STRUCT(dri_screen);
  353.    if (!screen)
  354.       return NULL;
  355.  
  356.    screen->sPriv = sPriv;
  357.    screen->fd = -1;
  358.  
  359.    swrast_no_present = debug_get_option_swrast_no_present();
  360.  
  361.    sPriv->driverPrivate = (void *)screen;
  362.    sPriv->extensions = drisw_screen_extensions;
  363.  
  364.    pscreen = drisw_create_screen(&drisw_lf);
  365.    /* dri_init_screen_helper checks pscreen for us */
  366.  
  367.    configs = dri_init_screen_helper(screen, pscreen, "swrast");
  368.    if (!configs)
  369.       goto fail;
  370.  
  371.    return configs;
  372. fail:
  373.    dri_destroy_screen_helper(screen);
  374.    FREE(screen);
  375.    return NULL;
  376. }
  377.  
  378. static boolean
  379. drisw_create_buffer(__DRIscreen * sPriv,
  380.                     __DRIdrawable * dPriv,
  381.                     const struct gl_config * visual, boolean isPixmap)
  382. {
  383.    struct dri_drawable *drawable = NULL;
  384.  
  385.    if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
  386.       return FALSE;
  387.  
  388.    drawable = dPriv->driverPrivate;
  389.  
  390.    drawable->allocate_textures = drisw_allocate_textures;
  391.    drawable->update_drawable_info = drisw_update_drawable_info;
  392.    drawable->flush_frontbuffer = drisw_flush_frontbuffer;
  393.    drawable->update_tex_buffer = drisw_update_tex_buffer;
  394.  
  395.    return TRUE;
  396. }
  397.  
  398. /**
  399.  * DRI driver virtual function table.
  400.  *
  401.  * DRI versions differ in their implementation of init_screen and swap_buffers.
  402.  */
  403. const struct __DriverAPIRec galliumsw_driver_api = {
  404.    .InitScreen = drisw_init_screen,
  405.    .DestroyScreen = dri_destroy_screen,
  406.    .CreateContext = dri_create_context,
  407.    .DestroyContext = dri_destroy_context,
  408.    .CreateBuffer = drisw_create_buffer,
  409.    .DestroyBuffer = dri_destroy_buffer,
  410.    .SwapBuffers = drisw_swap_buffers,
  411.    .MakeCurrent = dri_make_current,
  412.    .UnbindContext = dri_unbind_context,
  413.    .CopySubBuffer = drisw_copy_sub_buffer,
  414. };
  415.  
  416. /* This is the table of extensions that the loader will dlsym() for. */
  417. const __DRIextension *galliumsw_driver_extensions[] = {
  418.     &driCoreExtension.base,
  419.     &driSWRastExtension.base,
  420.     &driCopySubBufferExtension.base,
  421.     &gallium_config_options.base,
  422.     NULL
  423. };
  424.  
  425. /* vim: set sw=3 ts=8 sts=3 expandtab: */
  426.