Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | 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 "program/prog_instruction.h"
  37.  
  38. #include "st_context.h"
  39. #include "st_atom.h"
  40. #include "st_texture.h"
  41. #include "st_format.h"
  42. #include "st_cb_texture.h"
  43. #include "pipe/p_context.h"
  44. #include "util/u_format.h"
  45. #include "util/u_inlines.h"
  46. #include "cso_cache/cso_context.h"
  47.  
  48. /**
  49.  * Combine depth texture mode with "swizzle" so that depth mode swizzling
  50.  * takes place before texture swizzling, and return the resulting swizzle.
  51.  * If the format is not a depth format, return "swizzle" unchanged.
  52.  *
  53.  * \param format     PIPE_FORMAT_*.
  54.  * \param swizzle    Texture swizzle, a bitmask computed using MAKE_SWIZZLE4.
  55.  * \param depthmode  One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA, GL_RED.
  56.  */
  57. static GLuint apply_depthmode(enum pipe_format format,
  58.                               GLuint swizzle, GLenum depthmode)
  59. {
  60.    const struct util_format_description *desc =
  61.          util_format_description(format);
  62.    unsigned char swiz[4];
  63.    unsigned i;
  64.  
  65.    if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS ||
  66.        desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_NONE) {
  67.       /* Not a depth format. */
  68.       return swizzle;
  69.    }
  70.  
  71.    for (i = 0; i < 4; i++)
  72.       swiz[i] = GET_SWZ(swizzle, i);
  73.  
  74.    switch (depthmode) {
  75.       case GL_LUMINANCE:
  76.          /* Rewrite reads from W to ONE, and reads from XYZ to XXX. */
  77.          for (i = 0; i < 4; i++)
  78.             if (swiz[i] == SWIZZLE_W)
  79.                swiz[i] = SWIZZLE_ONE;
  80.             else if (swiz[i] < SWIZZLE_W)
  81.                swiz[i] = SWIZZLE_X;
  82.          break;
  83.  
  84.       case GL_INTENSITY:
  85.          /* Rewrite reads from XYZW to XXXX. */
  86.          for (i = 0; i < 4; i++)
  87.             if (swiz[i] <= SWIZZLE_W)
  88.                swiz[i] = SWIZZLE_X;
  89.          break;
  90.  
  91.       case GL_ALPHA:
  92.          /* Rewrite reads from W to X, and reads from XYZ to 000. */
  93.          for (i = 0; i < 4; i++)
  94.             if (swiz[i] == SWIZZLE_W)
  95.                swiz[i] = SWIZZLE_X;
  96.             else if (swiz[i] < SWIZZLE_W)
  97.                swiz[i] = SWIZZLE_ZERO;
  98.          break;
  99.       case GL_RED:
  100.          /* Rewrite reads W to 1, XYZ to X00 */
  101.          for (i = 0; i < 4; i++)
  102.             if (swiz[i] == SWIZZLE_W)
  103.                swiz[i] = SWIZZLE_ONE;
  104.             else if (swiz[i] == SWIZZLE_Y || swiz[i] == SWIZZLE_Z)
  105.                swiz[i] = SWIZZLE_ZERO;
  106.          break;
  107.    }
  108.  
  109.    return MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]);
  110. }
  111.  
  112. /**
  113.  * Return TRUE if the swizzling described by "swizzle" and
  114.  * "depthmode" (for depth textures only) is different from the swizzling
  115.  * set in the given sampler view.
  116.  *
  117.  * \param sv         A sampler view.
  118.  * \param swizzle    Texture swizzle, a bitmask computed using MAKE_SWIZZLE4.
  119.  * \param depthmode  One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA.
  120.  */
  121. static boolean check_sampler_swizzle(struct pipe_sampler_view *sv,
  122.                                      GLuint swizzle, GLenum depthmode)
  123. {
  124.    swizzle = apply_depthmode(sv->texture->format, swizzle, depthmode);
  125.  
  126.    if ((sv->swizzle_r != GET_SWZ(swizzle, 0)) ||
  127.        (sv->swizzle_g != GET_SWZ(swizzle, 1)) ||
  128.        (sv->swizzle_b != GET_SWZ(swizzle, 2)) ||
  129.        (sv->swizzle_a != GET_SWZ(swizzle, 3)))
  130.       return true;
  131.    return false;
  132. }
  133.  
  134. static INLINE struct pipe_sampler_view *
  135. st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
  136.                                           struct st_texture_object *stObj,
  137.                                           enum pipe_format format)
  138.                                          
  139. {
  140.    struct pipe_sampler_view templ;
  141.    GLuint swizzle = apply_depthmode(stObj->pt->format,
  142.                                     stObj->base._Swizzle,
  143.                                     stObj->base.DepthMode);
  144.  
  145.    u_sampler_view_default_template(&templ,
  146.                                    stObj->pt,
  147.                                    format);
  148.  
  149.    if (swizzle != SWIZZLE_NOOP) {
  150.       templ.swizzle_r = GET_SWZ(swizzle, 0);
  151.       templ.swizzle_g = GET_SWZ(swizzle, 1);
  152.       templ.swizzle_b = GET_SWZ(swizzle, 2);
  153.       templ.swizzle_a = GET_SWZ(swizzle, 3);
  154.    }
  155.  
  156.    return pipe->create_sampler_view(pipe, stObj->pt, &templ);
  157. }
  158.  
  159.  
  160. static INLINE struct pipe_sampler_view *
  161. st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj,
  162.                                        struct pipe_context *pipe,
  163.                                        enum pipe_format format)
  164.  
  165. {
  166.    if (!stObj || !stObj->pt) {
  167.       return NULL;
  168.    }
  169.  
  170.    if (!stObj->sampler_view) {
  171.       stObj->sampler_view = st_create_texture_sampler_view_from_stobj(pipe, stObj, format);
  172.    }
  173.  
  174.    return stObj->sampler_view;
  175. }
  176.  
  177. static void
  178. update_textures(struct st_context *st)
  179. {
  180.    struct pipe_context *pipe = st->pipe;
  181.    struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
  182.    struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
  183.    const GLbitfield samplersUsed = (vprog->Base.SamplersUsed |
  184.                                     fprog->Base.SamplersUsed);
  185.    GLuint su;
  186.  
  187.    st->state.num_textures = 0;
  188.  
  189.    /* loop over sampler units (aka tex image units) */
  190.    for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
  191.       struct pipe_sampler_view *sampler_view = NULL;
  192.       enum pipe_format st_view_format;
  193.       if (samplersUsed & (1 << su)) {
  194.          struct gl_texture_object *texObj;
  195.          struct st_texture_object *stObj;
  196.          GLboolean retval;
  197.          GLuint texUnit;
  198.  
  199.          if (fprog->Base.SamplersUsed & (1 << su))
  200.             texUnit = fprog->Base.SamplerUnits[su];
  201.          else
  202.             texUnit = vprog->Base.SamplerUnits[su];
  203.  
  204.          texObj = st->ctx->Texture.Unit[texUnit]._Current;
  205.  
  206.          if (!texObj) {
  207.             texObj = st_get_default_texture(st);
  208.          }
  209.          stObj = st_texture_object(texObj);
  210.  
  211.          retval = st_finalize_texture(st->ctx, st->pipe, texObj);
  212.          if (!retval) {
  213.             /* out of mem */
  214.             continue;
  215.          }
  216.  
  217.          st_view_format = stObj->pt->format;
  218.          {
  219.             struct st_texture_image *firstImage;
  220.             enum pipe_format firstImageFormat;
  221.             firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
  222.  
  223.             firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat);
  224.             if (firstImageFormat != stObj->pt->format)
  225.                st_view_format = firstImageFormat;
  226.  
  227.          }
  228.          st->state.num_textures = su + 1;
  229.  
  230.          /* if sampler view has changed dereference it */
  231.          if (stObj->sampler_view)
  232.             if (check_sampler_swizzle(stObj->sampler_view,
  233.                                       stObj->base._Swizzle,
  234.                                       stObj->base.DepthMode) ||
  235.                 (st_view_format != stObj->sampler_view->format))
  236.                pipe_sampler_view_reference(&stObj->sampler_view, NULL);
  237.  
  238.          sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe, st_view_format);
  239.       }
  240.       pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view);
  241.    }
  242.  
  243.    cso_set_fragment_sampler_views(st->cso_context,
  244.                                   st->state.num_textures,
  245.                                   st->state.sampler_views);
  246.    if (st->ctx->Const.MaxVertexTextureImageUnits > 0) {
  247.       cso_set_vertex_sampler_views(st->cso_context,
  248.                                    MIN2(st->state.num_textures,
  249.                                         st->ctx->Const.MaxVertexTextureImageUnits),
  250.                                    st->state.sampler_views);
  251.    }
  252. }
  253.  
  254.  
  255. const struct st_tracked_state st_update_texture = {
  256.    "st_update_texture",                                 /* name */
  257.    {                                                    /* dirty */
  258.       _NEW_TEXTURE,                                     /* mesa */
  259.       ST_NEW_FRAGMENT_PROGRAM,                          /* st */
  260.    },
  261.    update_textures                                      /* update */
  262. };
  263.  
  264.  
  265.  
  266.  
  267. static void
  268. finalize_textures(struct st_context *st)
  269. {
  270.    struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
  271.    const GLboolean prev_missing_textures = st->missing_textures;
  272.    GLuint su;
  273.  
  274.    st->missing_textures = GL_FALSE;
  275.  
  276.    for (su = 0; su < st->ctx->Const.MaxTextureCoordUnits; su++) {
  277.       if (fprog->Base.SamplersUsed & (1 << su)) {
  278.          const GLuint texUnit = fprog->Base.SamplerUnits[su];
  279.          struct gl_texture_object *texObj
  280.             = st->ctx->Texture.Unit[texUnit]._Current;
  281.  
  282.          if (texObj) {
  283.             GLboolean retval;
  284.  
  285.             retval = st_finalize_texture(st->ctx, st->pipe, texObj);
  286.             if (!retval) {
  287.                /* out of mem */
  288.                st->missing_textures = GL_TRUE;
  289.                continue;
  290.             }
  291.          }
  292.       }
  293.    }
  294.  
  295.    if (prev_missing_textures != st->missing_textures)
  296.       st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
  297. }
  298.  
  299.  
  300.  
  301. const struct st_tracked_state st_finalize_textures = {
  302.    "st_finalize_textures",              /* name */
  303.    {                                    /* dirty */
  304.       _NEW_TEXTURE,                     /* mesa */
  305.       0,                                /* st */
  306.    },
  307.    finalize_textures                    /* update */
  308. };
  309.