Пример #1
0
void
_mesa_update_fetch_functions(struct gl_context *ctx, GLuint unit)
{
   struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
   struct gl_sampler_object *samp;
   GLuint face, i;
   GLuint dims;

   if (!texObj)
      return;

   samp = _mesa_get_samplerobj(ctx, unit);

   dims = _mesa_get_texture_dimensions(texObj->Target);

   for (face = 0; face < 6; face++) {
      for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
         if (texObj->Image[face][i]) {
	    set_fetch_functions(samp,
                                swrast_texture_image(texObj->Image[face][i]),
                                dims);
         }
      }
   }
}
Пример #2
0
static GLboolean
update_single_texture(struct st_context *st,
                      struct pipe_sampler_view **sampler_view,
                      GLuint texUnit)
{
    struct pipe_context *pipe = st->pipe;
    struct gl_context *ctx = st->ctx;
    const struct gl_sampler_object *samp;
    struct gl_texture_object *texObj;
    struct st_texture_object *stObj;
    enum pipe_format view_format;
    GLboolean retval;

    samp = _mesa_get_samplerobj(ctx, texUnit);

    texObj = ctx->Texture.Unit[texUnit]._Current;

    if (!texObj) {
        texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
        samp = &texObj->Sampler;
    }
    stObj = st_texture_object(texObj);

    retval = st_finalize_texture(ctx, st->pipe, texObj);
    if (!retval) {
        /* out of mem */
        return GL_FALSE;
    }

    /* Determine the format of the texture sampler view */
    if (texObj->Target == GL_TEXTURE_BUFFER) {
        view_format =
            st_mesa_format_to_pipe_format(stObj->base._BufferObjectFormat);
    }
    else {
        view_format = stObj->pt->format;

        /* If sRGB decoding is off, use the linear format */
        if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
            view_format = util_format_linear(view_format);
        }
    }

    /* if sampler view has changed dereference it */
    if (stObj->sampler_view) {
        if (check_sampler_swizzle(stObj->sampler_view,
                                  stObj->base._Swizzle,
                                  stObj->base.DepthMode) ||
                (view_format != stObj->sampler_view->format) ||
                stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) {
            pipe_sampler_view_reference(&stObj->sampler_view, NULL);
        }
    }

    *sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe,
                    samp,
                    view_format);
    return GL_TRUE;
}
Пример #3
0
void
brw_populate_sampler_prog_key_data(struct gl_context *ctx,
				   const struct gl_program *prog,
                                   unsigned sampler_count,
				   struct brw_sampler_prog_key_data *key)
{
   struct brw_context *brw = brw_context(ctx);

   for (int s = 0; s < sampler_count; s++) {
      key->swizzles[s] = SWIZZLE_NOOP;

      if (!(prog->SamplersUsed & (1 << s)))
	 continue;

      int unit_id = prog->SamplerUnits[s];
      const struct gl_texture_unit *unit = &ctx->Texture.Unit[unit_id];

      if (unit->_ReallyEnabled && unit->_Current->Target != GL_TEXTURE_BUFFER) {
	 const struct gl_texture_object *t = unit->_Current;
	 const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
	 struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit_id);

         const bool alpha_depth = t->DepthMode == GL_ALPHA &&
            (img->_BaseFormat == GL_DEPTH_COMPONENT ||
             img->_BaseFormat == GL_DEPTH_STENCIL);

         /* Haswell handles texture swizzling as surface format overrides
          * (except for GL_ALPHA); all other platforms need MOVs in the shader.
          */
         if (!brw->is_haswell || alpha_depth)
            key->swizzles[s] = brw_get_texture_swizzle(ctx, t);

	 if (img->InternalFormat == GL_YCBCR_MESA) {
	    key->yuvtex_mask |= 1 << s;
	    if (img->TexFormat == MESA_FORMAT_YCBCR)
		key->yuvtex_swap_mask |= 1 << s;
	 }

	 if (sampler->MinFilter != GL_NEAREST &&
	     sampler->MagFilter != GL_NEAREST) {
	    if (sampler->WrapS == GL_CLAMP)
	       key->gl_clamp_mask[0] |= 1 << s;
	    if (sampler->WrapT == GL_CLAMP)
	       key->gl_clamp_mask[1] |= 1 << s;
	    if (sampler->WrapR == GL_CLAMP)
	       key->gl_clamp_mask[2] |= 1 << s;
	 }

         /* gather4's channel select for green from RG32F is broken;
          * requires a shader w/a on IVB; fixable with just SCS on HSW. */
         if (brw->gen >= 7 && !brw->is_haswell && prog->UsesGather) {
            if (img->InternalFormat == GL_RG32F)
               key->gather_channel_quirk_mask |= 1 << s;
         }
      }
   }
}
Пример #4
0
void r200TexUpdateParameters(struct gl_context *ctx, GLuint unit)
{
   struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
   radeonTexObj* t = radeon_tex_obj(ctx->Texture.Unit[unit]._Current);

   r200SetTexMaxAnisotropy(t , samp->MaxAnisotropy);
   r200SetTexFilter(t, samp->MinFilter, samp->MagFilter);
   r200SetTexWrap(t, samp->WrapS, samp->WrapT, samp->WrapR);
   r200SetTexBorderColor(t, samp->BorderColor.f);
}
Пример #5
0
/**
 * Fetch a texel.
 */
static void
fetch_texel(struct gl_context * ctx, const GLfloat texcoord[4], GLfloat lambda,
	    GLuint unit, GLfloat color[4])
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);

   /* XXX use a float-valued TextureSample routine here!!! */
   swrast->TextureSample[unit](ctx, _mesa_get_samplerobj(ctx, unit),
                               ctx->Texture.Unit[unit]._Current,
			       1, (const GLfloat(*)[4]) texcoord,
                               &lambda, (GLfloat (*)[4]) color);
}
Пример #6
0
void
brw_populate_sampler_prog_key_data(struct gl_context *ctx,
				   const struct gl_program *prog,
				   struct brw_sampler_prog_key_data *key)
{
   struct intel_context *intel = intel_context(ctx);

   for (int s = 0; s < MAX_SAMPLERS; s++) {
      key->swizzles[s] = SWIZZLE_NOOP;

      if (!(prog->SamplersUsed & (1 << s)))
	 continue;

      int unit_id = prog->SamplerUnits[s];
      const struct gl_texture_unit *unit = &ctx->Texture.Unit[unit_id];

      if (unit->_ReallyEnabled && unit->_Current->Target != GL_TEXTURE_BUFFER) {
	 const struct gl_texture_object *t = unit->_Current;
	 const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
	 struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit_id);

         const bool alpha_depth = t->DepthMode == GL_ALPHA &&
            (img->_BaseFormat == GL_DEPTH_COMPONENT ||
             img->_BaseFormat == GL_DEPTH_STENCIL);

         /* Haswell handles texture swizzling as surface format overrides
          * (except for GL_ALPHA); all other platforms need MOVs in the shader.
          */
         if (!intel->is_haswell || alpha_depth)
            key->swizzles[s] = brw_get_texture_swizzle(ctx, t);

	 if (img->InternalFormat == GL_YCBCR_MESA) {
	    key->yuvtex_mask |= 1 << s;
	    if (img->TexFormat == MESA_FORMAT_YCBCR)
		key->yuvtex_swap_mask |= 1 << s;
	 }

	 if (sampler->MinFilter != GL_NEAREST &&
	     sampler->MagFilter != GL_NEAREST) {
	    if (sampler->WrapS == GL_CLAMP)
	       key->gl_clamp_mask[0] |= 1 << s;
	    if (sampler->WrapT == GL_CLAMP)
	       key->gl_clamp_mask[1] |= 1 << s;
	    if (sampler->WrapR == GL_CLAMP)
	       key->gl_clamp_mask[2] |= 1 << s;
	 }
      }
   }
}
Пример #7
0
static GLboolean
update_single_texture(struct st_context *st,
                      struct pipe_sampler_view **sampler_view,
                      GLuint texUnit, unsigned glsl_version)
{
    struct gl_context *ctx = st->ctx;
    const struct gl_sampler_object *samp;
    struct gl_texture_object *texObj;
    struct st_texture_object *stObj;
    enum pipe_format view_format;
    GLboolean retval;

    samp = _mesa_get_samplerobj(ctx, texUnit);

    texObj = ctx->Texture.Unit[texUnit]._Current;

    if (!texObj) {
        texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
        samp = &texObj->Sampler;
    }
    stObj = st_texture_object(texObj);

    retval = st_finalize_texture(ctx, st->pipe, texObj);
    if (!retval) {
        /* out of mem */
        return GL_FALSE;
    }

    /* Determine the format of the texture sampler view */
    if (texObj->Target == GL_TEXTURE_BUFFER) {
        view_format =
            st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat);
    }
    else {
        view_format =
            stObj->surface_based ? stObj->surface_format : stObj->pt->format;

        /* If sRGB decoding is off, use the linear format */
        if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
            view_format = util_format_linear(view_format);
        }
    }

    *sampler_view =
        st_get_texture_sampler_view_from_stobj(st, stObj, view_format,
                glsl_version);
    return GL_TRUE;
}
Пример #8
0
static GLboolean
update_single_texture(struct st_context *st,
                      struct pipe_sampler_view **sampler_view,
		      GLuint texUnit, unsigned glsl_version)
{
   struct gl_context *ctx = st->ctx;
   const struct gl_sampler_object *samp;
   struct gl_texture_object *texObj;
   struct st_texture_object *stObj;
   GLboolean retval;

   samp = _mesa_get_samplerobj(ctx, texUnit);

   texObj = ctx->Texture.Unit[texUnit]._Current;

   if (!texObj) {
      texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
      samp = &texObj->Sampler;
   }
   stObj = st_texture_object(texObj);

   retval = st_finalize_texture(ctx, st->pipe, texObj);
   if (!retval) {
      /* out of mem */
      return GL_FALSE;
   }

   /* Check a few pieces of state outside the texture object to see if we
    * need to force revalidation.
    */
   if (stObj->prev_glsl_version != glsl_version ||
       stObj->prev_sRGBDecode != samp->sRGBDecode) {

      st_texture_release_all_sampler_views(st, stObj);

      stObj->prev_glsl_version = glsl_version;
      stObj->prev_sRGBDecode = samp->sRGBDecode;
   }

   if (texObj->TargetIndex == TEXTURE_EXTERNAL_INDEX &&
       stObj->pt->screen->resource_changed)
         stObj->pt->screen->resource_changed(stObj->pt->screen, stObj->pt);

   *sampler_view =
      st_get_texture_sampler_view_from_stobj(st, stObj, samp, glsl_version);
   return GL_TRUE;
}
Пример #9
0
void
_swrast_update_texture_samplers(struct gl_context *ctx)
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   GLuint u;

   if (!swrast)
      return; /* pipe hack */

   for (u = 0; u < ARRAY_SIZE(swrast->TextureSample); u++) {
      struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current;
      /* Note: If tObj is NULL, the sample function will be a simple
       * function that just returns opaque black (0,0,0,1).
       */
      _mesa_update_fetch_functions(ctx, u);
      swrast->TextureSample[u] =
         _swrast_choose_texture_sample_func(ctx, tObj,
                                            _mesa_get_samplerobj(ctx, u));
   }
}
Пример #10
0
/**
 * Fetch a texel with the given partial derivatives to compute a level
 * of detail in the mipmap.
 * Called via machine->FetchTexelDeriv()
 * \param lodBias  the lod bias which may be specified by a TXB instruction,
 *                 otherwise zero.
 */
