Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 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.  /*
  29.   * Authors:
  30.   *   Keith Whitwell <keith@tungstengraphics.com>
  31.   *   Brian Paul
  32.   */
  33.  
  34.  
  35. #include "main/macros.h"
  36. #include "main/mtypes.h"
  37. #include "main/samplerobj.h"
  38. #include "main/texobj.h"
  39. #include "program/prog_instruction.h"
  40.  
  41. #include "st_context.h"
  42. #include "st_atom.h"
  43. #include "st_texture.h"
  44. #include "st_format.h"
  45. #include "st_cb_texture.h"
  46. #include "pipe/p_context.h"
  47. #include "util/u_format.h"
  48. #include "util/u_inlines.h"
  49. #include "cso_cache/cso_context.h"
  50.  
  51.  
  52. /**
  53.  * Combine depth texture mode with "swizzle" so that depth mode swizzling
  54.  * takes place before texture swizzling, and return the resulting swizzle.
  55.  * If the format is not a depth format, return "swizzle" unchanged.
  56.  *
  57.  * \param format     PIPE_FORMAT_*.
  58.  * \param swizzle    Texture swizzle, a bitmask computed using MAKE_SWIZZLE4.
  59.  * \param depthmode  One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA, GL_RED.
  60.  */
  61. static GLuint
  62. apply_depthmode(enum pipe_format format, GLuint swizzle, GLenum depthmode)
  63. {
  64.    const struct util_format_description *desc =
  65.          util_format_description(format);
  66.    unsigned char swiz[4];
  67.    unsigned i;
  68.  
  69.    if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS ||
  70.        desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_NONE) {
  71.       /* Not a depth format. */
  72.       return swizzle;
  73.    }
  74.  
  75.    for (i = 0; i < 4; i++)
  76.       swiz[i] = GET_SWZ(swizzle, i);
  77.  
  78.    switch (depthmode) {
  79.       case GL_LUMINANCE:
  80.          /* Rewrite reads from W to ONE, and reads from XYZ to XXX. */
  81.          for (i = 0; i < 4; i++)
  82.             if (swiz[i] == SWIZZLE_W)
  83.                swiz[i] = SWIZZLE_ONE;
  84.             else if (swiz[i] < SWIZZLE_W)
  85.                swiz[i] = SWIZZLE_X;
  86.          break;
  87.  
  88.       case GL_INTENSITY:
  89.          /* Rewrite reads from XYZW to XXXX. */
  90.          for (i = 0; i < 4; i++)
  91.             if (swiz[i] <= SWIZZLE_W)
  92.                swiz[i] = SWIZZLE_X;
  93.          break;
  94.  
  95.       case GL_ALPHA:
  96.          /* Rewrite reads from W to X, and reads from XYZ to 000. */
  97.          for (i = 0; i < 4; i++)
  98.             if (swiz[i] == SWIZZLE_W)
  99.                swiz[i] = SWIZZLE_X;
  100.             else if (swiz[i] < SWIZZLE_W)
  101.                swiz[i] = SWIZZLE_ZERO;
  102.          break;
  103.       case GL_RED:
  104.          /* Rewrite reads W to 1, XYZ to X00 */
  105.          for (i = 0; i < 4; i++)
  106.             if (swiz[i] == SWIZZLE_W)
  107.                swiz[i] = SWIZZLE_ONE;
  108.             else if (swiz[i] == SWIZZLE_Y || swiz[i] == SWIZZLE_Z)
  109.                swiz[i] = SWIZZLE_ZERO;
  110.          break;
  111.    }
  112.  
  113.    return MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]);
  114. }
  115.  
  116.  
  117. /**
  118.  * Return TRUE if the swizzling described by "swizzle" and
  119.  * "depthmode" (for depth textures only) is different from the swizzling
  120.  * set in the given sampler view.
  121.  *
  122.  * \param sv         A sampler view.
  123.  * \param swizzle    Texture swizzle, a bitmask computed using MAKE_SWIZZLE4.
  124.  * \param depthmode  One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA.
  125.  */
  126. static boolean
  127. check_sampler_swizzle(struct pipe_sampler_view *sv,
  128.                       GLuint swizzle, GLenum depthmode)
  129. {
  130.    swizzle = apply_depthmode(sv->texture->format, swizzle, depthmode);
  131.  
  132.    if ((sv->swizzle_r != GET_SWZ(swizzle, 0)) ||
  133.        (sv->swizzle_g != GET_SWZ(swizzle, 1)) ||
  134.        (sv->swizzle_b != GET_SWZ(swizzle, 2)) ||
  135.        (sv->swizzle_a != GET_SWZ(swizzle, 3)))
  136.       return TRUE;
  137.    return FALSE;
  138. }
  139.  
  140.  
  141. static struct pipe_sampler_view *
  142. st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
  143.                                           struct st_texture_object *stObj,
  144.                                           const struct gl_sampler_object *samp,
  145.                                           enum pipe_format format)
  146. {
  147.    struct pipe_sampler_view templ;
  148.    GLuint swizzle = apply_depthmode(stObj->pt->format,
  149.                                     stObj->base._Swizzle,
  150.                                     stObj->base.DepthMode);
  151.  
  152.    u_sampler_view_default_template(&templ,
  153.                                    stObj->pt,
  154.                                    format);
  155.  
  156.    if (stObj->pt->target == PIPE_BUFFER) {
  157.       unsigned base, size;
  158.       unsigned f, n;
  159.       const struct util_format_description *desc
  160.          = util_format_description(templ.format);
  161.  
  162.       base = stObj->base.BufferOffset;
  163.       if (base >= stObj->pt->width0)
  164.          return NULL;
  165.       size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
  166.  
  167.       f = ((base * 8) / desc->block.bits) * desc->block.width;
  168.       n = ((size * 8) / desc->block.bits) * desc->block.width;
  169.       if (!n)
  170.          return NULL;
  171.       templ.u.buf.first_element = f;
  172.       templ.u.buf.last_element  = f + (n - 1);
  173.    } else {
  174.       templ.u.tex.first_level = stObj->base.BaseLevel;
  175.    }
  176.  
  177.    if (swizzle != SWIZZLE_NOOP) {
  178.       templ.swizzle_r = GET_SWZ(swizzle, 0);
  179.       templ.swizzle_g = GET_SWZ(swizzle, 1);
  180.       templ.swizzle_b = GET_SWZ(swizzle, 2);
  181.       templ.swizzle_a = GET_SWZ(swizzle, 3);
  182.    }
  183.  
  184.    return pipe->create_sampler_view(pipe, stObj->pt, &templ);
  185. }
  186.  
  187.  
  188. static struct pipe_sampler_view *
  189. st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj,
  190.                                        struct pipe_context *pipe,
  191.                                        const struct gl_sampler_object *samp,
  192.                                        enum pipe_format format)
  193. {
  194.    if (!stObj || !stObj->pt) {
  195.       return NULL;
  196.    }
  197.  
  198.    if (!stObj->sampler_view) {
  199.       stObj->sampler_view =
  200.          st_create_texture_sampler_view_from_stobj(pipe, stObj, samp, format);
  201.    }
  202.  
  203.    return stObj->sampler_view;
  204. }
  205.  
  206.  
  207. static GLboolean
  208. update_single_texture(struct st_context *st,
  209.                       struct pipe_sampler_view **sampler_view,
  210.                       GLuint texUnit)
  211. {
  212.    struct pipe_context *pipe = st->pipe;
  213.    struct gl_context *ctx = st->ctx;
  214.    const struct gl_sampler_object *samp;
  215.    struct gl_texture_object *texObj;
  216.    struct st_texture_object *stObj;
  217.    enum pipe_format view_format;
  218.    GLboolean retval;
  219.  
  220.    samp = _mesa_get_samplerobj(ctx, texUnit);
  221.  
  222.    texObj = ctx->Texture.Unit[texUnit]._Current;
  223.  
  224.    if (!texObj) {
  225.       texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
  226.       samp = &texObj->Sampler;
  227.    }
  228.    stObj = st_texture_object(texObj);
  229.  
  230.    retval = st_finalize_texture(ctx, st->pipe, texObj);
  231.    if (!retval) {
  232.       /* out of mem */
  233.       return GL_FALSE;
  234.    }
  235.  
  236.    /* Determine the format of the texture sampler view */
  237.    if (texObj->Target == GL_TEXTURE_BUFFER) {
  238.       view_format =
  239.          st_mesa_format_to_pipe_format(stObj->base._BufferObjectFormat);
  240.    }
  241.    else {
  242.       view_format =
  243.          stObj->surface_based ? stObj->surface_format : stObj->pt->format;
  244.  
  245.       /* If sRGB decoding is off, use the linear format */
  246.       if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
  247.          view_format = util_format_linear(view_format);
  248.       }
  249.    }
  250.  
  251.    /* if sampler view has changed dereference it */
  252.    if (stObj->sampler_view) {
  253.       if (check_sampler_swizzle(stObj->sampler_view,
  254.                                 stObj->base._Swizzle,
  255.                                 stObj->base.DepthMode) ||
  256.           (view_format != stObj->sampler_view->format) ||
  257.           stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) {
  258.          pipe_sampler_view_reference(&stObj->sampler_view, NULL);
  259.       }
  260.    }
  261.  
  262.    *sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe,
  263.                                                           samp,
  264.                                                           view_format);
  265.    return GL_TRUE;
  266. }
  267.  
  268.  
  269.  
  270. static void
  271. update_textures(struct st_context *st,
  272.                 unsigned shader_stage,
  273.                 const struct gl_program *prog,
  274.                 unsigned max_units,
  275.                 struct pipe_sampler_view **sampler_views,
  276.                 unsigned *num_textures)
  277. {
  278.    const GLuint old_max = *num_textures;
  279.    GLbitfield samplers_used = prog->SamplersUsed;
  280.    GLuint unit, new_count;
  281.  
  282.    if (samplers_used == 0x0 && old_max == 0)
  283.       return;
  284.  
  285.    *num_textures = 0;
  286.  
  287.    /* loop over sampler units (aka tex image units) */
  288.    for (unit = 0; unit < max_units; unit++, samplers_used >>= 1) {
  289.       struct pipe_sampler_view *sampler_view = NULL;
  290.  
  291.       if (samplers_used & 1) {
  292.          const GLuint texUnit = prog->SamplerUnits[unit];
  293.          GLboolean retval;
  294.  
  295.          retval = update_single_texture(st, &sampler_view, texUnit);
  296.          if (retval == GL_FALSE)
  297.             continue;
  298.  
  299.          *num_textures = unit + 1;
  300.       }
  301.       else if (samplers_used == 0 && unit >= old_max) {
  302.          /* if we've reset all the old views and we have no more new ones */
  303.          break;
  304.       }
  305.  
  306.       pipe_sampler_view_reference(&(sampler_views[unit]), sampler_view);
  307.    }
  308.  
  309.    /* Ex: if old_max = 3 and *num_textures = 1, we need to pass an
  310.     * array of views={X, NULL, NULL} to unref the old texture views
  311.     * at positions [1] and [2].
  312.     */
  313.    new_count = MAX2(*num_textures, old_max);
  314.    assert(new_count <= max_units);
  315.  
  316.    cso_set_sampler_views(st->cso_context,
  317.                          shader_stage,
  318.                          new_count,
  319.                          sampler_views);
  320. }
  321.  
  322.  
  323.  
  324. static void
  325. update_vertex_textures(struct st_context *st)
  326. {
  327.    const struct gl_context *ctx = st->ctx;
  328.  
  329.    if (ctx->Const.VertexProgram.MaxTextureImageUnits > 0) {
  330.       update_textures(st,
  331.                       PIPE_SHADER_VERTEX,
  332.                       &ctx->VertexProgram._Current->Base,
  333.                       ctx->Const.VertexProgram.MaxTextureImageUnits,
  334.                       st->state.sampler_views[PIPE_SHADER_VERTEX],
  335.                       &st->state.num_sampler_views[PIPE_SHADER_VERTEX]);
  336.    }
  337. }
  338.  
  339.  
  340. static void
  341. update_fragment_textures(struct st_context *st)
  342. {
  343.    const struct gl_context *ctx = st->ctx;
  344.  
  345.    update_textures(st,
  346.                    PIPE_SHADER_FRAGMENT,
  347.                    &ctx->FragmentProgram._Current->Base,
  348.                    ctx->Const.FragmentProgram.MaxTextureImageUnits,
  349.                    st->state.sampler_views[PIPE_SHADER_FRAGMENT],
  350.                    &st->state.num_sampler_views[PIPE_SHADER_FRAGMENT]);
  351. }
  352.  
  353.  
  354. static void
  355. update_geometry_textures(struct st_context *st)
  356. {
  357.    const struct gl_context *ctx = st->ctx;
  358.  
  359.    if (ctx->GeometryProgram._Current) {
  360.       update_textures(st,
  361.                       PIPE_SHADER_GEOMETRY,
  362.                       &ctx->GeometryProgram._Current->Base,
  363.                       ctx->Const.FragmentProgram.MaxTextureImageUnits,
  364.                       st->state.sampler_views[PIPE_SHADER_GEOMETRY],
  365.                       &st->state.num_sampler_views[PIPE_SHADER_GEOMETRY]);
  366.    }
  367. }
  368.  
  369.  
  370. const struct st_tracked_state st_update_fragment_texture = {
  371.    "st_update_texture",                                 /* name */
  372.    {                                                    /* dirty */
  373.       _NEW_TEXTURE,                                     /* mesa */
  374.       ST_NEW_FRAGMENT_PROGRAM,                          /* st */
  375.    },
  376.    update_fragment_textures                             /* update */
  377. };
  378.  
  379.  
  380. const struct st_tracked_state st_update_vertex_texture = {
  381.    "st_update_vertex_texture",                          /* name */
  382.    {                                                    /* dirty */
  383.       _NEW_TEXTURE,                                     /* mesa */
  384.       ST_NEW_VERTEX_PROGRAM,                            /* st */
  385.    },
  386.    update_vertex_textures                               /* update */
  387. };
  388.  
  389.  
  390. const struct st_tracked_state st_update_geometry_texture = {
  391.    "st_update_geometry_texture",                        /* name */
  392.    {                                                    /* dirty */
  393.       _NEW_TEXTURE,                                     /* mesa */
  394.       ST_NEW_GEOMETRY_PROGRAM,                          /* st */
  395.    },
  396.    update_geometry_textures                             /* update */
  397. };
  398.  
  399.  
  400.  
  401. static void
  402. finalize_textures(struct st_context *st)
  403. {
  404.    struct gl_context *ctx = st->ctx;
  405.    struct gl_fragment_program *fprog = ctx->FragmentProgram._Current;
  406.    const GLboolean prev_missing_textures = st->missing_textures;
  407.    GLuint su;
  408.  
  409.    st->missing_textures = GL_FALSE;
  410.  
  411.    for (su = 0; su < ctx->Const.MaxTextureCoordUnits; su++) {
  412.       if (fprog->Base.SamplersUsed & (1 << su)) {
  413.          const GLuint texUnit = fprog->Base.SamplerUnits[su];
  414.          struct gl_texture_object *texObj
  415.             = ctx->Texture.Unit[texUnit]._Current;
  416.  
  417.          if (texObj) {
  418.             GLboolean retval;
  419.  
  420.             retval = st_finalize_texture(ctx, st->pipe, texObj);
  421.             if (!retval) {
  422.                /* out of mem */
  423.                st->missing_textures = GL_TRUE;
  424.                continue;
  425.             }
  426.          }
  427.       }
  428.    }
  429.  
  430.    if (prev_missing_textures != st->missing_textures)
  431.       st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
  432. }
  433.  
  434.  
  435. const struct st_tracked_state st_finalize_textures = {
  436.    "st_finalize_textures",              /* name */
  437.    {                                    /* dirty */
  438.       _NEW_TEXTURE,                     /* mesa */
  439.       0,                                /* st */
  440.    },
  441.    finalize_textures                    /* update */
  442. };
  443.