Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 VMware, Inc.
  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 VMWARE 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 <keithw@vmware.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/teximage.h"
  39. #include "main/texobj.h"
  40. #include "program/prog_instruction.h"
  41.  
  42. #include "st_context.h"
  43. #include "st_atom.h"
  44. #include "st_texture.h"
  45. #include "st_format.h"
  46. #include "st_cb_texture.h"
  47. #include "pipe/p_context.h"
  48. #include "util/u_format.h"
  49. #include "util/u_inlines.h"
  50. #include "cso_cache/cso_context.h"
  51.  
  52.  
  53. /**
  54.  * Return swizzle1(swizzle2)
  55.  */
  56. static unsigned
  57. swizzle_swizzle(unsigned swizzle1, unsigned swizzle2)
  58. {
  59.    unsigned i, swz[4];
  60.  
  61.    for (i = 0; i < 4; i++) {
  62.       unsigned s = GET_SWZ(swizzle1, i);
  63.       switch (s) {
  64.       case SWIZZLE_X:
  65.       case SWIZZLE_Y:
  66.       case SWIZZLE_Z:
  67.       case SWIZZLE_W:
  68.          swz[i] = GET_SWZ(swizzle2, s);
  69.          break;
  70.       case SWIZZLE_ZERO:
  71.          swz[i] = SWIZZLE_ZERO;
  72.          break;
  73.       case SWIZZLE_ONE:
  74.          swz[i] = SWIZZLE_ONE;
  75.          break;
  76.       default:
  77.          assert(!"Bad swizzle term");
  78.          swz[i] = SWIZZLE_X;
  79.       }
  80.    }
  81.  
  82.    return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
  83. }
  84.  
  85.  
  86. /**
  87.  * Given a user-specified texture base format, the actual gallium texture
  88.  * format and the current GL_DEPTH_MODE, return a texture swizzle.
  89.  *
  90.  * Consider the case where the user requests a GL_RGB internal texture
  91.  * format the driver actually uses an RGBA format.  The A component should
  92.  * be ignored and sampling from the texture should always return (r,g,b,1).
  93.  * But if we rendered to the texture we might have written A values != 1.
  94.  * By sampling the texture with a ".xyz1" swizzle we'll get the expected A=1.
  95.  * This function computes the texture swizzle needed to get the expected
  96.  * values.
  97.  *
  98.  * In the case of depth textures, the GL_DEPTH_MODE state determines the
  99.  * texture swizzle.
  100.  *
  101.  * This result must be composed with the user-specified swizzle to get
  102.  * the final swizzle.
  103.  */
  104. static unsigned
  105. compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode,
  106.                                enum pipe_format actualFormat)
  107. {
  108.    switch (baseFormat) {
  109.    case GL_RGBA:
  110.       return SWIZZLE_XYZW;
  111.    case GL_RGB:
  112.       if (util_format_has_alpha(actualFormat))
  113.          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE);
  114.       else
  115.          return SWIZZLE_XYZW;
  116.    case GL_RG:
  117.       if (util_format_get_nr_components(actualFormat) > 2)
  118.          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE);
  119.       else
  120.          return SWIZZLE_XYZW;
  121.    case GL_RED:
  122.       if (util_format_get_nr_components(actualFormat) > 1)
  123.          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
  124.                               SWIZZLE_ZERO, SWIZZLE_ONE);
  125.       else
  126.          return SWIZZLE_XYZW;
  127.    case GL_ALPHA:
  128.       if (util_format_get_nr_components(actualFormat) > 1)
  129.          return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
  130.                               SWIZZLE_ZERO, SWIZZLE_W);
  131.       else
  132.          return SWIZZLE_XYZW;
  133.    case GL_LUMINANCE:
  134.       if (util_format_get_nr_components(actualFormat) > 1)
  135.          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
  136.       else
  137.          return SWIZZLE_XYZW;
  138.    case GL_LUMINANCE_ALPHA:
  139.       if (util_format_get_nr_components(actualFormat) > 2)
  140.          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W);
  141.       else
  142.          return SWIZZLE_XYZW;
  143.    case GL_INTENSITY:
  144.       if (util_format_get_nr_components(actualFormat) > 1)
  145.          return SWIZZLE_XXXX;
  146.       else
  147.          return SWIZZLE_XYZW;
  148.    case GL_STENCIL_INDEX:
  149.       return SWIZZLE_XYZW;
  150.    case GL_DEPTH_STENCIL:
  151.       /* fall-through */
  152.    case GL_DEPTH_COMPONENT:
  153.       /* Now examine the depth mode */
  154.       switch (depthMode) {
  155.       case GL_LUMINANCE:
  156.          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
  157.       case GL_INTENSITY:
  158.          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
  159.       case GL_ALPHA:
  160.          return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
  161.                               SWIZZLE_ZERO, SWIZZLE_X);
  162.       case GL_RED:
  163.          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
  164.                               SWIZZLE_ZERO, SWIZZLE_ONE);
  165.       default:
  166.          assert(!"Unexpected depthMode");
  167.          return SWIZZLE_XYZW;
  168.       }
  169.    default:
  170.       assert(!"Unexpected baseFormat");
  171.       return SWIZZLE_XYZW;
  172.    }
  173. }
  174.  
  175.  
  176. static unsigned
  177. get_texture_format_swizzle(const struct st_texture_object *stObj)
  178. {
  179.    GLenum baseFormat = _mesa_texture_base_format(&stObj->base);
  180.    unsigned tex_swizzle;
  181.  
  182.    if (baseFormat != GL_NONE) {
  183.       tex_swizzle = compute_texture_format_swizzle(baseFormat,
  184.                                                    stObj->base.DepthMode,
  185.                                                    stObj->pt->format);
  186.    }
  187.    else {
  188.       tex_swizzle = SWIZZLE_XYZW;
  189.    }
  190.  
  191.    /* Combine the texture format swizzle with user's swizzle */
  192.    return swizzle_swizzle(stObj->base._Swizzle, tex_swizzle);
  193. }
  194.  
  195.  
  196. /**
  197.  * Return TRUE if the texture's sampler view swizzle is not equal to
  198.  * the texture's swizzle.
  199.  *
  200.  * \param stObj  the st texture object,
  201.  */
  202. static boolean
  203. check_sampler_swizzle(const struct st_texture_object *stObj,
  204.                       struct pipe_sampler_view *sv)
  205. {
  206.    unsigned swizzle = get_texture_format_swizzle(stObj);
  207.  
  208.    return ((sv->swizzle_r != GET_SWZ(swizzle, 0)) ||
  209.            (sv->swizzle_g != GET_SWZ(swizzle, 1)) ||
  210.            (sv->swizzle_b != GET_SWZ(swizzle, 2)) ||
  211.            (sv->swizzle_a != GET_SWZ(swizzle, 3)));
  212. }
  213.  
  214.  
  215. static unsigned last_level(struct st_texture_object *stObj)
  216. {
  217.    unsigned ret = MIN2(stObj->base.MinLevel + stObj->base._MaxLevel,
  218.                        stObj->pt->last_level);
  219.    if (stObj->base.Immutable)
  220.       ret = MIN2(ret, stObj->base.MinLevel + stObj->base.NumLevels - 1);
  221.    return ret;
  222. }
  223.  
  224. static unsigned last_layer(struct st_texture_object *stObj)
  225. {
  226.    if (stObj->base.Immutable && stObj->pt->array_size > 1)
  227.       return MIN2(stObj->base.MinLayer + stObj->base.NumLayers - 1,
  228.                   stObj->pt->array_size - 1);
  229.    return stObj->pt->array_size - 1;
  230. }
  231.  
  232. static struct pipe_sampler_view *
  233. st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
  234.                                           struct st_texture_object *stObj,
  235.                                           const struct gl_sampler_object *samp,
  236.                                           enum pipe_format format)
  237. {
  238.    struct pipe_sampler_view templ;
  239.    unsigned swizzle = get_texture_format_swizzle(stObj);
  240.  
  241.    u_sampler_view_default_template(&templ,
  242.                                    stObj->pt,
  243.                                    format);
  244.  
  245.    if (stObj->pt->target == PIPE_BUFFER) {
  246.       unsigned base, size;
  247.       unsigned f, n;
  248.       const struct util_format_description *desc
  249.          = util_format_description(templ.format);
  250.  
  251.       base = stObj->base.BufferOffset;
  252.       if (base >= stObj->pt->width0)
  253.          return NULL;
  254.       size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
  255.  
  256.       f = ((base * 8) / desc->block.bits) * desc->block.width;
  257.       n = ((size * 8) / desc->block.bits) * desc->block.width;
  258.       if (!n)
  259.          return NULL;
  260.       templ.u.buf.first_element = f;
  261.       templ.u.buf.last_element  = f + (n - 1);
  262.    } else {
  263.       templ.u.tex.first_level = stObj->base.MinLevel + stObj->base.BaseLevel;
  264.       templ.u.tex.last_level = last_level(stObj);
  265.       assert(templ.u.tex.first_level <= templ.u.tex.last_level);
  266.       templ.u.tex.first_layer = stObj->base.MinLayer;
  267.       templ.u.tex.last_layer = last_layer(stObj);
  268.       assert(templ.u.tex.first_layer <= templ.u.tex.last_layer);
  269.       templ.target = gl_target_to_pipe(stObj->base.Target);
  270.    }
  271.  
  272.    if (swizzle != SWIZZLE_NOOP) {
  273.       templ.swizzle_r = GET_SWZ(swizzle, 0);
  274.       templ.swizzle_g = GET_SWZ(swizzle, 1);
  275.       templ.swizzle_b = GET_SWZ(swizzle, 2);
  276.       templ.swizzle_a = GET_SWZ(swizzle, 3);
  277.    }
  278.  
  279.    return pipe->create_sampler_view(pipe, stObj->pt, &templ);
  280. }
  281.  
  282.  
  283. static struct pipe_sampler_view *
  284. st_get_texture_sampler_view_from_stobj(struct st_context *st,
  285.                                        struct st_texture_object *stObj,
  286.                                        const struct gl_sampler_object *samp,
  287.                                        enum pipe_format format)
  288. {
  289.    struct pipe_sampler_view **sv;
  290.    const struct st_texture_image *firstImage;
  291.    if (!stObj || !stObj->pt) {
  292.       return NULL;
  293.    }
  294.  
  295.    sv = st_texture_get_sampler_view(st, stObj);
  296.  
  297.    if (util_format_is_depth_and_stencil(format)) {
  298.       if (stObj->base.StencilSampling)
  299.          format = util_format_stencil_only(format);
  300.       else {
  301.          firstImage = st_texture_image_const(_mesa_base_tex_image(&stObj->base));
  302.          if (firstImage->base._BaseFormat == GL_STENCIL_INDEX)
  303.             format = util_format_stencil_only(format);
  304.       }
  305.    }
  306.  
  307.    /* if sampler view has changed dereference it */
  308.    if (*sv) {
  309.       if (check_sampler_swizzle(stObj, *sv) ||
  310.           (format != (*sv)->format) ||
  311.           gl_target_to_pipe(stObj->base.Target) != (*sv)->target ||
  312.           stObj->base.MinLevel + stObj->base.BaseLevel != (*sv)->u.tex.first_level ||
  313.           last_level(stObj) != (*sv)->u.tex.last_level ||
  314.           stObj->base.MinLayer != (*sv)->u.tex.first_layer ||
  315.           last_layer(stObj) != (*sv)->u.tex.last_layer) {
  316.          pipe_sampler_view_reference(sv, NULL);
  317.       }
  318.    }
  319.  
  320.    if (!*sv) {
  321.       *sv = st_create_texture_sampler_view_from_stobj(st->pipe, stObj, samp, format);
  322.  
  323.    } else if ((*sv)->context != st->pipe) {
  324.       /* Recreate view in correct context, use existing view as template */
  325.       struct pipe_sampler_view *new_sv =
  326.          st->pipe->create_sampler_view(st->pipe, stObj->pt, *sv);
  327.       pipe_sampler_view_reference(sv, NULL);
  328.       *sv = new_sv;
  329.    }
  330.  
  331.    return *sv;
  332. }
  333.  
  334. static GLboolean
  335. update_single_texture(struct st_context *st,
  336.                       struct pipe_sampler_view **sampler_view,
  337.                       GLuint texUnit)
  338. {
  339.    struct gl_context *ctx = st->ctx;
  340.    const struct gl_sampler_object *samp;
  341.    struct gl_texture_object *texObj;
  342.    struct st_texture_object *stObj;
  343.    enum pipe_format view_format;
  344.    GLboolean retval;
  345.  
  346.    samp = _mesa_get_samplerobj(ctx, texUnit);
  347.  
  348.    texObj = ctx->Texture.Unit[texUnit]._Current;
  349.  
  350.    if (!texObj) {
  351.       texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
  352.       samp = &texObj->Sampler;
  353.    }
  354.    stObj = st_texture_object(texObj);
  355.  
  356.    retval = st_finalize_texture(ctx, st->pipe, texObj);
  357.    if (!retval) {
  358.       /* out of mem */
  359.       return GL_FALSE;
  360.    }
  361.  
  362.    /* Determine the format of the texture sampler view */
  363.    if (texObj->Target == GL_TEXTURE_BUFFER) {
  364.       view_format =
  365.          st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat);
  366.    }
  367.    else {
  368.       view_format =
  369.          stObj->surface_based ? stObj->surface_format : stObj->pt->format;
  370.  
  371.       /* If sRGB decoding is off, use the linear format */
  372.       if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
  373.          view_format = util_format_linear(view_format);
  374.       }
  375.    }
  376.  
  377.    *sampler_view = st_get_texture_sampler_view_from_stobj(st, stObj, samp,
  378.                                                           view_format);
  379.    return GL_TRUE;
  380. }
  381.  
  382.  
  383.  
  384. static void
  385. update_textures(struct st_context *st,
  386.                 unsigned shader_stage,
  387.                 const struct gl_program *prog,
  388.                 unsigned max_units,
  389.                 struct pipe_sampler_view **sampler_views,
  390.                 unsigned *num_textures)
  391. {
  392.    const GLuint old_max = *num_textures;
  393.    GLbitfield samplers_used = prog->SamplersUsed;
  394.    GLuint unit;
  395.  
  396.    if (samplers_used == 0x0 && old_max == 0)
  397.       return;
  398.  
  399.    *num_textures = 0;
  400.  
  401.    /* loop over sampler units (aka tex image units) */
  402.    for (unit = 0; unit < max_units; unit++, samplers_used >>= 1) {
  403.       struct pipe_sampler_view *sampler_view = NULL;
  404.  
  405.       if (samplers_used & 1) {
  406.          const GLuint texUnit = prog->SamplerUnits[unit];
  407.          GLboolean retval;
  408.  
  409.          retval = update_single_texture(st, &sampler_view, texUnit);
  410.          if (retval == GL_FALSE)
  411.             continue;
  412.  
  413.          *num_textures = unit + 1;
  414.       }
  415.       else if (samplers_used == 0 && unit >= old_max) {
  416.          /* if we've reset all the old views and we have no more new ones */
  417.          break;
  418.       }
  419.  
  420.       pipe_sampler_view_reference(&(sampler_views[unit]), sampler_view);
  421.    }
  422.  
  423.    cso_set_sampler_views(st->cso_context,
  424.                          shader_stage,
  425.                          *num_textures,
  426.                          sampler_views);
  427. }
  428.  
  429.  
  430.  
  431. static void
  432. update_vertex_textures(struct st_context *st)
  433. {
  434.    const struct gl_context *ctx = st->ctx;
  435.  
  436.    if (ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits > 0) {
  437.       update_textures(st,
  438.                       PIPE_SHADER_VERTEX,
  439.                       &ctx->VertexProgram._Current->Base,
  440.                       ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits,
  441.                       st->state.sampler_views[PIPE_SHADER_VERTEX],
  442.                       &st->state.num_sampler_views[PIPE_SHADER_VERTEX]);
  443.    }
  444. }
  445.  
  446.  
  447. static void
  448. update_fragment_textures(struct st_context *st)
  449. {
  450.    const struct gl_context *ctx = st->ctx;
  451.  
  452.    update_textures(st,
  453.                    PIPE_SHADER_FRAGMENT,
  454.                    &ctx->FragmentProgram._Current->Base,
  455.                    ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits,
  456.                    st->state.sampler_views[PIPE_SHADER_FRAGMENT],
  457.                    &st->state.num_sampler_views[PIPE_SHADER_FRAGMENT]);
  458. }
  459.  
  460.  
  461. static void
  462. update_geometry_textures(struct st_context *st)
  463. {
  464.    const struct gl_context *ctx = st->ctx;
  465.  
  466.    if (ctx->GeometryProgram._Current) {
  467.       update_textures(st,
  468.                       PIPE_SHADER_GEOMETRY,
  469.                       &ctx->GeometryProgram._Current->Base,
  470.                       ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits,
  471.                       st->state.sampler_views[PIPE_SHADER_GEOMETRY],
  472.                       &st->state.num_sampler_views[PIPE_SHADER_GEOMETRY]);
  473.    }
  474. }
  475.  
  476.  
  477. const struct st_tracked_state st_update_fragment_texture = {
  478.    "st_update_texture",                                 /* name */
  479.    {                                                    /* dirty */
  480.       _NEW_TEXTURE,                                     /* mesa */
  481.       ST_NEW_FRAGMENT_PROGRAM,                          /* st */
  482.    },
  483.    update_fragment_textures                             /* update */
  484. };
  485.  
  486.  
  487. const struct st_tracked_state st_update_vertex_texture = {
  488.    "st_update_vertex_texture",                          /* name */
  489.    {                                                    /* dirty */
  490.       _NEW_TEXTURE,                                     /* mesa */
  491.       ST_NEW_VERTEX_PROGRAM,                            /* st */
  492.    },
  493.    update_vertex_textures                               /* update */
  494. };
  495.  
  496.  
  497. const struct st_tracked_state st_update_geometry_texture = {
  498.    "st_update_geometry_texture",                        /* name */
  499.    {                                                    /* dirty */
  500.       _NEW_TEXTURE,                                     /* mesa */
  501.       ST_NEW_GEOMETRY_PROGRAM,                          /* st */
  502.    },
  503.    update_geometry_textures                             /* update */
  504. };
  505.  
  506.  
  507.  
  508. static void
  509. finalize_textures(struct st_context *st)
  510. {
  511.    struct gl_context *ctx = st->ctx;
  512.    struct gl_fragment_program *fprog = ctx->FragmentProgram._Current;
  513.    const GLboolean prev_missing_textures = st->missing_textures;
  514.    GLuint su;
  515.  
  516.    st->missing_textures = GL_FALSE;
  517.  
  518.    for (su = 0; su < ctx->Const.MaxTextureCoordUnits; su++) {
  519.       if (fprog->Base.SamplersUsed & (1 << su)) {
  520.          const GLuint texUnit = fprog->Base.SamplerUnits[su];
  521.          struct gl_texture_object *texObj
  522.             = ctx->Texture.Unit[texUnit]._Current;
  523.  
  524.          if (texObj) {
  525.             GLboolean retval;
  526.  
  527.             retval = st_finalize_texture(ctx, st->pipe, texObj);
  528.             if (!retval) {
  529.                /* out of mem */
  530.                st->missing_textures = GL_TRUE;
  531.                continue;
  532.             }
  533.          }
  534.       }
  535.    }
  536.  
  537.    if (prev_missing_textures != st->missing_textures)
  538.       st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
  539. }
  540.  
  541.  
  542. const struct st_tracked_state st_finalize_textures = {
  543.    "st_finalize_textures",              /* name */
  544.    {                                    /* dirty */
  545.       _NEW_TEXTURE,                     /* mesa */
  546.       0,                                /* st */
  547.    },
  548.    finalize_textures                    /* update */
  549. };
  550.