static void
fetch_texel_deriv( struct gl_context *ctx, const GLfloat texcoord[4],
                   const GLfloat texdx[4], const GLfloat texdy[4],
                   GLfloat lodBias, GLuint unit, GLfloat color[4] )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
   const struct gl_texture_object *texObj = texUnit->_Current;

   if (texObj) {
      const struct gl_texture_image *texImg =
         texObj->Image[0][texObj->BaseLevel];
      const struct swrast_texture_image *swImg =
         swrast_texture_image_const(texImg);
      const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
      const GLfloat texW = (GLfloat) swImg->WidthScale;
      const GLfloat texH = (GLfloat) swImg->HeightScale;
      GLfloat lambda;
      GLfloat rgba[4];

      lambda = _swrast_compute_lambda(texdx[0], texdy[0], /* ds/dx, ds/dy */
                                      texdx[1], texdy[1], /* dt/dx, dt/dy */
                                      texdx[3], texdy[3], /* dq/dx, dq/dy */
                                      texW, texH,
                                      texcoord[0], texcoord[1], texcoord[3],
                                      1.0F / texcoord[3]);

      lambda += lodBias + texUnit->LodBias + samp->LodBias;

      lambda = CLAMP(lambda, samp->MinLod, samp->MaxLod);

      swrast->TextureSample[unit](ctx, samp, ctx->Texture.Unit[unit]._Current,
                                  1, (const GLfloat (*)[4]) texcoord,
                                  &lambda, &rgba);
      swizzle_texel(rgba, color, texObj->_Swizzle);
   }
   else {
      ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
   }
}
Пример #11
0
/**
 * Fetch a texel with given lod.
 * Called via machine->FetchTexelLod()
 */
static void
fetch_texel_lod( struct gl_context *ctx, const GLfloat texcoord[4], GLfloat lambda,
                 GLuint unit, GLfloat color[4] )
{
   const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;

   if (texObj) {
      SWcontext *swrast = SWRAST_CONTEXT(ctx);
      GLfloat rgba[4];
      const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);

      lambda = CLAMP(lambda, samp->MinLod, samp->MaxLod);

      swrast->TextureSample[unit](ctx, samp, ctx->Texture.Unit[unit]._Current,
                                  1, (const GLfloat (*)[4]) texcoord,
                                  &lambda, &rgba);
      swizzle_texel(rgba, color, texObj->_Swizzle);
   }
   else {
      ASSIGN_4V(color, 0.0F, 0.0F, 0.0F, 1.0F);
   }
}
/**
 * Get a pipe_sampler_view object from a texture unit.
 */
void
st_update_single_texture(struct st_context *st,
                         struct pipe_sampler_view **sampler_view,
                         GLuint texUnit, bool glsl130_or_later,
                         bool ignore_srgb_decode)
{
   struct gl_context *ctx = st->ctx;
   const struct gl_sampler_object *samp;
   struct gl_texture_object *texObj;
   struct st_texture_object *stObj;

   samp = _mesa_get_samplerobj(ctx, texUnit);

   texObj = ctx->Texture.Unit[texUnit]._Current;
   assert(texObj);

   stObj = st_texture_object(texObj);

   if (unlikely(texObj->Target == GL_TEXTURE_BUFFER)) {
      *sampler_view = st_get_buffer_sampler_view_from_stobj(st, stObj);
      return;
   }

   if (!st_finalize_texture(ctx, st->pipe, texObj, 0) ||
       !stObj->pt) {
      /* out of mem */
      *sampler_view = NULL;
      return;
   }

   if (texObj->TargetIndex == TEXTURE_EXTERNAL_INDEX &&
       stObj->pt->screen->resource_changed)
         stObj->pt->screen->resource_changed(stObj->pt->screen, stObj->pt);

   *sampler_view =
      st_get_texture_sampler_view_from_stobj(st, stObj, samp,
                                             glsl130_or_later,
                                             ignore_srgb_decode);
}
Пример #13
0
void
brw_populate_sampler_prog_key_data(struct gl_context *ctx,
				   const struct gl_program *prog,
                                   unsigned sampler_count,
				   struct brw_sampler_prog_key_data *key)
{
   struct brw_context *brw = brw_context(ctx);

   for (int s = 0; s < sampler_count; s++) {
      key->swizzles[s] = SWIZZLE_NOOP;

      if (!(prog->SamplersUsed & (1 << s)))
	 continue;

      int unit_id = prog->SamplerUnits[s];
      const struct gl_texture_unit *unit = &ctx->Texture.Unit[unit_id];

      if (unit->_Current && unit->_Current->Target != GL_TEXTURE_BUFFER) {
	 const struct gl_texture_object *t = unit->_Current;
	 const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
	 struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit_id);

         const bool alpha_depth = t->DepthMode == GL_ALPHA &&
            (img->_BaseFormat == GL_DEPTH_COMPONENT ||
             img->_BaseFormat == GL_DEPTH_STENCIL);

         /* Haswell handles texture swizzling as surface format overrides
          * (except for GL_ALPHA); all other platforms need MOVs in the shader.
          */
         if (alpha_depth || (brw->gen < 8 && !brw->is_haswell))
            key->swizzles[s] = brw_get_texture_swizzle(ctx, t);

	 if (brw->gen < 8 &&
             sampler->MinFilter != GL_NEAREST &&
	     sampler->MagFilter != GL_NEAREST) {
	    if (sampler->WrapS == GL_CLAMP)
	       key->gl_clamp_mask[0] |= 1 << s;
	    if (sampler->WrapT == GL_CLAMP)
	       key->gl_clamp_mask[1] |= 1 << s;
	    if (sampler->WrapR == GL_CLAMP)
	       key->gl_clamp_mask[2] |= 1 << s;
	 }

         /* gather4's channel select for green from RG32F is broken; requires
          * a shader w/a on IVB; fixable with just SCS on HSW.
          */
         if (brw->gen == 7 && !brw->is_haswell && prog->UsesGather) {
            if (img->InternalFormat == GL_RG32F)
               key->gather_channel_quirk_mask |= 1 << s;
         }

         /* Gen6's gather4 is broken for UINT/SINT; we treat them as
          * UNORM/FLOAT instead and fix it in the shader.
          */
         if (brw->gen == 6 && prog->UsesGather) {
            key->gen6_gather_wa[s] = gen6_gather_workaround(img->InternalFormat);
         }

         /* If this is a multisample sampler, and uses the CMS MSAA layout,
          * then we need to emit slightly different code to first sample the
          * MCS surface.
          */
         struct intel_texture_object *intel_tex =
            intel_texture_object((struct gl_texture_object *)t);

         if (brw->gen >= 7 &&
             intel_tex->mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) {
            key->compressed_multisample_layout_mask |= 1 << s;

            if (intel_tex->mt->num_samples >= 16) {
               assert(brw->gen >= 9);
               key->msaa_16 |= 1 << s;
            }
         }
      }
   }
}
Пример #14
0
/**
 * Apply texture mapping to a span of fragments.
 */
