Subversion Repositories Kolibri OS

Rev

Rev 4358 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * 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
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. /* Provide additional functionality on top of bufmgr buffers:
  29.  *   - 2d semantics and blit operations
  30.  *   - refcounting of buffers for multiple images in a buffer.
  31.  *   - refcounting of buffer mappings.
  32.  *   - some logic for moving the buffers to the best memory pools for
  33.  *     given operations.
  34.  *
  35.  * Most of this is to make it easier to implement the fixed-layout
  36.  * mipmap tree required by intel hardware in the face of GL's
  37.  * programming interface where each image can be specifed in random
  38.  * order and it isn't clear what layout the tree should have until the
  39.  * last moment.
  40.  */
  41.  
  42. //#include <sys/ioctl.h>
  43. #include <errno.h>
  44.  
  45. #include "main/hash.h"
  46. #include "intel_context.h"
  47. #include "intel_regions.h"
  48. #include "intel_blit.h"
  49. #include "intel_buffer_objects.h"
  50. #include "intel_bufmgr.h"
  51. #include "intel_batchbuffer.h"
  52.  
  53. #define FILE_DEBUG_FLAG DEBUG_REGION
  54.  
  55. /* This should be set to the maximum backtrace size desired.
  56.  * Set it to 0 to disable backtrace debugging.
  57.  */
  58. #define DEBUG_BACKTRACE_SIZE 0
  59.  
  60. #if DEBUG_BACKTRACE_SIZE == 0
  61. /* Use the standard debug output */
  62. #define _DBG(...) DBG(__VA_ARGS__)
  63. #else
  64. /* Use backtracing debug output */
  65. #define _DBG(...) {debug_backtrace(); DBG(__VA_ARGS__);}
  66.  
  67. /* Backtracing debug support */
  68. #include <execinfo.h>
  69.  
  70. static void
  71. debug_backtrace(void)
  72. {
  73.    void *trace[DEBUG_BACKTRACE_SIZE];
  74.    char **strings = NULL;
  75.    int traceSize;
  76.    register int i;
  77.  
  78.    traceSize = backtrace(trace, DEBUG_BACKTRACE_SIZE);
  79.    strings = backtrace_symbols(trace, traceSize);
  80.    if (strings == NULL) {
  81.       DBG("no backtrace:");
  82.       return;
  83.    }
  84.  
  85.    /* Spit out all the strings with a colon separator.  Ignore
  86.     * the first, since we don't really care about the call
  87.     * to debug_backtrace() itself.  Skip until the final "/" in
  88.     * the trace to avoid really long lines.
  89.     */
  90.    for (i = 1; i < traceSize; i++) {
  91.       char *p = strings[i], *slash = strings[i];
  92.       while (*p) {
  93.          if (*p++ == '/') {
  94.             slash = p;
  95.          }
  96.       }
  97.  
  98.       DBG("%s:", slash);
  99.    }
  100.  
  101.    /* Free up the memory, and we're done */
  102.    free(strings);
  103. }
  104.  
  105. #endif
  106.  
  107. static struct intel_region *
  108. intel_region_alloc_internal(struct intel_screen *screen,
  109.                             GLuint cpp,
  110.                             GLuint width, GLuint height, GLuint pitch,
  111.                             uint32_t tiling, drm_intel_bo *buffer)
  112. {
  113.    struct intel_region *region;
  114.  
  115.    region = calloc(sizeof(*region), 1);
  116.    if (region == NULL)
  117.       return region;
  118.  
  119.    region->cpp = cpp;
  120.    region->width = width;
  121.    region->height = height;
  122.    region->pitch = pitch;
  123.    region->refcount = 1;
  124.    region->bo = buffer;
  125.    region->tiling = tiling;
  126.  
  127.    _DBG("%s <-- %p\n", __FUNCTION__, region);
  128.    return region;
  129. }
  130.  
  131. struct intel_region *
  132. intel_region_alloc(struct intel_screen *screen,
  133.                    uint32_t tiling,
  134.                    GLuint cpp, GLuint width, GLuint height,
  135.                    bool expect_accelerated_upload)
  136. {
  137.    drm_intel_bo *buffer;
  138.    unsigned long flags = 0;
  139.    unsigned long aligned_pitch;
  140.    struct intel_region *region;
  141.  
  142.    if (expect_accelerated_upload)
  143.       flags |= BO_ALLOC_FOR_RENDER;
  144.  
  145.    buffer = drm_intel_bo_alloc_tiled(screen->bufmgr, "region",
  146.                                      width, height, cpp,
  147.                                      &tiling, &aligned_pitch, flags);
  148.    if (buffer == NULL)
  149.       return NULL;
  150.  
  151.    region = intel_region_alloc_internal(screen, cpp, width, height,
  152.                                         aligned_pitch, tiling, buffer);
  153.    if (region == NULL) {
  154.       drm_intel_bo_unreference(buffer);
  155.       return NULL;
  156.    }
  157.  
  158.    return region;
  159. }
  160.  
  161. bool
  162. intel_region_flink(struct intel_region *region, uint32_t *name)
  163. {
  164.    if (region->name == 0) {
  165.       if (drm_intel_bo_flink(region->bo, &region->name))
  166.          return false;
  167.    }
  168.  
  169.    *name = region->name;
  170.  
  171.    return true;
  172. }
  173.  
  174. struct intel_region *
  175. intel_region_alloc_for_handle(struct intel_screen *screen,
  176.                               GLuint cpp,
  177.                               GLuint width, GLuint height, GLuint pitch,
  178.                               GLuint handle, const char *name)
  179. {
  180.    struct intel_region *region;
  181.    drm_intel_bo *buffer;
  182.    int ret;
  183.    uint32_t bit_6_swizzle, tiling;
  184.  
  185.    buffer = intel_bo_gem_create_from_name(screen->bufmgr, name, handle);
  186.    if (buffer == NULL)
  187.       return NULL;
  188.    ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
  189.    if (ret != 0) {
  190.       fprintf(stderr, "Couldn't get tiling of buffer %d (%s): %s\n",
  191.               handle, name, strerror(-ret));
  192.       drm_intel_bo_unreference(buffer);
  193.       return NULL;
  194.    }
  195.  
  196.    region = intel_region_alloc_internal(screen, cpp,
  197.                                         width, height, pitch, tiling, buffer);
  198.    if (region == NULL) {
  199.       drm_intel_bo_unreference(buffer);
  200.       return NULL;
  201.    }
  202.  
  203.    region->name = handle;
  204.  
  205.    return region;
  206. }
  207.  
  208. #if 0
  209. struct intel_region *
  210. intel_region_alloc_for_fd(struct intel_screen *screen,
  211.                           GLuint cpp,
  212.                           GLuint width, GLuint height, GLuint pitch,
  213.                           int fd, const char *name)
  214. {
  215.    struct intel_region *region;
  216.    drm_intel_bo *buffer;
  217.    int ret;
  218.    uint32_t bit_6_swizzle, tiling;
  219.  
  220.    buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr,
  221.                                                fd, height * pitch);
  222.    if (buffer == NULL)
  223.       return NULL;
  224.    ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
  225.    if (ret != 0) {
  226.       fprintf(stderr, "Couldn't get tiling of buffer (%s): %s\n",
  227.               name, strerror(-ret));
  228.       drm_intel_bo_unreference(buffer);
  229.       return NULL;
  230.    }
  231.  
  232.    region = intel_region_alloc_internal(screen, cpp,
  233.                                         width, height, pitch, tiling, buffer);
  234.    if (region == NULL) {
  235.       drm_intel_bo_unreference(buffer);
  236.       return NULL;
  237.    }
  238.  
  239.    return region;
  240. }
  241. #endif
  242.  
  243. void
  244. intel_region_reference(struct intel_region **dst, struct intel_region *src)
  245. {
  246.    _DBG("%s: %p(%d) -> %p(%d)\n", __FUNCTION__,
  247.         *dst, *dst ? (*dst)->refcount : 0, src, src ? src->refcount : 0);
  248.  
  249.    if (src != *dst) {
  250.       if (*dst)
  251.          intel_region_release(dst);
  252.  
  253.       if (src)
  254.          src->refcount++;
  255.       *dst = src;
  256.    }
  257. }
  258.  
  259. void
  260. intel_region_release(struct intel_region **region_handle)
  261. {
  262.    struct intel_region *region = *region_handle;
  263.  
  264.    if (region == NULL) {
  265.       _DBG("%s NULL\n", __FUNCTION__);
  266.       return;
  267.    }
  268.  
  269.    _DBG("%s %p %d\n", __FUNCTION__, region, region->refcount - 1);
  270.  
  271.    ASSERT(region->refcount > 0);
  272.    region->refcount--;
  273.  
  274.    if (region->refcount == 0) {
  275.       drm_intel_bo_unreference(region->bo);
  276.  
  277.       free(region);
  278.    }
  279.    *region_handle = NULL;
  280. }
  281.  
  282. /**
  283.  * This function computes masks that may be used to select the bits of the X
  284.  * and Y coordinates that indicate the offset within a tile.  If the region is
  285.  * untiled, the masks are set to 0.
  286.  */
  287. void
  288. intel_region_get_tile_masks(struct intel_region *region,
  289.                             uint32_t *mask_x, uint32_t *mask_y,
  290.                             bool map_stencil_as_y_tiled)
  291. {
  292.    int cpp = region->cpp;
  293.    uint32_t tiling = region->tiling;
  294.  
  295.    if (map_stencil_as_y_tiled)
  296.       tiling = I915_TILING_Y;
  297.  
  298.    switch (tiling) {
  299.    default:
  300.       assert(false);
  301.    case I915_TILING_NONE:
  302.       *mask_x = *mask_y = 0;
  303.       break;
  304.    case I915_TILING_X:
  305.       *mask_x = 512 / cpp - 1;
  306.       *mask_y = 7;
  307.       break;
  308.    case I915_TILING_Y:
  309.       *mask_x = 128 / cpp - 1;
  310.       *mask_y = 31;
  311.       break;
  312.    }
  313. }
  314.  
  315. /**
  316.  * Compute the offset (in bytes) from the start of the region to the given x
  317.  * and y coordinate.  For tiled regions, caller must ensure that x and y are
  318.  * multiples of the tile size.
  319.  */
  320. uint32_t
  321. intel_region_get_aligned_offset(struct intel_region *region, uint32_t x,
  322.                                 uint32_t y, bool map_stencil_as_y_tiled)
  323. {
  324.    int cpp = region->cpp;
  325.    uint32_t pitch = region->pitch;
  326.    uint32_t tiling = region->tiling;
  327.  
  328.    if (map_stencil_as_y_tiled) {
  329.       tiling = I915_TILING_Y;
  330.  
  331.       /* When mapping a W-tiled stencil buffer as Y-tiled, each 64-high W-tile
  332.        * gets transformed into a 32-high Y-tile.  Accordingly, the pitch of
  333.        * the resulting region is twice the pitch of the original region, since
  334.        * each row in the Y-tiled view corresponds to two rows in the actual
  335.        * W-tiled surface.  So we need to correct the pitch before computing
  336.        * the offsets.
  337.        */
  338.       pitch *= 2;
  339.    }
  340.  
  341.    switch (tiling) {
  342.    default:
  343.       assert(false);
  344.    case I915_TILING_NONE:
  345.       return y * pitch + x * cpp;
  346.    case I915_TILING_X:
  347.       assert((x % (512 / cpp)) == 0);
  348.       assert((y % 8) == 0);
  349.       return y * pitch + x / (512 / cpp) * 4096;
  350.    case I915_TILING_Y:
  351.       assert((x % (128 / cpp)) == 0);
  352.       assert((y % 32) == 0);
  353.       return y * pitch + x / (128 / cpp) * 4096;
  354.    }
  355. }
  356.