void
_swrast_texture_span( struct gl_context *ctx, SWspan *span )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   float4_array primary_rgba;
   GLuint unit;

   if (!swrast->TexelBuffer) {
#ifdef _OPENMP
      const GLint maxThreads = omp_get_max_threads();
#else
      const GLint maxThreads = 1;
#endif

      /* TexelBuffer is also global and normally shared by all SWspan
       * instances; when running with multiple threads, create one per
       * thread.
       */
      swrast->TexelBuffer =
	 malloc(ctx->Const.FragmentProgram.MaxTextureImageUnits * maxThreads *
			    SWRAST_MAX_WIDTH * 4 * sizeof(GLfloat));
      if (!swrast->TexelBuffer) {
	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_combine");
	 return;
      }
   }

   primary_rgba = malloc(span->end * 4 * sizeof(GLfloat));

   if (!primary_rgba) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture_span");
      return;
   }

   ASSERT(span->end <= SWRAST_MAX_WIDTH);

   /*
    * Save copy of the incoming fragment colors (the GL_PRIMARY_COLOR)
    */
   if (swrast->_TextureCombinePrimary) {
      GLuint i;
      for (i = 0; i < span->end; i++) {
         primary_rgba[i][RCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][RCOMP]);
         primary_rgba[i][GCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][GCOMP]);
         primary_rgba[i][BCOMP] = CHAN_TO_FLOAT(span->array->rgba[i][BCOMP]);
         primary_rgba[i][ACOMP] = CHAN_TO_FLOAT(span->array->rgba[i][ACOMP]);
      }
   }

   /* First must sample all bump maps */
   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];

      if (texUnit->_ReallyEnabled &&
         texUnit->_CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) {
         const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
            span->array->attribs[VARYING_SLOT_TEX0 + unit];
         float4_array targetcoords =
            span->array->attribs[VARYING_SLOT_TEX0 +
               ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0];

         const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
         GLfloat *lambda = span->array->lambda[unit];
         float4_array texels = get_texel_array(swrast, unit);
         GLuint i;
         GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0];
         GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1];
         GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2];
         GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3];

         /* adjust texture lod (lambda) */
         if (span->arrayMask & SPAN_LAMBDA) {
            if (texUnit->LodBias + samp->LodBias != 0.0F) {
               /* apply LOD bias, but don't clamp yet */
               const GLfloat bias = CLAMP(texUnit->LodBias + samp->LodBias,
                                          -ctx->Const.MaxTextureLodBias,
                                          ctx->Const.MaxTextureLodBias);
               GLuint i;
               for (i = 0; i < span->end; i++) {
                  lambda[i] += bias;
               }
            }

            if (samp->MinLod != -1000.0 ||
                samp->MaxLod != 1000.0) {
               /* apply LOD clamping to lambda */
               const GLfloat min = samp->MinLod;
               const GLfloat max = samp->MaxLod;
               GLuint i;
               for (i = 0; i < span->end; i++) {
                  GLfloat l = lambda[i];
                  lambda[i] = CLAMP(l, min, max);
               }
            }
         }

         /* Sample the texture (span->end = number of fragments) */
         swrast->TextureSample[unit]( ctx, samp,
                                      ctx->Texture.Unit[unit]._Current,
                                      span->end, texcoords, lambda, texels );

         /* manipulate the span values of the bump target
            not sure this can work correctly even ignoring
            the problem that channel is unsigned */
         for (i = 0; i < span->end; i++) {
            targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] *
                                  rotMatrix01) / targetcoords[i][3];
            targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] *
                                  rotMatrix11) / targetcoords[i][3];
         }
      }
   }

   /*
    * Must do all texture sampling before combining in order to
    * accomodate GL_ARB_texture_env_crossbar.
    */
   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
      if (texUnit->_ReallyEnabled &&
          texUnit->_CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
         const GLfloat (*texcoords)[4] = (const GLfloat (*)[4])
            span->array->attribs[VARYING_SLOT_TEX0 + unit];
         const struct gl_texture_object *curObj = texUnit->_Current;
         const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit);
         GLfloat *lambda = span->array->lambda[unit];
         float4_array texels = get_texel_array(swrast, unit);

         /* adjust texture lod (lambda) */
         if (span->arrayMask & SPAN_LAMBDA) {
            if (texUnit->LodBias + samp->LodBias != 0.0F) {
               /* apply LOD bias, but don't clamp yet */
               const GLfloat bias = CLAMP(texUnit->LodBias + samp->LodBias,
                                          -ctx->Const.MaxTextureLodBias,
                                          ctx->Const.MaxTextureLodBias);
               GLuint i;
               for (i = 0; i < span->end; i++) {
                  lambda[i] += bias;
               }
            }

            if (samp->MinLod != -1000.0 ||
                samp->MaxLod != 1000.0) {
               /* apply LOD clamping to lambda */
               const GLfloat min = samp->MinLod;
               const GLfloat max = samp->MaxLod;
               GLuint i;
               for (i = 0; i < span->end; i++) {
                  GLfloat l = lambda[i];
                  lambda[i] = CLAMP(l, min, max);
               }
            }
         }
         else if (samp->MaxAnisotropy > 1.0 &&
                  samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) {
            /* sample_lambda_2d_aniso is beeing used as texture_sample_func,
             * it requires the current SWspan *span as an additional parameter.
             * In order to keep the same function signature, the unused lambda
             * parameter will be modified to actually contain the SWspan pointer.
             * This is a Hack. To make it right, the texture_sample_func
             * signature and all implementing functions need to be modified.
             */
            /* "hide" SWspan struct; cast to (GLfloat *) to suppress warning */
            lambda = (GLfloat *)span;
         }

         /* Sample the texture (span->end = number of fragments) */
         swrast->TextureSample[unit]( ctx, samp,
                                      ctx->Texture.Unit[unit]._Current,
                                      span->end, texcoords, lambda, texels );

         /* GL_EXT_texture_swizzle */
         if (curObj->_Swizzle != SWIZZLE_NOOP) {
            swizzle_texels(curObj->_Swizzle, span->end, texels);
         }
      }
   }

   /*
    * OK, now apply the texture (aka texture combine/blend).
    * We modify the span->color.rgba values.
    */
   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
      if (ctx->Texture.Unit[unit]._ReallyEnabled)
         texture_combine(ctx, unit, primary_rgba, swrast->TexelBuffer, span);
   }

   free(primary_rgba);
}
Пример #15
0
GLuint
intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
{
   struct gl_context *ctx = &intel->ctx;
   struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
   struct intel_texture_object *intelObj = intel_texture_object(tObj);
   struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
   GLuint face, i;
   GLuint nr_faces = 0;
   struct intel_texture_image *firstImage;
   int width, height, depth;

   /* TBOs require no validation -- they always just point to their BO. */
   if (tObj->Target == GL_TEXTURE_BUFFER)
      return true;

   /* We know/require this is true by now: 
    */
   assert(intelObj->base._BaseComplete);

   /* What levels must the tree include at a minimum?
    */
   intel_update_max_level(intelObj, sampler);
   if (intelObj->mt && intelObj->mt->first_level != tObj->BaseLevel)
      intelObj->needs_validate = true;

   if (!intelObj->needs_validate)
      return true;

   firstImage = intel_texture_image(tObj->Image[0][tObj->BaseLevel]);

   /* Check tree can hold all active levels.  Check tree matches
    * target, imageFormat, etc.
    *
    * For pre-gen4, we have to match first_level == tObj->BaseLevel,
    * because we don't have the control that gen4 does to make min/mag
    * determination happen at a nonzero (hardware) baselevel.  Because
    * of that, we just always relayout on baselevel change.
    */
   if (intelObj->mt &&
       (!intel_miptree_match_image(intelObj->mt, &firstImage->base.Base) ||
	intelObj->mt->first_level != tObj->BaseLevel ||
	intelObj->mt->last_level < intelObj->_MaxLevel)) {
      intel_miptree_release(&intelObj->mt);
   }


   /* May need to create a new tree:
    */
   if (!intelObj->mt) {
      intel_miptree_get_dimensions_for_image(&firstImage->base.Base,
					     &width, &height, &depth);

      perf_debug("Creating new %s %dx%dx%d %d..%d miptree to handle finalized "
                 "texture miptree.\n",
                 _mesa_get_format_name(firstImage->base.Base.TexFormat),
                 width, height, depth, tObj->BaseLevel, intelObj->_MaxLevel);

      intelObj->mt = intel_miptree_create(intel,
                                          intelObj->base.Target,
					  firstImage->base.Base.TexFormat,
                                          tObj->BaseLevel,
                                          intelObj->_MaxLevel,
                                          width,
                                          height,
                                          depth,
					  true,
                                          0 /* num_samples */,
                                          false /* force_y_tiling */);
      if (!intelObj->mt)
         return false;
   }

   /* Pull in any images not in the object's tree:
    */
   nr_faces = _mesa_num_tex_faces(intelObj->base.Target);
   for (face = 0; face < nr_faces; face++) {
      for (i = tObj->BaseLevel; i <= intelObj->_MaxLevel; i++) {
         struct intel_texture_image *intelImage =
            intel_texture_image(intelObj->base.Image[face][i]);
	 /* skip too small size mipmap */
 	 if (intelImage == NULL)
		 break;

         if (intelObj->mt != intelImage->mt) {
            intel_miptree_copy_teximage(intel, intelImage, intelObj->mt,
                                        false /* invalidate */);
         }

         /* After we're done, we'd better agree that our layout is
          * appropriate, or we'll end up hitting this function again on the
          * next draw
          */
         assert(intel_miptree_match_image(intelObj->mt, &intelImage->base.Base));
      }
   }

   intelObj->needs_validate = false;

   return true;
}
Пример #16
0
GLuint
intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
{
   struct gl_context *ctx = &intel->ctx;
   struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
   struct intel_texture_object *intelObj = intel_texture_object(tObj);
   struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
   GLuint face, i;
   GLuint nr_faces = 0;
   struct intel_texture_image *firstImage;

   /* We know/require this is true by now: 
    */
   assert(intelObj->base._Complete);

   /* What levels must the tree include at a minimum?
    */
   intel_update_max_level(intel, intelObj, sampler);
   firstImage = intel_texture_image(tObj->Image[0][tObj->BaseLevel]);

   /* Fallback case:
    */
   if (firstImage->base.Border) {
      if (intelObj->mt) {
         intel_miptree_release(intel, &intelObj->mt);
      }
      return GL_FALSE;
   }

   /* Check tree can hold all active levels.  Check tree matches
    * target, imageFormat, etc.
    *
    * For pre-gen4, we have to match first_level == tObj->BaseLevel,
    * because we don't have the control that gen4 does to make min/mag
    * determination happen at a nonzero (hardware) baselevel.  Because
    * of that, we just always relayout on baselevel change.
    */
   if (intelObj->mt &&
       (intelObj->mt->target != intelObj->base.Target ||
	intelObj->mt->format != firstImage->base.TexFormat ||
	intelObj->mt->first_level != tObj->BaseLevel ||
	intelObj->mt->last_level < intelObj->_MaxLevel ||
	intelObj->mt->width0 != firstImage->base.Width ||
	intelObj->mt->height0 != firstImage->base.Height ||
	intelObj->mt->depth0 != firstImage->base.Depth)) {
      intel_miptree_release(intel, &intelObj->mt);
   }


   /* May need to create a new tree:
    */
   if (!intelObj->mt) {
      intelObj->mt = intel_miptree_create(intel,
                                          intelObj->base.Target,
					  firstImage->base.TexFormat,
                                          tObj->BaseLevel,
                                          intelObj->_MaxLevel,
                                          firstImage->base.Width,
                                          firstImage->base.Height,
                                          firstImage->base.Depth,
					  GL_TRUE);
      if (!intelObj->mt)
         return GL_FALSE;
   }

   /* Pull in any images not in the object's tree:
    */
   nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
   for (face = 0; face < nr_faces; face++) {
      for (i = tObj->BaseLevel; i <= intelObj->_MaxLevel; i++) {
         struct intel_texture_image *intelImage =
            intel_texture_image(intelObj->base.Image[face][i]);
	 /* skip too small size mipmap */
 	 if (intelImage == NULL)
		 break;
	 /* Need to import images in main memory or held in other trees.
	  * If it's a render target, then its data isn't needed to be in
	  * the object tree (otherwise we'd be FBO incomplete), and we need
	  * to keep track of the image's MT as needing to be pulled in still,
	  * or we'll lose the rendering that's done to it.
          */
         if (intelObj->mt != intelImage->mt &&
	     !intelImage->used_as_render_target) {
            copy_image_data_to_tree(intel, intelObj, intelImage);
         }
      }
   }

   return GL_TRUE;
}
Пример #17
0
/**
 * At rendering-from-a-texture time, make sure that the texture object has a
 * miptree that can hold the entire texture based on
 * BaseLevel/MaxLevel/filtering, and copy in any texture images that are
 * stored in other miptrees.
 */
GLuint
intel_finalize_mipmap_tree(struct brw_context *brw, GLuint unit)
{
   struct gl_context *ctx = &brw->ctx;
   struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
   struct intel_texture_object *intelObj = intel_texture_object(tObj);
   struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
   GLuint face, i;
   GLuint nr_faces = 0;
   struct intel_texture_image *firstImage;
   int width, height, depth;

   /* TBOs require no validation -- they always just point to their BO. */
   if (tObj->Target == GL_TEXTURE_BUFFER)
      return true;

   /* We know that this is true by now, and if it wasn't, we might have
    * mismatched level sizes and the copies would fail.
    */
   assert(intelObj->base._BaseComplete);

   intel_update_max_level(intelObj, sampler);

   /* What levels does this validated texture image require? */
   int validate_first_level = tObj->BaseLevel;
   int validate_last_level = intelObj->_MaxLevel;

   /* Skip the loop over images in the common case of no images having
    * changed.  But if the GL_BASE_LEVEL or GL_MAX_LEVEL change to something we
    * haven't looked at, then we do need to look at those new images.
    */
   if (!intelObj->needs_validate &&
       validate_first_level >= intelObj->validated_first_level &&
       validate_last_level <= intelObj->validated_last_level) {
      return true;
   }

   /* Immutable textures should not get this far -- they should have been
    * created in a validated state, and nothing can invalidate them.
    */
   assert(!tObj->Immutable);

   firstImage = intel_texture_image(tObj->Image[0][tObj->BaseLevel]);

   /* Check tree can hold all active levels.  Check tree matches
    * target, imageFormat, etc.
    *
    * For pre-gen4, we have to match first_level == tObj->BaseLevel,
    * because we don't have the control that gen4 does to make min/mag
    * determination happen at a nonzero (hardware) baselevel.  Because
    * of that, we just always relayout on baselevel change.
    */
   if (intelObj->mt &&
       (!intel_miptree_match_image(intelObj->mt, &firstImage->base.Base) ||
	validate_first_level < intelObj->mt->first_level ||
	validate_last_level > intelObj->mt->last_level)) {
      intel_miptree_release(&intelObj->mt);
   }


   /* May need to create a new tree:
    */
   if (!intelObj->mt) {
      intel_miptree_get_dimensions_for_image(&firstImage->base.Base,
					     &width, &height, &depth);

      perf_debug("Creating new %s %dx%dx%d %d-level miptree to handle "
                 "finalized texture miptree.\n",
                 _mesa_get_format_name(firstImage->base.Base.TexFormat),
                 width, height, depth, validate_last_level + 1);

      intelObj->mt = intel_miptree_create(brw,
                                          intelObj->base.Target,
					  firstImage->base.Base.TexFormat,
                                          0, /* first_level */
                                          validate_last_level,
                                          width,
                                          height,
                                          depth,
					  true,
                                          0 /* num_samples */,
                                          INTEL_MIPTREE_TILING_ANY);
      if (!intelObj->mt)
         return false;
   }

   /* Pull in any images not in the object's tree:
    */
   nr_faces = _mesa_num_tex_faces(intelObj->base.Target);
   for (face = 0; face < nr_faces; face++) {
      for (i = validate_first_level; i <= validate_last_level; i++) {
         struct intel_texture_image *intelImage =
            intel_texture_image(intelObj->base.Image[face][i]);
	 /* skip too small size mipmap */
 	 if (intelImage == NULL)
		 break;

         if (intelObj->mt != intelImage->mt) {
            intel_miptree_copy_teximage(brw, intelImage, intelObj->mt,
                                        false /* invalidate */);
         }

         /* After we're done, we'd better agree that our layout is
          * appropriate, or we'll end up hitting this function again on the
          * next draw
          */
         assert(intel_miptree_match_image(intelObj->mt, &intelImage->base.Base));
      }
   }

   intelObj->validated_first_level = validate_first_level;
   intelObj->validated_last_level = validate_last_level;
   intelObj->_Format = intelObj->mt->format;
   intelObj->needs_validate = false;

   return true;
}
Пример #18
0
/* Recalculate all state from scratch.  Perhaps not the most
 * efficient, but this has gotten complex enough that we need
 * something which is understandable and reliable.
 */
static bool
i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
{
   struct gl_context *ctx = &intel->ctx;
   struct i915_context *i915 = i915_context(ctx);
   struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit];
   struct gl_texture_object *tObj = tUnit->_Current;
   struct intel_texture_object *intelObj = intel_texture_object(tObj);
   struct gl_texture_image *firstImage;
   struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
   GLuint *state = i915->state.Tex[unit], format, pitch;
   GLint lodbias, aniso = 0;
   GLubyte border[4];
   GLfloat maxlod;

   memset(state, 0, sizeof(state));

   /*We need to refcount these. */

   if (i915->state.tex_buffer[unit] != NULL) {
       drm_intel_bo_unreference(i915->state.tex_buffer[unit]);
       i915->state.tex_buffer[unit] = NULL;
   }

   if (!intel_finalize_mipmap_tree(intel, unit))
      return false;

   /* Get first image here, since intelObj->firstLevel will get set in
    * the intel_finalize_mipmap_tree() call above.
    */
   firstImage = tObj->Image[0][tObj->BaseLevel];

   drm_intel_bo_reference(intelObj->mt->region->bo);
   i915->state.tex_buffer[unit] = intelObj->mt->region->bo;
   i915->state.tex_offset[unit] = intelObj->mt->offset;

   format = translate_texture_format(firstImage->TexFormat,
				     tObj->DepthMode);
   pitch = intelObj->mt->region->pitch * intelObj->mt->cpp;

   state[I915_TEXREG_MS3] =
      (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) |
       ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format);

   if (intelObj->mt->region->tiling != I915_TILING_NONE) {
      state[I915_TEXREG_MS3] |= MS3_TILED_SURFACE;
      if (intelObj->mt->region->tiling == I915_TILING_Y)
	 state[I915_TEXREG_MS3] |= MS3_TILE_WALK;
   }

   /* We get one field with fraction bits for the maximum addressable
    * (lowest resolution) LOD.  Use it to cover both MAX_LEVEL and
    * MAX_LOD.
    */
   maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel);
   state[I915_TEXREG_MS4] =
      ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |
       MS4_CUBE_FACE_ENA_MASK |
       (U_FIXED(CLAMP(maxlod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) |
       ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));


   {
      GLuint minFilt, mipFilt, magFilt;

      switch (sampler->MinFilter) {
      case GL_NEAREST:
         minFilt = FILTER_NEAREST;
         mipFilt = MIPFILTER_NONE;
         break;
      case GL_LINEAR:
         minFilt = FILTER_LINEAR;
         mipFilt = MIPFILTER_NONE;
         break;
      case GL_NEAREST_MIPMAP_NEAREST:
         minFilt = FILTER_NEAREST;
         mipFilt = MIPFILTER_NEAREST;
         break;
      case GL_LINEAR_MIPMAP_NEAREST:
         minFilt = FILTER_LINEAR;
         mipFilt = MIPFILTER_NEAREST;
         break;
      case GL_NEAREST_MIPMAP_LINEAR:
         minFilt = FILTER_NEAREST;
         mipFilt = MIPFILTER_LINEAR;
         break;
      case GL_LINEAR_MIPMAP_LINEAR:
         minFilt = FILTER_LINEAR;
         mipFilt = MIPFILTER_LINEAR;
         break;
      default:
         return false;
      }

      if (sampler->MaxAnisotropy > 1.0) {
         minFilt = FILTER_ANISOTROPIC;
         magFilt = FILTER_ANISOTROPIC;
         if (sampler->MaxAnisotropy > 2.0)
            aniso = SS2_MAX_ANISO_4;
         else
            aniso = SS2_MAX_ANISO_2;
      }
      else {
         switch (sampler->MagFilter) {
         case GL_NEAREST:
            magFilt = FILTER_NEAREST;
            break;
         case GL_LINEAR:
            magFilt = FILTER_LINEAR;
            break;
         default:
            return false;
         }
      }

      lodbias = (int) ((tUnit->LodBias + sampler->LodBias) * 16.0);
      if (lodbias < -256)
          lodbias = -256;
      if (lodbias > 255)
          lodbias = 255;
      state[I915_TEXREG_SS2] = ((lodbias << SS2_LOD_BIAS_SHIFT) & 
                                SS2_LOD_BIAS_MASK);

      /* YUV conversion:
       */
      if (firstImage->TexFormat == MESA_FORMAT_YCBCR ||
          firstImage->TexFormat == MESA_FORMAT_YCBCR_REV)
         state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION;

      /* Shadow:
       */
      if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB &&
          tObj->Target != GL_TEXTURE_3D) {
         if (tObj->Target == GL_TEXTURE_1D) 
            return false;

         state[I915_TEXREG_SS2] |=
            (SS2_SHADOW_ENABLE |
             intel_translate_shadow_compare_func(sampler->CompareFunc));

         minFilt = FILTER_4X4_FLAT;
         magFilt = FILTER_4X4_FLAT;
      }

      state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
                                 (mipFilt << SS2_MIP_FILTER_SHIFT) |
                                 (magFilt << SS2_MAG_FILTER_SHIFT) |
                                 aniso);
   }

   {
      GLenum ws = sampler->WrapS;
      GLenum wt = sampler->WrapT;
      GLenum wr = sampler->WrapR;
      float minlod;

      /* We program 1D textures as 2D textures, so the 2D texcoord could
       * result in sampling border values if we don't set the T wrap to
       * repeat.
       */
      if (tObj->Target == GL_TEXTURE_1D)
	 wt = GL_REPEAT;

      /* 3D textures don't seem to respect the border color.
       * Fallback if there's ever a danger that they might refer to
       * it.  
       * 
       * Effectively this means fallback on 3D clamp or
       * clamp_to_border.
       */
      if (tObj->Target == GL_TEXTURE_3D &&
          (sampler->MinFilter != GL_NEAREST ||
           sampler->MagFilter != GL_NEAREST) &&
          (ws == GL_CLAMP ||
           wt == GL_CLAMP ||
           wr == GL_CLAMP ||
           ws == GL_CLAMP_TO_BORDER ||
           wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER))
         return false;

      /* Only support TEXCOORDMODE_CLAMP_EDGE and TEXCOORDMODE_CUBE (not 
       * used) when using cube map texture coordinates
       */
      if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
          (((ws != GL_CLAMP) && (ws != GL_CLAMP_TO_EDGE)) ||
           ((wt != GL_CLAMP) && (wt != GL_CLAMP_TO_EDGE))))
          return false;

      /*
       * According to 3DSTATE_MAP_STATE at page of 104 in Bspec
       * Vol3d 3D Instructions:
       *   [DevGDG and DevAlv]: Must be a power of 2 for cube maps.
       *   [DevLPT, DevCST and DevBLB]: If not a power of 2, cube maps
       *      must have all faces enabled.
       *
       * But, as I tested on pineview(DevBLB derived), the rendering is
       * bad(you will find the color isn't samplered right in some
       * fragments). After checking, it seems that the texture layout is
       * wrong: making the width and height align of 4(although this
       * doesn't make much sense) will fix this issue and also broke some
       * others. Well, Bspec mentioned nothing about the layout alignment
       * and layout for NPOT cube map.  I guess the Bspec just assume it's
       * a POT cube map.
       *
       * Thus, I guess we need do this for other platforms as well.
       */
      if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
          !is_power_of_two(firstImage->Height))
         return false;

      state[I915_TEXREG_SS3] = ss3;     /* SS3_NORMALIZED_COORDS */

      state[I915_TEXREG_SS3] |=
         ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) |
          (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) |
          (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT));

      minlod = MIN2(sampler->MinLod, tObj->_MaxLevel - tObj->BaseLevel);
      state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
      state[I915_TEXREG_SS3] |= (U_FIXED(CLAMP(minlod, 0.0, 11.0), 4) <<
				 SS3_MIN_LOD_SHIFT);

   }

   /* convert border color from float to ubyte */
   CLAMPED_FLOAT_TO_UBYTE(border[0], sampler->BorderColor.f[0]);
   CLAMPED_FLOAT_TO_UBYTE(border[1], sampler->BorderColor.f[1]);
   CLAMPED_FLOAT_TO_UBYTE(border[2], sampler->BorderColor.f[2]);
   CLAMPED_FLOAT_TO_UBYTE(border[3], sampler->BorderColor.f[3]);

   if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) {
      /* GL specs that border color for depth textures is taken from the
       * R channel, while the hardware uses A.  Spam R into all the channels
       * for safety.
       */
      state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[0],
					       border[0],
					       border[0],
					       border[0]);
   } else {
      state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[3],
					       border[0],
					       border[1],
					       border[2]);
   }


   I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), true);
   /* memcmp was already disabled, but definitely won't work as the
    * region might now change and that wouldn't be detected:
    */
   I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));


#if 0
   DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]);
   DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]);
   DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]);
   DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]);
   DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]);
   DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]);
#endif

   return true;
}
Пример #19
0
/**
 * Sets the sampler state for a single unit.
 */
static void
gen7_update_sampler_state(struct brw_context *brw, int unit, int ss_index,
			  struct gen7_sampler_state *sampler,
                          uint32_t *sdc_offset)
{
   struct gl_context *ctx = &brw->ctx;
   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
   struct gl_texture_object *texObj = texUnit->_Current;
   struct gl_sampler_object *gl_sampler = _mesa_get_samplerobj(ctx, unit);
   bool using_nearest = false;

   /* These don't use samplers at all. */
   if (texObj->Target == GL_TEXTURE_BUFFER)
      return;

   switch (gl_sampler->MinFilter) {
   case GL_NEAREST:
      sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
      sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
      using_nearest = true;
      break;
   case GL_LINEAR:
      sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
      sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
      break;
   case GL_NEAREST_MIPMAP_NEAREST:
      sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
      sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
      break;
   case GL_LINEAR_MIPMAP_NEAREST:
      sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
      sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
      break;
   case GL_NEAREST_MIPMAP_LINEAR:
      sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
      sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
      break;
   case GL_LINEAR_MIPMAP_LINEAR:
      sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
      sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
      break;
   default:
      break;
   }

   /* Set Anisotropy: */
   if (gl_sampler->MaxAnisotropy > 1.0) {
      sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC;
      sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC;
      sampler->ss0.aniso_algorithm = 1;

      if (gl_sampler->MaxAnisotropy > 2.0) {
	 sampler->ss3.max_aniso = MIN2((gl_sampler->MaxAnisotropy - 2) / 2,
				       BRW_ANISORATIO_16);
      }
   }
   else {
      switch (gl_sampler->MagFilter) {
      case GL_NEAREST:
	 sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
	 using_nearest = true;
	 break;
      case GL_LINEAR:
	 sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
	 break;
      default:
	 break;
      }
   }

   sampler->ss3.r_wrap_mode = translate_wrap_mode(gl_sampler->WrapR,
						  using_nearest);
   sampler->ss3.s_wrap_mode = translate_wrap_mode(gl_sampler->WrapS,
						  using_nearest);
   sampler->ss3.t_wrap_mode = translate_wrap_mode(gl_sampler->WrapT,
						  using_nearest);

   /* Cube-maps on 965 and later must use the same wrap mode for all 3
    * coordinate dimensions.  Futher, only CUBE and CLAMP are valid.
    */
   if (texObj->Target == GL_TEXTURE_CUBE_MAP ||
       texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) {
      if ((ctx->Texture.CubeMapSeamless || gl_sampler->CubeMapSeamless) &&
	  (gl_sampler->MinFilter != GL_NEAREST ||
	   gl_sampler->MagFilter != GL_NEAREST)) {
	 sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
	 sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
	 sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
      } else {
	 sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
	 sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
	 sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
      }
   } else if (texObj->Target == GL_TEXTURE_1D) {
      /* There's a bug in 1D texture sampling - it actually pays
       * attention to the wrap_t value, though it should not.
       * Override the wrap_t value here to GL_REPEAT to keep
       * any nonexistent border pixels from floating in.
       */
      sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
   }

   /* Set shadow function: */
   if (gl_sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
      /* Shadowing is "enabled" by emitting a particular sampler
       * message (sample_c).  So need to recompile WM program when
       * shadow comparison is enabled on each/any texture unit.
       */
      sampler->ss1.shadow_function =
	 intel_translate_shadow_compare_func(gl_sampler->CompareFunc);
   }

   /* Set LOD bias: */
   sampler->ss0.lod_bias = S_FIXED(CLAMP(texUnit->LodBias +
					 gl_sampler->LodBias, -16, 15), 8);

   sampler->ss0.lod_preclamp = 1; /* OpenGL mode */
   sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */

   sampler->ss0.base_level = U_FIXED(0, 1);

   sampler->ss1.max_lod = U_FIXED(CLAMP(gl_sampler->MaxLod, 0, 13), 8);
   sampler->ss1.min_lod = U_FIXED(CLAMP(gl_sampler->MinLod, 0, 13), 8);

   /* The sampler can handle non-normalized texture rectangle coordinates
    * natively
    */
   if (texObj->Target == GL_TEXTURE_RECTANGLE) {
      sampler->ss3.non_normalized_coord = 1;
   }

   upload_default_color(brw, gl_sampler, unit, sdc_offset);

   sampler->ss2.default_color_pointer = *sdc_offset >> 5;

   if (sampler->ss0.min_filter != BRW_MAPFILTER_NEAREST)
      sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN |
                                    BRW_ADDRESS_ROUNDING_ENABLE_V_MIN |
                                    BRW_ADDRESS_ROUNDING_ENABLE_R_MIN;
   if (sampler->ss0.mag_filter != BRW_MAPFILTER_NEAREST)
      sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG |
                                    BRW_ADDRESS_ROUNDING_ENABLE_V_MAG |
                                    BRW_ADDRESS_ROUNDING_ENABLE_R_MAG;
}
Пример #20
0
static void
convert_sampler(struct st_context *st,
                struct pipe_sampler_state *sampler,
                GLuint texUnit)
{
    struct gl_texture_object *texobj;
    struct gl_context *ctx = st->ctx;
    struct gl_sampler_object *msamp;

    texobj = ctx->Texture.Unit[texUnit]._Current;
    if (!texobj) {
        texobj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
    }

    msamp = _mesa_get_samplerobj(ctx, texUnit);

    memset(sampler, 0, sizeof(*sampler));
    sampler->wrap_s = gl_wrap_xlate(msamp->WrapS);
    sampler->wrap_t = gl_wrap_xlate(msamp->WrapT);
    sampler->wrap_r = gl_wrap_xlate(msamp->WrapR);

    sampler->min_img_filter = gl_filter_to_img_filter(msamp->MinFilter);
    sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->MinFilter);
    sampler->mag_img_filter = gl_filter_to_img_filter(msamp->MagFilter);

    if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB)
        sampler->normalized_coords = 1;

    sampler->lod_bias = ctx->Texture.Unit[texUnit].LodBias + msamp->LodBias;

    sampler->min_lod = CLAMP(msamp->MinLod,
                             0.0f,
                             (GLfloat) texobj->MaxLevel - texobj->BaseLevel);
    sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel - texobj->BaseLevel,
                            msamp->MaxLod);
    if (sampler->max_lod < sampler->min_lod) {
        /* The GL spec doesn't seem to specify what to do in this case.
         * Swap the values.
         */
        float tmp = sampler->max_lod;
        sampler->max_lod = sampler->min_lod;
        sampler->min_lod = tmp;
        assert(sampler->min_lod <= sampler->max_lod);
    }

    if (msamp->BorderColor.ui[0] ||
            msamp->BorderColor.ui[1] ||
            msamp->BorderColor.ui[2] ||
            msamp->BorderColor.ui[3]) {
        struct st_texture_object *stobj = st_texture_object(texobj);
        struct gl_texture_image *teximg;
        GLboolean is_integer = GL_FALSE;
        union pipe_color_union border_color;

        teximg = texobj->Image[0][texobj->BaseLevel];

        if (teximg) {
            is_integer = _mesa_is_enum_format_integer(teximg->InternalFormat);
        }

        if (st->apply_texture_swizzle_to_border_color && stobj->sampler_view) {
            const unsigned char swz[4] =
            {
                stobj->sampler_view->swizzle_r,
                stobj->sampler_view->swizzle_g,
                stobj->sampler_view->swizzle_b,
                stobj->sampler_view->swizzle_a,
            };

            st_translate_color(&msamp->BorderColor,
                               &border_color,
                               teximg ? teximg->_BaseFormat : GL_RGBA, is_integer);

            util_format_apply_color_swizzle(&sampler->border_color,
                                            &border_color, swz, is_integer);
        } else {
            st_translate_color(&msamp->BorderColor,
                               &sampler->border_color,
                               teximg ? teximg->_BaseFormat : GL_RGBA, is_integer);
        }
    }

    sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ?
                               0 : (GLuint) msamp->MaxAnisotropy);

    /* only care about ARB_shadow, not SGI shadow */
    if (msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) {
        sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
        sampler->compare_func
            = st_compare_func_to_pipe(msamp->CompareFunc);
    }

    sampler->seamless_cube_map =
        ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless;
}
Пример #21
0
/**
 * Sets the sampler state for a single unit.
 */
static void
gen7_update_sampler_state(struct brw_context *brw, int unit,
			  struct gen7_sampler_state *sampler)
{
   struct intel_context *intel = &brw->intel;
   struct gl_context *ctx = &intel->ctx;
   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
   struct gl_texture_object *texObj = texUnit->_Current;
   struct gl_sampler_object *gl_sampler = _mesa_get_samplerobj(ctx, unit);
   bool using_nearest = false;

   switch (gl_sampler->MinFilter) {
   case GL_NEAREST:
      sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
      sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
      using_nearest = true;
      break;
   case GL_LINEAR:
      sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
      sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
      break;
   case GL_NEAREST_MIPMAP_NEAREST:
      sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
      sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
      break;
   case GL_LINEAR_MIPMAP_NEAREST:
      sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
      sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
      break;
   case GL_NEAREST_MIPMAP_LINEAR:
      sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
      sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
      break;
   case GL_LINEAR_MIPMAP_LINEAR:
      sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
      sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
      break;
   default:
      break;
   }

   /* Set Anisotropy: */
   if (gl_sampler->MaxAnisotropy > 1.0) {
      sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC;
      sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC;

      if (gl_sampler->MaxAnisotropy > 2.0) {
	 sampler->ss3.max_aniso = MIN2((gl_sampler->MaxAnisotropy - 2) / 2,
				       BRW_ANISORATIO_16);
      }
   }
   else {
      switch (gl_sampler->MagFilter) {
      case GL_NEAREST:
	 sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
	 using_nearest = true;
	 break;
      case GL_LINEAR:
	 sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
	 break;
      default:
	 break;
      }
   }

   sampler->ss3.r_wrap_mode = translate_wrap_mode(gl_sampler->WrapR,
						  using_nearest);
   sampler->ss3.s_wrap_mode = translate_wrap_mode(gl_sampler->WrapS,
						  using_nearest);
   sampler->ss3.t_wrap_mode = translate_wrap_mode(gl_sampler->WrapT,
						  using_nearest);

   /* Cube-maps on 965 and later must use the same wrap mode for all 3
    * coordinate dimensions.  Futher, only CUBE and CLAMP are valid.
    */
   if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
      if (ctx->Texture.CubeMapSeamless &&
	  (gl_sampler->MinFilter != GL_NEAREST ||
	   gl_sampler->MagFilter != GL_NEAREST)) {
	 sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
	 sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
	 sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
      } else {
	 sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
	 sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
	 sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
      }
   } else if (texObj->Target == GL_TEXTURE_1D) {
      /* There's a bug in 1D texture sampling - it actually pays
       * attention to the wrap_t value, though it should not.
       * Override the wrap_t value here to GL_REPEAT to keep
       * any nonexistent border pixels from floating in.
       */
      sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
   }

   /* Set shadow function: */
   if (gl_sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
      /* Shadowing is "enabled" by emitting a particular sampler
       * message (sample_c).  So need to recompile WM program when
       * shadow comparison is enabled on each/any texture unit.
       */
      sampler->ss1.shadow_function =
	 intel_translate_shadow_compare_func(gl_sampler->CompareFunc);
   }

   /* Set LOD bias: */
   sampler->ss0.lod_bias = S_FIXED(CLAMP(texUnit->LodBias +
					 gl_sampler->LodBias, -16, 15), 8);

   sampler->ss0.lod_preclamp = 1; /* OpenGL mode */
   sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */

   /* Set BaseMipLevel, MaxLOD, MinLOD:
    *
    * XXX: I don't think that using firstLevel, lastLevel works,
    * because we always setup the surface state as if firstLevel ==
    * level zero.  Probably have to subtract firstLevel from each of
    * these:
    */
   sampler->ss0.base_level = U_FIXED(0, 1);

   sampler->ss1.max_lod = U_FIXED(CLAMP(gl_sampler->MaxLod, 0, 13), 8);
   sampler->ss1.min_lod = U_FIXED(CLAMP(gl_sampler->MinLod, 0, 13), 8);

   upload_default_color(brw, gl_sampler, unit);

   sampler->ss2.default_color_pointer = brw->wm.sdc_offset[unit] >> 5;
}
Пример #22
0
GLuint
intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
{
   struct gl_context *ctx = &intel->ctx;
   struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current;
   struct intel_texture_object *intelObj = intel_texture_object(tObj);
   struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
   GLuint face, i;
   GLuint nr_faces = 0;
   struct intel_texture_image *firstImage;
   int width, height, depth;

   /* TBOs require no validation -- they always just point to their BO. */
   if (tObj->Target == GL_TEXTURE_BUFFER)
      return true;

   /* We know/require this is true by now: 
    */
   assert(intelObj->base._BaseComplete);

   /* What levels must the tree include at a minimum?
    */
   intel_update_max_level(intelObj, sampler);
   firstImage = intel_texture_image(tObj->Image[0][tObj->BaseLevel]);

   /* Check tree can hold all active levels.  Check tree matches
    * target, imageFormat, etc.
    *
    * For pre-gen4, we have to match first_level == tObj->BaseLevel,
    * because we don't have the control that gen4 does to make min/mag
    * determination happen at a nonzero (hardware) baselevel.  Because
    * of that, we just always relayout on baselevel change.
    */
   if (intelObj->mt &&
       (!intel_miptree_match_image(intelObj->mt, &firstImage->base.Base) ||
	intelObj->mt->first_level != tObj->BaseLevel ||
	intelObj->mt->last_level < intelObj->_MaxLevel)) {
      intel_miptree_release(&intelObj->mt);
   }


   /* May need to create a new tree:
    */
   if (!intelObj->mt) {
      intel_miptree_get_dimensions_for_image(&firstImage->base.Base,
					     &width, &height, &depth);

      intelObj->mt = intel_miptree_create(intel,
                                          intelObj->base.Target,
					  firstImage->base.Base.TexFormat,
                                          tObj->BaseLevel,
                                          intelObj->_MaxLevel,
                                          width,
                                          height,
                                          depth,
					  true,
                                          0 /* num_samples */,
                                          false /* msaa_is_interleaved */);
      if (!intelObj->mt)
         return false;
   }

   /* Pull in any images not in the object's tree:
    */
   nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
   for (face = 0; face < nr_faces; face++) {
      for (i = tObj->BaseLevel; i <= intelObj->_MaxLevel; i++) {
         struct intel_texture_image *intelImage =
            intel_texture_image(intelObj->base.Image[face][i]);
	 /* skip too small size mipmap */
 	 if (intelImage == NULL)
		 break;

         if (intelObj->mt != intelImage->mt) {
            intel_miptree_copy_teximage(intel, intelImage, intelObj->mt);
         }
      }
   }

   return true;
}
Пример #23
0
/* Recalculate all state from scratch.  Perhaps not the most
 * efficient, but this has gotten complex enough that we need
 * something which is understandable and reliable.
 */
static bool
i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
{
   struct gl_context *ctx = &intel->ctx;
   struct i830_context *i830 = i830_context(ctx);
   struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit];
   struct gl_texture_object *tObj = tUnit->_Current;
   struct intel_texture_object *intelObj = intel_texture_object(tObj);
   struct gl_texture_image *firstImage;
   struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
   GLuint *state = i830->state.Tex[unit], format, pitch;
   GLint lodbias;
   GLubyte border[4];
   GLuint dst_x, dst_y;

   memset(state, 0, sizeof(*state));

   /*We need to refcount these. */

   if (i830->state.tex_buffer[unit] != NULL) {
       drm_intel_bo_unreference(i830->state.tex_buffer[unit]);
       i830->state.tex_buffer[unit] = NULL;
   }

   if (!intel_finalize_mipmap_tree(intel, unit))
      return false;

   /* Get first image here, since intelObj->firstLevel will get set in
    * the intel_finalize_mipmap_tree() call above.
    */
   firstImage = tObj->Image[0][tObj->BaseLevel];

   intel_miptree_get_image_offset(intelObj->mt, tObj->BaseLevel, 0,
				  &dst_x, &dst_y);

   drm_intel_bo_reference(intelObj->mt->region->bo);
   i830->state.tex_buffer[unit] = intelObj->mt->region->bo;
   pitch = intelObj->mt->region->pitch;

   /* XXX: This calculation is probably broken for tiled images with
    * a non-page-aligned offset.
    */
   i830->state.tex_offset[unit] = dst_x * intelObj->mt->cpp + dst_y * pitch;

   format = translate_texture_format(firstImage->TexFormat);

   state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
                               (LOAD_TEXTURE_MAP0 << unit) | 4);

   state[I830_TEXREG_TM0S1] =
      (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
       ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format);

   if (intelObj->mt->region->tiling != I915_TILING_NONE) {
      state[I830_TEXREG_TM0S1] |= TM0S1_TILED_SURFACE;
      if (intelObj->mt->region->tiling == I915_TILING_Y)
	 state[I830_TEXREG_TM0S1] |= TM0S1_TILE_WALK;
   }

   state[I830_TEXREG_TM0S2] =
      ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK);

   {
      if (tObj->Target == GL_TEXTURE_CUBE_MAP)
         state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) |
                                    CUBE_NEGX_ENABLE |
                                    CUBE_POSX_ENABLE |
                                    CUBE_NEGY_ENABLE |
                                    CUBE_POSY_ENABLE |
                                    CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE);
      else
         state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit));
   }




   {
      GLuint minFilt, mipFilt, magFilt;
      float maxlod;
      uint32_t minlod_fixed, maxlod_fixed;

      switch (sampler->MinFilter) {
      case GL_NEAREST:
         minFilt = FILTER_NEAREST;
         mipFilt = MIPFILTER_NONE;
         break;
      case GL_LINEAR:
         minFilt = FILTER_LINEAR;
         mipFilt = MIPFILTER_NONE;
         break;
      case GL_NEAREST_MIPMAP_NEAREST:
         minFilt = FILTER_NEAREST;
         mipFilt = MIPFILTER_NEAREST;
         break;
      case GL_LINEAR_MIPMAP_NEAREST:
         minFilt = FILTER_LINEAR;
         mipFilt = MIPFILTER_NEAREST;
         break;
      case GL_NEAREST_MIPMAP_LINEAR:
         minFilt = FILTER_NEAREST;
         mipFilt = MIPFILTER_LINEAR;
         break;
      case GL_LINEAR_MIPMAP_LINEAR:
         minFilt = FILTER_LINEAR;
         mipFilt = MIPFILTER_LINEAR;
         break;
      default:
         return false;
      }

      if (sampler->MaxAnisotropy > 1.0) {
         minFilt = FILTER_ANISOTROPIC;
         magFilt = FILTER_ANISOTROPIC;
      }
      else {
         switch (sampler->MagFilter) {
         case GL_NEAREST:
            magFilt = FILTER_NEAREST;
            break;
         case GL_LINEAR:
            magFilt = FILTER_LINEAR;
            break;
         default:
            return false;
         }
      }

      lodbias = (int) ((tUnit->LodBias + sampler->LodBias) * 16.0);
      if (lodbias < -64)
          lodbias = -64;
      if (lodbias > 63)
          lodbias = 63;
      
      state[I830_TEXREG_TM0S3] = ((lodbias << TM0S3_LOD_BIAS_SHIFT) & 
                                  TM0S3_LOD_BIAS_MASK);
#if 0
      /* YUV conversion:
       */
      if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR ||
          firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV)
         state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION;
#endif

      /* We get one field with fraction bits for the maximum
       * addressable (smallest resolution) LOD.  Use it to cover both
       * MAX_LEVEL and MAX_LOD.
       */
      minlod_fixed = U_FIXED(CLAMP(sampler->MinLod, 0.0, 11), 4);
      maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel);
      if (intel->intelScreen->deviceID == PCI_CHIP_I855_GM ||
	  intel->intelScreen->deviceID == PCI_CHIP_I865_G) {
	 maxlod_fixed = U_FIXED(CLAMP(maxlod, 0.0, 11.75), 2);
	 maxlod_fixed = MAX2(maxlod_fixed, (minlod_fixed + 3) >> 2);
	 state[I830_TEXREG_TM0S3] |= maxlod_fixed << TM0S3_MIN_MIP_SHIFT;
	 state[I830_TEXREG_TM0S2] |= TM0S2_LOD_PRECLAMP;
      } else {
Пример #24
0
void
nv20_emit_tex_obj(struct gl_context *ctx, int emit)
{
	const int i = emit - NOUVEAU_STATE_TEX_OBJ0;
	struct nouveau_pushbuf *push = context_push(ctx);
	const int bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART | NOUVEAU_BO_VRAM;
	struct gl_texture_object *t;
	struct nouveau_surface *s;
	struct gl_texture_image *ti;
	const struct gl_sampler_object *sa;
	uint32_t tx_format, tx_filter, tx_wrap, tx_enable;

	PUSH_RESET(push, BUFCTX_TEX(i));

	if (!ctx->Texture.Unit[i]._ReallyEnabled) {
		BEGIN_NV04(push, NV20_3D(TEX_ENABLE(i)), 1);
		PUSH_DATA (push, 0);

		context_dirty(ctx, TEX_SHADER);
		return;
	}

	t = ctx->Texture.Unit[i]._Current;
	s = &to_nouveau_texture(t)->surfaces[t->BaseLevel];
	ti = t->Image[0][t->BaseLevel];
	sa = _mesa_get_samplerobj(ctx, i);

	if (!nouveau_texture_validate(ctx, t))
		return;

	/* Recompute the texturing registers. */
	tx_format = ti->DepthLog2 << 28
		| ti->HeightLog2 << 24
		| ti->WidthLog2 << 20
		| NV20_3D_TEX_FORMAT_DIMS_2D
		| NV20_3D_TEX_FORMAT_NO_BORDER
		| 1 << 16;

	tx_wrap = nvgl_wrap_mode(sa->WrapR) << 16
		| nvgl_wrap_mode(sa->WrapT) << 8
		| nvgl_wrap_mode(sa->WrapS) << 0;

	tx_filter = nvgl_filter_mode(sa->MagFilter) << 24
		| nvgl_filter_mode(sa->MinFilter) << 16
		| 2 << 12;

	tx_enable = NV20_3D_TEX_ENABLE_ENABLE
		| log2i(sa->MaxAnisotropy) << 4;

	if (t->Target == GL_TEXTURE_RECTANGLE) {
		BEGIN_NV04(push, NV20_3D(TEX_NPOT_PITCH(i)), 1);
		PUSH_DATA (push, s->pitch << 16);
		BEGIN_NV04(push, NV20_3D(TEX_NPOT_SIZE(i)), 1);
		PUSH_DATA (push, s->width << 16 | s->height);

		tx_format |= get_tex_format_rect(ti);
	} else {
		tx_format |= get_tex_format_pot(ti);
	}

	if (sa->MinFilter != GL_NEAREST &&
	    sa->MinFilter != GL_LINEAR) {
		int lod_min = sa->MinLod;
		int lod_max = MIN2(sa->MaxLod, t->_MaxLambda);
		int lod_bias = sa->LodBias
			+ ctx->Texture.Unit[i].LodBias;

		lod_max = CLAMP(lod_max, 0, 15);
		lod_min = CLAMP(lod_min, 0, 15);
		lod_bias = CLAMP(lod_bias, 0, 15);

		tx_format |= NV20_3D_TEX_FORMAT_MIPMAP;
		tx_filter |= lod_bias << 8;
		tx_enable |= lod_min << 26
			| lod_max << 14;
	}

	/* Write it to the hardware. */
	BEGIN_NV04(push, NV20_3D(TEX_FORMAT(i)), 1);
	PUSH_MTHD (push, NV20_3D(TEX_FORMAT(i)), BUFCTX_TEX(i),
			 s->bo, tx_format, bo_flags | NOUVEAU_BO_OR,
			 NV20_3D_TEX_FORMAT_DMA0,
			 NV20_3D_TEX_FORMAT_DMA1);

	BEGIN_NV04(push, NV20_3D(TEX_OFFSET(i)), 1);
	PUSH_MTHDl(push, NV20_3D(TEX_OFFSET(i)), BUFCTX_TEX(i),
			 s->bo, s->offset, bo_flags);

	BEGIN_NV04(push, NV20_3D(TEX_WRAP(i)), 1);
	PUSH_DATA (push, tx_wrap);

	BEGIN_NV04(push, NV20_3D(TEX_FILTER(i)), 1);
	PUSH_DATA (push, tx_filter);

	BEGIN_NV04(push, NV20_3D(TEX_ENABLE(i)), 1);
	PUSH_DATA (push, tx_enable);

	context_dirty(ctx, TEX_SHADER);
}
Пример #25
0
static void
convert_sampler(struct st_context *st,
                struct pipe_sampler_state *sampler,
                GLuint texUnit)
{
   const struct gl_texture_object *texobj;
   struct gl_context *ctx = st->ctx;
   const struct gl_sampler_object *msamp;
   GLenum texBaseFormat;

   texobj = ctx->Texture.Unit[texUnit]._Current;
   if (!texobj) {
      texobj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
      msamp = &texobj->Sampler;
   } else {
      msamp = _mesa_get_samplerobj(ctx, texUnit);
   }

   texBaseFormat = _mesa_texture_base_format(texobj);

   memset(sampler, 0, sizeof(*sampler));
   sampler->wrap_s = gl_wrap_xlate(msamp->WrapS);
   sampler->wrap_t = gl_wrap_xlate(msamp->WrapT);
   sampler->wrap_r = gl_wrap_xlate(msamp->WrapR);

   sampler->min_img_filter = gl_filter_to_img_filter(msamp->MinFilter);
   sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->MinFilter);
   sampler->mag_img_filter = gl_filter_to_img_filter(msamp->MagFilter);

   if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB)
      sampler->normalized_coords = 1;

   sampler->lod_bias = ctx->Texture.Unit[texUnit].LodBias + msamp->LodBias;

   sampler->min_lod = MAX2(msamp->MinLod, 0.0f);
   sampler->max_lod = msamp->MaxLod;
   if (sampler->max_lod < sampler->min_lod) {
      /* The GL spec doesn't seem to specify what to do in this case.
       * Swap the values.
       */
      float tmp = sampler->max_lod;
      sampler->max_lod = sampler->min_lod;
      sampler->min_lod = tmp;
      assert(sampler->min_lod <= sampler->max_lod);
   }

   /* For non-black borders... */
   if (msamp->BorderColor.ui[0] ||
       msamp->BorderColor.ui[1] ||
       msamp->BorderColor.ui[2] ||
       msamp->BorderColor.ui[3]) {
      const struct st_texture_object *stobj = st_texture_object_const(texobj);
      const GLboolean is_integer = texobj->_IsIntegerFormat;
      const struct pipe_sampler_view *sv = NULL;
      union pipe_color_union border_color;
      GLuint i;

      /* Just search for the first used view. We can do this because the
         swizzle is per-texture, not per context. */
      /* XXX: clean that up to not use the sampler view at all */
      for (i = 0; i < stobj->num_sampler_views; ++i) {
         if (stobj->sampler_views[i]) {
            sv = stobj->sampler_views[i];
            break;
         }
      }

      if (st->apply_texture_swizzle_to_border_color && sv) {
         const unsigned char swz[4] =
         {
            sv->swizzle_r,
            sv->swizzle_g,
            sv->swizzle_b,
            sv->swizzle_a,
         };

         st_translate_color(&msamp->BorderColor,
                            &border_color,
                            texBaseFormat, is_integer);

         util_format_apply_color_swizzle(&sampler->border_color,
                                         &border_color, swz, is_integer);
      } else {
         st_translate_color(&msamp->BorderColor,
                            &sampler->border_color,
                            texBaseFormat, is_integer);
      }
   }

   sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ?
                              0 : (GLuint) msamp->MaxAnisotropy);

   /* If sampling a depth texture and using shadow comparison */
   if ((texBaseFormat == GL_DEPTH_COMPONENT ||
        texBaseFormat == GL_DEPTH_STENCIL) &&
       msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) {
      sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
      sampler->compare_func = st_compare_func_to_pipe(msamp->CompareFunc);
   }

   sampler->seamless_cube_map =
      ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless;
}
Пример #26
0
void
brw_populate_sampler_prog_key_data(struct gl_context *ctx,
                                   const struct gl_program *prog,
                                   struct brw_sampler_prog_key_data *key)
{
   struct brw_context *brw = brw_context(ctx);
   const struct gen_device_info *devinfo = &brw->screen->devinfo;
   GLbitfield mask = prog->SamplersUsed;

   while (mask) {
      const int s = u_bit_scan(&mask);

      key->swizzles[s] = SWIZZLE_NOOP;
      key->scale_factors[s] = 0.0f;

      int unit_id = prog->SamplerUnits[s];
      const struct gl_texture_unit *unit = &ctx->Texture.Unit[unit_id];

      if (unit->_Current && unit->_Current->Target != GL_TEXTURE_BUFFER) {
         const struct gl_texture_object *t = unit->_Current;
         const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
         struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit_id);

         const bool alpha_depth = t->DepthMode == GL_ALPHA &&
            (img->_BaseFormat == GL_DEPTH_COMPONENT ||
             img->_BaseFormat == GL_DEPTH_STENCIL);

         /* Haswell handles texture swizzling as surface format overrides
          * (except for GL_ALPHA); all other platforms need MOVs in the shader.
          */
         if (alpha_depth || (devinfo->gen < 8 && !devinfo->is_haswell))
            key->swizzles[s] = brw_get_texture_swizzle(ctx, t);

         if (devinfo->gen < 8 &&
             sampler->MinFilter != GL_NEAREST &&
             sampler->MagFilter != GL_NEAREST) {
            if (sampler->WrapS == GL_CLAMP)
               key->gl_clamp_mask[0] |= 1 << s;
            if (sampler->WrapT == GL_CLAMP)
               key->gl_clamp_mask[1] |= 1 << s;
            if (sampler->WrapR == GL_CLAMP)
               key->gl_clamp_mask[2] |= 1 << s;
         }

         /* gather4 for RG32* is broken in multiple ways on Gen7. */
         if (devinfo->gen == 7 && prog->info.uses_texture_gather) {
            switch (img->InternalFormat) {
            case GL_RG32I:
            case GL_RG32UI: {
               /* We have to override the format to R32G32_FLOAT_LD.
                * This means that SCS_ALPHA and SCS_ONE will return 0x3f8
                * (1.0) rather than integer 1.  This needs shader hacks.
                *
                * On Ivybridge, we whack W (alpha) to ONE in our key's
                * swizzle.  On Haswell, we look at the original texture
                * swizzle, and use XYZW with channels overridden to ONE,
                * leaving normal texture swizzling to SCS.
                */
               unsigned src_swizzle =
                  devinfo->is_haswell ? t->_Swizzle : key->swizzles[s];
               for (int i = 0; i < 4; i++) {
                  unsigned src_comp = GET_SWZ(src_swizzle, i);
                  if (src_comp == SWIZZLE_ONE || src_comp == SWIZZLE_W) {
                     key->swizzles[i] &= ~(0x7 << (3 * i));
                     key->swizzles[i] |= SWIZZLE_ONE << (3 * i);
                  }
               }
               /* fallthrough */
            }
            case GL_RG32F:
               /* The channel select for green doesn't work - we have to
                * request blue.  Haswell can use SCS for this, but Ivybridge
                * needs a shader workaround.
                */
               if (!devinfo->is_haswell)
                  key->gather_channel_quirk_mask |= 1 << s;
               break;
            }
         }

         /* Gen6's gather4 is broken for UINT/SINT; we treat them as
          * UNORM/FLOAT instead and fix it in the shader.
          */
         if (devinfo->gen == 6 && prog->info.uses_texture_gather) {
            key->gen6_gather_wa[s] = gen6_gather_workaround(img->InternalFormat);
         }

         /* If this is a multisample sampler, and uses the CMS MSAA layout,
          * then we need to emit slightly different code to first sample the
          * MCS surface.
          */
         struct intel_texture_object *intel_tex =
            intel_texture_object((struct gl_texture_object *)t);

         /* From gen9 onwards some single sampled buffers can also be
          * compressed. These don't need ld2dms sampling along with mcs fetch.
          */
         if (intel_tex->mt->aux_usage == ISL_AUX_USAGE_MCS) {
            assert(devinfo->gen >= 7);
            assert(intel_tex->mt->surf.samples > 1);
            assert(intel_tex->mt->aux_buf);
            assert(intel_tex->mt->surf.msaa_layout == ISL_MSAA_LAYOUT_ARRAY);
            key->compressed_multisample_layout_mask |= 1 << s;

            if (intel_tex->mt->surf.samples >= 16) {
               assert(devinfo->gen >= 9);
               key->msaa_16 |= 1 << s;
            }
         }

         if (t->Target == GL_TEXTURE_EXTERNAL_OES && intel_tex->planar_format) {

            /* Setup possible scaling factor. */
            key->scale_factors[s] = intel_tex->planar_format->scaling_factor;

            switch (intel_tex->planar_format->components) {
            case __DRI_IMAGE_COMPONENTS_Y_UV:
               key->y_uv_image_mask |= 1 << s;
               break;
            case __DRI_IMAGE_COMPONENTS_Y_U_V:
               key->y_u_v_image_mask |= 1 << s;
               break;
            case __DRI_IMAGE_COMPONENTS_Y_XUXV:
               key->yx_xuxv_image_mask |= 1 << s;
               break;
            case __DRI_IMAGE_COMPONENTS_Y_UXVX:
               key->xy_uxvx_image_mask |= 1 << s;
               break;
            case __DRI_IMAGE_COMPONENTS_AYUV:
               key->ayuv_image_mask |= 1 << s;
               break;
            case __DRI_IMAGE_COMPONENTS_XYUV:
               key->xyuv_image_mask |= 1 << s;
               break;
            default:
               break;
            }
         }

      }
   }
}
Пример #27
0
static GLboolean
update_single_texture(struct st_context *st,
                      struct pipe_sampler_view **sampler_view,
		      GLuint texUnit)
{
   struct pipe_context *pipe = st->pipe;
   struct gl_context *ctx = st->ctx;
   const struct gl_sampler_object *samp;
   struct gl_texture_object *texObj;
   struct st_texture_object *stObj;
   enum pipe_format st_view_format;
   GLboolean retval;

   samp = _mesa_get_samplerobj(ctx, texUnit);

   texObj = ctx->Texture.Unit[texUnit]._Current;

   if (!texObj) {
      texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
      samp = &texObj->Sampler;
   }
   stObj = st_texture_object(texObj);

   retval = st_finalize_texture(ctx, st->pipe, texObj);
   if (!retval) {
      /* out of mem */
      return GL_FALSE;
   }

   /* Determine the format of the texture sampler view */
   st_view_format = stObj->pt->format;
   {
      const struct st_texture_image *firstImage =
	 st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
      const gl_format texFormat = firstImage->base.TexFormat;
      enum pipe_format firstImageFormat =
	 st_mesa_format_to_pipe_format(texFormat);

      if ((samp->sRGBDecode == GL_SKIP_DECODE_EXT) &&
	  (_mesa_get_format_color_encoding(texFormat) == GL_SRGB)) {
         /* Don't do sRGB->RGB conversion.  Interpret the texture data as
          * linear values.
          */
	 const gl_format linearFormat =
	    _mesa_get_srgb_format_linear(texFormat);
	 firstImageFormat = st_mesa_format_to_pipe_format(linearFormat);
      }

      if (firstImageFormat != stObj->pt->format)
	 st_view_format = firstImageFormat;
   }

   /* if sampler view has changed dereference it */
   if (stObj->sampler_view) {
      if (check_sampler_swizzle(stObj->sampler_view,
				stObj->base._Swizzle,
				samp->DepthMode) ||
	  (st_view_format != stObj->sampler_view->format) ||
	  stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) {
	 pipe_sampler_view_reference(&stObj->sampler_view, NULL);
      }
   }

   *sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe,
							  samp,
							  st_view_format);
   return GL_TRUE;
}