diff options
Diffstat (limited to 'mesalib/src/mesa')
31 files changed, 733 insertions, 259 deletions
| diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index 29a209ede..8114550ba 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -3118,6 +3118,7 @@ setup_texture_coords(GLenum faceTarget,                       GLint slice,                       GLint width,                       GLint height, +                     GLint depth,                       GLfloat coords0[3],                       GLfloat coords1[3],                       GLfloat coords2[3], @@ -3134,8 +3135,11 @@ setup_texture_coords(GLenum faceTarget,     case GL_TEXTURE_2D:     case GL_TEXTURE_3D:     case GL_TEXTURE_2D_ARRAY: -      if (faceTarget == GL_TEXTURE_3D) -         r = 1.0F / slice; +      if (faceTarget == GL_TEXTURE_3D) { +         assert(slice < depth); +         assert(depth >= 1); +         r = (slice + 0.5f) / depth; +      }        else if (faceTarget == GL_TEXTURE_2D_ARRAY)           r = slice;        else @@ -3571,10 +3575,10 @@ _mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,     else        assert(!genMipmapSave); -  /* Setup texture coordinates */ +   /* Setup texture coordinates */     setup_texture_coords(faceTarget,                          slice, -                        0, 0, /* width, height never used here */ +                        0, 0, 1, /* width, height never used here */                          verts[0].tex,                          verts[1].tex,                          verts[2].tex, @@ -3840,6 +3844,7 @@ decompress_texture_image(struct gl_context *ctx,     struct gl_texture_object *texObj = texImage->TexObject;     const GLint width = texImage->Width;     const GLint height = texImage->Height; +   const GLint depth = texImage->Height;     const GLenum target = texObj->Target;     GLenum faceTarget;     struct vertex { @@ -3935,7 +3940,7 @@ decompress_texture_image(struct gl_context *ctx,        _mesa_BindSampler(ctx->Texture.CurrentUnit, decompress->Sampler);     } -   setup_texture_coords(faceTarget, slice, width, height, +   setup_texture_coords(faceTarget, slice, width, height, depth,                          verts[0].tex,                          verts[1].tex,                          verts[2].tex, diff --git a/mesalib/src/mesa/drivers/dri/common/xmlpool/t_options.h b/mesalib/src/mesa/drivers/dri/common/xmlpool/t_options.h index 1e7eced06..7b441c68f 100644 --- a/mesalib/src/mesa/drivers/dri/common/xmlpool/t_options.h +++ b/mesalib/src/mesa/drivers/dri/common/xmlpool/t_options.h @@ -75,6 +75,11 @@ DRI_CONF_OPT_BEGIN(always_flush_cache,bool,def) \          DRI_CONF_DESC(en,gettext("Enable flushing GPU caches with each draw call")) \  DRI_CONF_OPT_END +#define DRI_CONF_DISABLE_THROTTLING(def) \ +DRI_CONF_OPT_BEGIN(disable_throttling,bool,def) \ +	DRI_CONF_DESC(en,gettext("Disable throttling on first batch after flush")) \ +DRI_CONF_OPT_END +  #define DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN(def) \  DRI_CONF_OPT_BEGIN(force_glsl_extensions_warn,bool,def) \          DRI_CONF_DESC(en,gettext("Force GLSL extension default behavior to 'warn'")) \ diff --git a/mesalib/src/mesa/main/compiler.h b/mesalib/src/mesa/main/compiler.h index 48712485a..8b23665e6 100644 --- a/mesalib/src/mesa/main/compiler.h +++ b/mesalib/src/mesa/main/compiler.h @@ -307,8 +307,9 @@ static INLINE GLuint CPU_TO_LE32(GLuint x)   * USE_IEEE: Determine if we're using IEEE floating point   */  #if defined(__i386__) || defined(__386__) || defined(__sparc__) || \ -    defined(__s390x__) || defined(__powerpc__) || \ +    defined(__s390__) || defined(__s390x__) || defined(__powerpc__) || \      defined(__x86_64__) || \ +    defined(__m68k__) || \      defined(ia64) || defined(__ia64__) || \      defined(__hppa__) || defined(hpux) || \      defined(__mips) || defined(_MIPS_ARCH) || \ diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index 4860d4d12..8f3cd3d6b 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -195,9 +195,10 @@ struct dd_function_table {                                       GLenum srcFormat, GLenum srcType );     /** -    * Determine sample counts support for a particular format +    * Determine sample counts support for a particular target and format      *      * \param ctx            GL context +    * \param target         GL target enum      * \param internalFormat GL format enum      * \param samples        Buffer to hold the returned sample counts.      *                       Drivers \b must \b not return more than 16 counts. @@ -207,6 +208,7 @@ struct dd_function_table {      * \c internaFormat is not renderable, zero is returned.      */     size_t (*QuerySamplesForFormat)(struct gl_context *ctx, +                                   GLenum target,                                     GLenum internalFormat,                                     int samples[16]); diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 0126e2930..3fdf62667 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -43,6 +43,7 @@  #include "hash.h"  #include "macros.h"  #include "mfeatures.h" +#include "multisample.h"  #include "mtypes.h"  #include "renderbuffer.h"  #include "state.h" @@ -474,6 +475,32 @@ _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)  /** + * Return true if the framebuffer has a combined depth/stencil + * renderbuffer attached. + */ +GLboolean +_mesa_has_depthstencil_combined(const struct gl_framebuffer *fb) +{ +   const struct gl_renderbuffer_attachment *depth = +         &fb->Attachment[BUFFER_DEPTH]; +   const struct gl_renderbuffer_attachment *stencil = +         &fb->Attachment[BUFFER_STENCIL]; + +   if (depth->Type == stencil->Type) { +      if (depth->Type == GL_RENDERBUFFER_EXT && +          depth->Renderbuffer == stencil->Renderbuffer) +         return GL_TRUE; + +      if (depth->Type == GL_TEXTURE && +          depth->Texture == stencil->Texture) +         return GL_TRUE; +   } + +   return GL_FALSE; +} + + +/**   * For debug only.   */  static void @@ -1466,6 +1493,7 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,        "glRenderbufferStorage" : "glRenderbufferStorageMultisample";     struct gl_renderbuffer *rb;     GLenum baseFormat; +   GLenum sample_count_error;     GET_CURRENT_CONTEXT(ctx);     if (MESA_VERBOSE & VERBOSE_API) { @@ -1509,9 +1537,14 @@ renderbuffer_storage(GLenum target, GLenum internalFormat,        /* NumSamples == 0 indicates non-multisampling */        samples = 0;     } -   else if (samples > (GLsizei) ctx->Const.MaxSamples) { -      /* note: driver may choose to use more samples than what's requested */ -      _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples)", func); + +   /* check the sample count; +    * note: driver may choose to use more samples than what's requested +    */ +   sample_count_error = _mesa_check_sample_count(ctx, target, +         internalFormat, samples); +   if (sample_count_error != GL_NO_ERROR) { +      _mesa_error(ctx, sample_count_error, "%s(samples)", func);        return;     } diff --git a/mesalib/src/mesa/main/fbobject.h b/mesalib/src/mesa/main/fbobject.h index ec8b0afe4..0358864d7 100644 --- a/mesalib/src/mesa/main/fbobject.h +++ b/mesalib/src/mesa/main/fbobject.h @@ -113,6 +113,9 @@ _mesa_framebuffer_renderbuffer(struct gl_context *ctx,  extern void  _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb); +extern GLboolean +_mesa_has_depthstencil_combined(const struct gl_framebuffer *fb); +  extern void  _mesa_test_framebuffer_completeness(struct gl_context *ctx,                                      struct gl_framebuffer *fb); diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp index 186988bbd..01a4542d7 100644 --- a/mesalib/src/mesa/main/ff_fragment_shader.cpp +++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp @@ -1350,22 +1350,6 @@ create_new_program(struct gl_context *ctx, struct state_key *key)     _mesa_glsl_link_shader(ctx, p.shader_program); -   /* Set the sampler uniforms, and relink to get them into the linked -    * program. -    */ -   struct gl_shader *const fs = -      p.shader_program->_LinkedShaders[MESA_SHADER_FRAGMENT]; -   struct gl_program *const fp = fs->Program; - -   _mesa_generate_parameters_list_for_uniforms(p.shader_program, fs, -					       fp->Parameters); - -   _mesa_associate_uniform_storage(ctx, p.shader_program, fp->Parameters); - -   _mesa_update_shader_textures_used(p.shader_program, fp); -   if (ctx->Driver.SamplerUniformChange) -      ctx->Driver.SamplerUniformChange(ctx, fp->Target, fp); -     if (!p.shader_program->LinkStatus)        _mesa_problem(ctx, "Failed to link fixed function fragment shader: %s\n",  		    p.shader_program->InfoLog); diff --git a/mesalib/src/mesa/main/formatquery.c b/mesalib/src/mesa/main/formatquery.c index bd895e874..78c5fbe5e 100644 --- a/mesalib/src/mesa/main/formatquery.c +++ b/mesalib/src/mesa/main/formatquery.c @@ -59,9 +59,10 @@ _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname,     case GL_TEXTURE_2D_MULTISAMPLE:     case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: -      /* Mesa does not currently support GL_ARB_texture_multisample, so these -       * enums are not valid on this implementation either. -       */ +      /* These enums are only valid if ARB_texture_multisample is supported */ +      if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_multisample) +         break; +     default:        _mesa_error(ctx, GL_INVALID_ENUM,                    "glGetInternalformativ(target=%s)", @@ -96,7 +97,8 @@ _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname,     switch (pname) {     case GL_SAMPLES: -      count = ctx->Driver.QuerySamplesForFormat(ctx, internalformat, buffer); +      count = ctx->Driver.QuerySamplesForFormat(ctx, target, +            internalformat, buffer);        break;     case GL_NUM_SAMPLE_COUNTS: {        /* The driver can return 0, and we should pass that along to the @@ -115,7 +117,7 @@ _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname,         *          returned."         */        const size_t num_samples = -         ctx->Driver.QuerySamplesForFormat(ctx, internalformat, buffer); +         ctx->Driver.QuerySamplesForFormat(ctx, target, internalformat, buffer);        /* QuerySamplesForFormat writes some stuff to buffer, so we have to         * separately over-write it with the requested value. diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index d3abc2b30..619aaa337 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -923,10 +923,10 @@ _mesa_get_color_read_type(struct gl_context *ctx)   * Returns the read renderbuffer for the specified format.   */  struct gl_renderbuffer * -_mesa_get_read_renderbuffer_for_format(struct gl_context *ctx, +_mesa_get_read_renderbuffer_for_format(const struct gl_context *ctx,                                         GLenum format)  { -   struct gl_framebuffer *rfb = ctx->ReadBuffer; +   const struct gl_framebuffer *rfb = ctx->ReadBuffer;     if (_mesa_is_color_format(format)) {        return rfb->Attachment[rfb->_ColorReadBufferIndex].Renderbuffer; diff --git a/mesalib/src/mesa/main/framebuffer.h b/mesalib/src/mesa/main/framebuffer.h index 06db04925..9b94452d6 100644 --- a/mesalib/src/mesa/main/framebuffer.h +++ b/mesalib/src/mesa/main/framebuffer.h @@ -98,7 +98,7 @@ extern GLenum  _mesa_get_color_read_format(struct gl_context *ctx);  extern struct gl_renderbuffer * -_mesa_get_read_renderbuffer_for_format(struct gl_context *ctx, +_mesa_get_read_renderbuffer_for_format(const struct gl_context *ctx,                                         GLenum format);  extern void diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 83b6c8984..a0e7e281d 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1179,6 +1179,7 @@ struct gl_texture_object     GLfloat Priority;		/**< in [0,1] */     GLint BaseLevel;		/**< min mipmap level, OpenGL 1.2 */     GLint MaxLevel;		/**< max mipmap level, OpenGL 1.2 */ +   GLint ImmutableLevels;       /**< ES 3.0 / ARB_texture_view */     GLint _MaxLevel;		/**< actual max mipmap level (q in the spec) */     GLfloat _MaxLambda;		/**< = _MaxLevel - BaseLevel (q - b in spec) */     GLint CropRect[4];           /**< GL_OES_draw_texture */ @@ -1796,6 +1797,7 @@ struct gl_transform_feedback_state  typedef enum  {     PROGRAM_TEMPORARY,   /**< machine->Temporary[] */ +   PROGRAM_ARRAY,       /**< Arrays & Matrixes */     PROGRAM_INPUT,       /**< machine->Inputs[] */     PROGRAM_OUTPUT,      /**< machine->Outputs[] */     PROGRAM_LOCAL_PARAM, /**< gl_program->LocalParams[] */ diff --git a/mesalib/src/mesa/main/multisample.c b/mesalib/src/mesa/main/multisample.c index 248494615..b0f45d933 100644 --- a/mesalib/src/mesa/main/multisample.c +++ b/mesalib/src/mesa/main/multisample.c @@ -29,6 +29,7 @@  #include "main/multisample.h"  #include "main/mtypes.h"  #include "main/fbobject.h" +#include "main/glformats.h"  /** @@ -112,3 +113,79 @@ _mesa_SampleMaski(GLuint index, GLbitfield mask)     FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);     ctx->Multisample.SampleMaskValue = mask;  } + + +/* Helper for checking a requested sample count against the limit + * for a particular (target, internalFormat) pair. The limit imposed, + * and the error generated, both depend on which extensions are supported. + * + * Returns a GL error enum, or GL_NO_ERROR if the requested sample count is + * acceptable. + */ +GLenum +_mesa_check_sample_count(struct gl_context *ctx, GLenum target, +                         GLenum internalFormat, GLsizei samples) +{ +   /* If ARB_internalformat_query is supported, then treat its highest returned sample +    * count as the absolute maximum for this format; it is allowed to exceed MAX_SAMPLES. +    * +    * From the ARB_internalformat_query spec: +    * +    * "If <samples is greater than the maximum number of samples supported +    * for <internalformat> then the error INVALID_OPERATION is generated." +    */ +   if (ctx->Extensions.ARB_internalformat_query) { +      GLint buffer[16]; +      int count = ctx->Driver.QuerySamplesForFormat(ctx, target, internalFormat, buffer); +      int limit = count ? buffer[0] : -1; + +      return samples > limit ? GL_INVALID_OPERATION : GL_NO_ERROR; +   } + +   /* If ARB_texture_multisample is supported, we have separate limits, +    * which may be lower than MAX_SAMPLES: +    * +    * From the ARB_texture_multisample spec, when describing the operation +    * of RenderbufferStorageMultisample: +    * +    * "If <internalformat> is a signed or unsigned integer format and +    * <samples> is greater than the value of MAX_INTEGER_SAMPLES, then the +    * error INVALID_OPERATION is generated" +    * +    * And when describing the operation of TexImage*Multisample: +    * +    * "The error INVALID_OPERATION may be generated if any of the following are true: +    * +    * * <internalformat> is a depth/stencil-renderable format and <samples> +    *   is greater than the value of MAX_DEPTH_TEXTURE_SAMPLES +    * * <internalformat> is a color-renderable format and <samples> is +    *   grater than the value of MAX_COLOR_TEXTURE_SAMPLES +    * * <internalformat> is a signed or unsigned integer format and +    *   <samples> is greater than the value of MAX_INTEGER_SAMPLES +    */ + +   if (ctx->Extensions.ARB_texture_multisample) { +      if (_mesa_is_enum_format_integer(internalFormat)) +         return samples > ctx->Const.MaxIntegerSamples ? GL_INVALID_OPERATION : GL_NO_ERROR; + +      if (target == GL_TEXTURE_2D_MULTISAMPLE || +          target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { + +         if (_mesa_is_depth_or_stencil_format(internalFormat)) +            return samples > ctx->Const.MaxDepthTextureSamples +               ? GL_INVALID_OPERATION : GL_NO_ERROR; +         else +            return samples > ctx->Const.MaxColorTextureSamples +               ? GL_INVALID_OPERATION : GL_NO_ERROR; +      } +   } + +   /* No more specific limit is available, so just use MAX_SAMPLES: +    * +    * On p205 of the GL3.1 spec: +    * +    * "... or if samples is greater than MAX_SAMPLES, then the error +    * INVALID_VALUE is generated" +    */ +   return samples > ctx->Const.MaxSamples ? GL_INVALID_VALUE : GL_NO_ERROR; +} diff --git a/mesalib/src/mesa/main/multisample.h b/mesalib/src/mesa/main/multisample.h index 9e6b8e0d3..f2f01de5c 100644 --- a/mesalib/src/mesa/main/multisample.h +++ b/mesalib/src/mesa/main/multisample.h @@ -44,4 +44,9 @@ _mesa_GetMultisamplefv(GLenum pname, GLuint index, GLfloat* val);  extern void GLAPIENTRY  _mesa_SampleMaski(GLuint index, GLbitfield mask); + +extern GLenum +_mesa_check_sample_count(struct gl_context *ctx, GLenum target, +                   GLenum internalFormat, GLsizei samples); +  #endif diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index 2f130ae9a..d3d09dea3 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -41,11 +41,212 @@  /** - * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the - * mapping. + * Return true if the conversion L=R+G+B is needed.   */  static GLboolean -fast_read_depth_pixels( struct gl_context *ctx, +need_rgb_to_luminance_conversion(gl_format texFormat, GLenum format) +{ +   GLenum baseTexFormat = _mesa_get_format_base_format(texFormat); + +   return (baseTexFormat == GL_RG || +           baseTexFormat == GL_RGB || +           baseTexFormat == GL_RGBA) && +          (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA); +} + + +/** + * Return transfer op flags for this ReadPixels operation. + */ +static GLbitfield +get_readpixels_transfer_ops(const struct gl_context *ctx, gl_format texFormat, +                            GLenum format, GLenum type, GLboolean uses_blit) +{ +   GLbitfield transferOps = ctx->_ImageTransferState; + +   if (format == GL_DEPTH_COMPONENT || +       format == GL_DEPTH_STENCIL || +       format == GL_STENCIL_INDEX) { +      return 0; +   } + +   /* Pixel transfer ops (scale, bias, table lookup) do not apply +    * to integer formats. +    */ +   if (_mesa_is_enum_format_integer(format)) { +      return 0; +   } + +   if (uses_blit) { +      /* For blit-based ReadPixels packing, the clamping is done automatically +       * unless the type is float. */ +      if (ctx->Color._ClampReadColor == GL_TRUE && +          (type == GL_FLOAT || type == GL_HALF_FLOAT)) { +         transferOps |= IMAGE_CLAMP_BIT; +      } +   } +   else { +      /* For CPU-based ReadPixels packing, the clamping must always be done +       * for non-float types, */ +      if (ctx->Color._ClampReadColor == GL_TRUE || +          (type != GL_FLOAT && type != GL_HALF_FLOAT)) { +         transferOps |= IMAGE_CLAMP_BIT; +      } +   } + +   /* If the format is unsigned normalized, we can ignore clamping +    * because the values are already in the range [0,1] so it won't +    * have any effect anyway. +    */ +   if (_mesa_get_format_datatype(texFormat) == GL_UNSIGNED_NORMALIZED && +       !need_rgb_to_luminance_conversion(texFormat, format)) { +      transferOps &= ~IMAGE_CLAMP_BIT; +   } + +   return transferOps; +} + + +/** + * Return true if memcpy cannot be used for ReadPixels. + * + * If uses_blit is true, the function returns true if a simple 3D engine blit + * cannot be used for ReadPixels packing. + * + * NOTE: This doesn't take swizzling and format conversions between + *       the readbuffer and the pixel pack buffer into account. + */ +GLboolean +_mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format, +                                 GLenum type, GLboolean uses_blit) +{ +   struct gl_renderbuffer *rb = +         _mesa_get_read_renderbuffer_for_format(ctx, format); +   GLenum srcType; + +   ASSERT(rb); + +   /* There are different rules depending on the base format. */ +   switch (format) { +   case GL_DEPTH_STENCIL: +      return !_mesa_has_depthstencil_combined(ctx->ReadBuffer) || +             ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f || +             ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset || +             ctx->Pixel.MapStencilFlag; + +   case GL_DEPTH_COMPONENT: +      return ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f; + +   case GL_STENCIL_INDEX: +      return ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset || +             ctx->Pixel.MapStencilFlag; + +   default: +      /* Color formats. */ +      if (need_rgb_to_luminance_conversion(rb->Format, format)) { +         return GL_TRUE; +      } + +      /* Conversion between signed and unsigned integers needs masking +       * (it isn't just memcpy). */ +      srcType = _mesa_get_format_datatype(rb->Format); + +      if ((srcType == GL_INT && +           (type == GL_UNSIGNED_INT || +            type == GL_UNSIGNED_SHORT || +            type == GL_UNSIGNED_BYTE)) || +          (srcType == GL_UNSIGNED_INT && +           (type == GL_INT || +            type == GL_SHORT || +            type == GL_BYTE))) { +         return GL_TRUE; +      } + +      /* And finally, see if there are any transfer ops. */ +      return get_readpixels_transfer_ops(ctx, rb->Format, format, type, +                                         uses_blit) != 0; +   } +   return GL_FALSE; +} + + +static GLboolean +readpixels_can_use_memcpy(const struct gl_context *ctx, GLenum format, GLenum type, +                          const struct gl_pixelstore_attrib *packing) +{ +   struct gl_renderbuffer *rb = +         _mesa_get_read_renderbuffer_for_format(ctx, format); + +   ASSERT(rb); + +   if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_FALSE)) { +      return GL_FALSE; +   } + +   /* The base internal format and the base Mesa format must match. */ +   if (rb->_BaseFormat != _mesa_get_format_base_format(rb->Format)) { +      return GL_FALSE; +   } + +   /* The Mesa format must match the input format and type. */ +   if (!_mesa_format_matches_format_and_type(rb->Format, format, type, +                                             packing->SwapBytes)) { +      return GL_FALSE; +   } + +   return GL_TRUE; +} + + +static GLboolean +readpixels_memcpy(struct gl_context *ctx, +                  GLint x, GLint y, +                  GLsizei width, GLsizei height, +                  GLenum format, GLenum type, +                  GLvoid *pixels, +                  const struct gl_pixelstore_attrib *packing) +{ +   struct gl_renderbuffer *rb = +         _mesa_get_read_renderbuffer_for_format(ctx, format); +   GLubyte *dst, *map; +   int dstStride, stride, j, texelBytes; + +   /* Fail if memcpy cannot be used. */ +   if (!readpixels_can_use_memcpy(ctx, format, type, packing)) { +      return GL_FALSE; +   } + +   dstStride = _mesa_image_row_stride(packing, width, format, type); +   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, +					   format, type, 0, 0); + +   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, +			       &map, &stride); +   if (!map) { +      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); +      return GL_TRUE;  /* don't bother trying the slow path */ +   } + +   texelBytes = _mesa_get_format_bytes(rb->Format); + +   /* memcpy*/ +   for (j = 0; j < height; j++) { +      memcpy(dst, map, width * texelBytes); +      dst += dstStride; +      map += stride; +   } + +   ctx->Driver.UnmapRenderbuffer(ctx, rb); +   return GL_TRUE; +} + + +/** + * Optimized path for conversion of depth values to GL_DEPTH_COMPONENT, + * GL_UNSIGNED_INT. + */ +static GLboolean +read_uint_depth_pixels( struct gl_context *ctx,  			GLint x, GLint y,  			GLsizei width, GLsizei height,  			GLenum type, GLvoid *pixels, @@ -65,10 +266,6 @@ fast_read_depth_pixels( struct gl_context *ctx,     if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED)        return GL_FALSE; -   if (!((type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16) || -	 type == GL_UNSIGNED_INT)) -      return GL_FALSE; -     ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,  			       &map, &stride); @@ -82,12 +279,7 @@ fast_read_depth_pixels( struct gl_context *ctx,  					   GL_DEPTH_COMPONENT, type, 0, 0);     for (j = 0; j < height; j++) { -      if (type == GL_UNSIGNED_INT) { -	 _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst); -      } else { -	 ASSERT(type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16); -	 memcpy(dst, map, width * 2); -      } +      _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst);        map += stride;        dst += dstStride; @@ -123,8 +315,10 @@ read_depth_pixels( struct gl_context *ctx,     ASSERT(x + width <= (GLint) rb->Width);     ASSERT(y + height <= (GLint) rb->Height); -   if (fast_read_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) +   if (type == GL_UNSIGNED_INT && +       read_uint_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) {        return; +   }     dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);     dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, @@ -212,21 +406,20 @@ read_stencil_pixels( struct gl_context *ctx,  /** - * Try to do glReadPixels of RGBA data using a simple memcpy or swizzle. + * Try to do glReadPixels of RGBA data using swizzle.   * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path)   */  static GLboolean -fast_read_rgba_pixels_memcpy( struct gl_context *ctx, -			      GLint x, GLint y, -			      GLsizei width, GLsizei height, -			      GLenum format, GLenum type, -			      GLvoid *pixels, -			      const struct gl_pixelstore_attrib *packing, -			      GLbitfield transferOps ) +read_rgba_pixels_swizzle(struct gl_context *ctx, +                         GLint x, GLint y, +                         GLsizei width, GLsizei height, +                         GLenum format, GLenum type, +                         GLvoid *pixels, +                         const struct gl_pixelstore_attrib *packing)  {     struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;     GLubyte *dst, *map; -   int dstStride, stride, j, texelBytes; +   int dstStride, stride, j;     GLboolean swizzle_rb = GL_FALSE, copy_xrgb = GL_FALSE;     /* XXX we could check for other swizzle/special cases here as needed */ @@ -242,19 +435,9 @@ fast_read_rgba_pixels_memcpy( struct gl_context *ctx,         !ctx->Pack.SwapBytes) {        copy_xrgb = GL_TRUE;     } -   else if (!_mesa_format_matches_format_and_type(rb->Format, format, type, -                                                  ctx->Pack.SwapBytes)) -      return GL_FALSE; - -   /* If the format is unsigned normalized then we can ignore clamping -    * because the values are already in the range [0,1] so it won't -    * have any effect anyway. -    */ -   if (_mesa_get_format_datatype(rb->Format) == GL_UNSIGNED_NORMALIZED) -      transferOps &= ~IMAGE_CLAMP_BIT; - -   if (transferOps) +   else {        return GL_FALSE; +   }     dstStride = _mesa_image_row_stride(packing, width, format, type);     dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, @@ -267,8 +450,6 @@ fast_read_rgba_pixels_memcpy( struct gl_context *ctx,        return GL_TRUE;  /* don't bother trying the slow path */     } -   texelBytes = _mesa_get_format_bytes(rb->Format); -     if (swizzle_rb) {        /* swap R/B */        for (j = 0; j < height; j++) { @@ -294,13 +475,6 @@ fast_read_rgba_pixels_memcpy( struct gl_context *ctx,           dst += dstStride;           map += stride;        } -   } else { -      /* just memcpy */ -      for (j = 0; j < height; j++) { -         memcpy(dst, map, width * texelBytes); -         dst += dstStride; -         map += stride; -      }     }     ctx->Driver.UnmapRenderbuffer(ctx, rb); @@ -379,22 +553,20 @@ read_rgba_pixels( struct gl_context *ctx,                    GLenum format, GLenum type, GLvoid *pixels,                    const struct gl_pixelstore_attrib *packing )  { -   GLbitfield transferOps = ctx->_ImageTransferState; +   GLbitfield transferOps;     struct gl_framebuffer *fb = ctx->ReadBuffer;     struct gl_renderbuffer *rb = fb->_ColorReadBuffer;     if (!rb)        return; -   if ((ctx->Color._ClampReadColor == GL_TRUE || type != GL_FLOAT) && -       !_mesa_is_enum_format_integer(format)) { -      transferOps |= IMAGE_CLAMP_BIT; -   } +   transferOps = get_readpixels_transfer_ops(ctx, rb->Format, format, type, +                                             GL_FALSE);     /* Try the optimized paths first. */ -   if (fast_read_rgba_pixels_memcpy(ctx, x, y, width, height, -                                    format, type, pixels, packing, -                                    transferOps)) { +   if (!transferOps && +       read_rgba_pixels_swizzle(ctx, x, y, width, height, +                                    format, type, pixels, packing)) {        return;     } @@ -649,6 +821,14 @@ _mesa_readpixels(struct gl_context *ctx,        pixels = _mesa_map_pbo_dest(ctx, &clippedPacking, pixels);        if (pixels) { +         /* Try memcpy first. */ +         if (readpixels_memcpy(ctx, x, y, width, height, format, type, +                               pixels, packing)) { +            _mesa_unmap_pbo_dest(ctx, &clippedPacking); +            return; +         } + +         /* Otherwise take the slow path. */           switch (format) {           case GL_STENCIL_INDEX:              read_stencil_pixels(ctx, x, y, width, height, type, pixels, diff --git a/mesalib/src/mesa/main/readpix.h b/mesalib/src/mesa/main/readpix.h index 5a5f73f52..7491c22ff 100644 --- a/mesalib/src/mesa/main/readpix.h +++ b/mesalib/src/mesa/main/readpix.h @@ -33,6 +33,10 @@ struct gl_context;  struct gl_pixelstore_attrib; +extern GLboolean +_mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format, +                                 GLenum type, GLboolean uses_blit); +  extern void  _mesa_readpixels(struct gl_context *ctx,                   GLint x, GLint y, GLsizei width, GLsizei height, diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index 7299a4b23..74b09ef2c 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -518,6 +518,7 @@ get_tex_rgba(struct gl_context *ctx, GLuint dimensions,     if (type_needs_clamping(type)) {        /* the returned image type can't have negative values */        if (dataType == GL_FLOAT || +          dataType == GL_HALF_FLOAT ||            dataType == GL_SIGNED_NORMALIZED ||            format == GL_LUMINANCE ||            format == GL_LUMINANCE_ALPHA) { diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 4042e7969..bc755ae79 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -40,6 +40,7 @@  #include "imports.h"  #include "macros.h"  #include "mfeatures.h" +#include "multisample.h"  #include "state.h"  #include "texcompress.h"  #include "texcompress_cpal.h" @@ -4199,6 +4200,7 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples,     struct gl_texture_image *texImage;     GLboolean sizeOK, dimensionsOK;     gl_format texFormat; +   GLenum sample_count_error;     GET_CURRENT_CONTEXT(ctx); @@ -4225,35 +4227,13 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples,        return;     } -   if (_mesa_is_enum_format_integer(internalformat)) { -      if (samples > ctx->Const.MaxIntegerSamples) { -         _mesa_error(ctx, GL_INVALID_OPERATION, -               "glTexImage%uDMultisample(samples>GL_MAX_INTEGER_SAMPLES)", -               dims); -         return; -      } -   } -   else if (_mesa_is_depth_or_stencil_format(internalformat)) { -      if (samples > ctx->Const.MaxDepthTextureSamples) { -         _mesa_error(ctx, GL_INVALID_OPERATION, -               "glTexImage%uDMultisample(samples>GL_MAX_DEPTH_TEXTURE_SAMPLES)", -               dims); -         return; -      } -   } -   else { -      if (samples > ctx->Const.MaxColorTextureSamples) { -         _mesa_error(ctx, GL_INVALID_OPERATION, -               "glTexImage%uDMultisample(samples>GL_MAX_COLOR_TEXTURE_SAMPLES)", -               dims); -         return; -      } +   sample_count_error = _mesa_check_sample_count(ctx, target, +         internalformat, samples); +   if (sample_count_error != GL_NO_ERROR) { +      _mesa_error(ctx, sample_count_error, "glTexImage%uDMultisample(samples)", dims); +      return;     } -   /* TODO: should ask the driver for the exact limit for this internalformat -    * once IDR's internalformat_query bits land -    */ -     texObj = _mesa_get_current_tex_object(ctx, target);     texImage = _mesa_get_tex_image(ctx, texObj, 0, 0); diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index 120845b4a..bd2f75170 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -1460,6 +1460,12 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )           *params = (GLfloat) obj->Immutable;           break; +      case GL_TEXTURE_IMMUTABLE_LEVELS: +         if (!_mesa_is_gles3(ctx)) +            goto invalid_pname; +         *params = (GLfloat) obj->ImmutableLevels; +         break; +        case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:           if (!_mesa_is_gles(ctx) || !ctx->Extensions.OES_EGL_image_external)              goto invalid_pname; @@ -1637,6 +1643,12 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params )           *params = (GLint) obj->Immutable;           break; +      case GL_TEXTURE_IMMUTABLE_LEVELS: +         if (!_mesa_is_gles3(ctx)) +            goto invalid_pname; +         *params = obj->ImmutableLevels; +         break; +        case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:           if (!_mesa_is_gles(ctx) || !ctx->Extensions.OES_EGL_image_external)              goto invalid_pname; diff --git a/mesalib/src/mesa/main/texstorage.c b/mesalib/src/mesa/main/texstorage.c index 00f19bae5..675fd745b 100644 --- a/mesalib/src/mesa/main/texstorage.c +++ b/mesalib/src/mesa/main/texstorage.c @@ -397,6 +397,7 @@ texstorage(GLuint dims, GLenum target, GLsizei levels, GLenum internalformat,        }        texObj->Immutable = GL_TRUE; +      texObj->ImmutableLevels = levels;     }  } diff --git a/mesalib/src/mesa/state_tracker/st_cb_blit.c b/mesalib/src/mesa/state_tracker/st_cb_blit.c index c463e3b04..50cab4294 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_blit.c +++ b/mesalib/src/mesa/state_tracker/st_cb_blit.c @@ -239,31 +239,22 @@ st_BlitFramebuffer(struct gl_context *ctx,        /* depth and/or stencil blit */        /* get src/dst depth surfaces */ -      struct gl_renderbuffer_attachment *srcDepth = -         &readFB->Attachment[BUFFER_DEPTH]; -      struct gl_renderbuffer_attachment *dstDepth = -         &drawFB->Attachment[BUFFER_DEPTH]; -      struct gl_renderbuffer_attachment *srcStencil = -         &readFB->Attachment[BUFFER_STENCIL]; -      struct gl_renderbuffer_attachment *dstStencil = -         &drawFB->Attachment[BUFFER_STENCIL]; -        struct st_renderbuffer *srcDepthRb = -         st_renderbuffer(srcDepth->Renderbuffer); +         st_renderbuffer(readFB->Attachment[BUFFER_DEPTH].Renderbuffer);        struct st_renderbuffer *dstDepthRb =  -         st_renderbuffer(dstDepth->Renderbuffer); +         st_renderbuffer(drawFB->Attachment[BUFFER_DEPTH].Renderbuffer);        struct pipe_surface *dstDepthSurf =           dstDepthRb ? dstDepthRb->surface : NULL;        struct st_renderbuffer *srcStencilRb = -         st_renderbuffer(srcStencil->Renderbuffer); +         st_renderbuffer(readFB->Attachment[BUFFER_STENCIL].Renderbuffer);        struct st_renderbuffer *dstStencilRb = -         st_renderbuffer(dstStencil->Renderbuffer); +         st_renderbuffer(drawFB->Attachment[BUFFER_STENCIL].Renderbuffer);        struct pipe_surface *dstStencilSurf =           dstStencilRb ? dstStencilRb->surface : NULL; -      if (st_is_depth_stencil_combined(srcDepth, srcStencil) && -          st_is_depth_stencil_combined(dstDepth, dstStencil)) { +      if (_mesa_has_depthstencil_combined(readFB) && +          _mesa_has_depthstencil_combined(drawFB)) {           blit.mask = 0;           if (mask & GL_DEPTH_BUFFER_BIT)              blit.mask |= PIPE_MASK_Z; diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.c b/mesalib/src/mesa/state_tracker/st_cb_fbo.c index 87c5b048c..4452e523b 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.c +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.c @@ -547,30 +547,6 @@ st_validate_attachment(struct gl_context *ctx,     return valid;  } - - -/** - * Check if two renderbuffer attachments name a combined depth/stencil - * renderbuffer. - */ -GLboolean -st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth, -                             const struct gl_renderbuffer_attachment *stencil) -{ -   assert(depth && stencil); - -   if (depth->Type == stencil->Type) { -      if (depth->Type == GL_RENDERBUFFER_EXT && -          depth->Renderbuffer == stencil->Renderbuffer) -         return GL_TRUE; - -      if (depth->Type == GL_TEXTURE && -          depth->Texture == stencil->Texture) -         return GL_TRUE; -   } - -   return GL_FALSE; -}  /** diff --git a/mesalib/src/mesa/state_tracker/st_cb_fbo.h b/mesalib/src/mesa/state_tracker/st_cb_fbo.h index 506fd06d6..461dbe985 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_fbo.h +++ b/mesalib/src/mesa/state_tracker/st_cb_fbo.h @@ -76,9 +76,4 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw);  extern void  st_init_fbo_functions(struct dd_function_table *functions); -extern GLboolean -st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth, -                             const struct gl_renderbuffer_attachment *stencil); - -  #endif /* ST_CB_FBO_H */ diff --git a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c index 6b824b161..bfed98870 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c @@ -25,35 +25,209 @@   *    **************************************************************************/ - +#include "main/image.h" +#include "main/pbo.h"  #include "main/imports.h"  #include "main/readpix.h" +#include "main/enums.h" +#include "main/framebuffer.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "st_cb_fbo.h"  #include "st_atom.h"  #include "st_context.h"  #include "st_cb_bitmap.h"  #include "st_cb_readpixels.h" +#include "state_tracker/st_cb_texture.h" +#include "state_tracker/st_format.h" +#include "state_tracker/st_texture.h"  /** - * The only special thing we need to do for the state tracker's - * glReadPixels is to validate state (to be sure we have up-to-date - * framebuffer surfaces) and flush the bitmap cache prior to reading. + * This uses a blit to copy the read buffer to a texture format which matches + * the format and type combo and then a fast read-back is done using memcpy. + * We can do arbitrary X/Y/Z/W/0/1 swizzling here as long as there is + * a format which matches the swizzling. + * + * If such a format isn't available, we fall back to _mesa_readpixels. + * + * NOTE: Some drivers use a blit to convert between tiled and linear + *       texture layouts during texture uploads/downloads, so the blit + *       we do here should be free in such cases.   */  static void  st_readpixels(struct gl_context *ctx, GLint x, GLint y,                GLsizei width, GLsizei height,                GLenum format, GLenum type,                const struct gl_pixelstore_attrib *pack, -              GLvoid *dest) +              GLvoid *pixels)  {     struct st_context *st = st_context(ctx); +   struct gl_renderbuffer *rb = +         _mesa_get_read_renderbuffer_for_format(ctx, format); +   struct st_renderbuffer *strb = st_renderbuffer(rb); +   struct pipe_context *pipe = st->pipe; +   struct pipe_screen *screen = pipe->screen; +   struct pipe_resource *src; +   struct pipe_resource *dst = NULL; +   struct pipe_resource dst_templ; +   enum pipe_format dst_format, src_format; +   struct pipe_blit_info blit; +   unsigned bind = PIPE_BIND_TRANSFER_READ; +   struct pipe_transfer *tex_xfer; +   ubyte *map = NULL; +   /* Validate state (to be sure we have up-to-date framebuffer surfaces) +    * and flush the bitmap cache prior to reading. */     st_validate_state(st);     st_flush_bitmap_cache(st); -   _mesa_readpixels(ctx, x, y, width, height, format, type, pack, dest); -} +   if (!st->prefer_blit_based_texture_transfer) { +      goto fallback; +   } + +   /* This must be done after state validation. */ +   src = strb->texture; + +   /* XXX Fallback for depth-stencil formats due to an incomplete +    * stencil blit implementation in some drivers. */ +   if (format == GL_DEPTH_STENCIL) { +      goto fallback; +   } + +   /* We are creating a texture of the size of the region being read back. +    * Need to check for NPOT texture support. */ +   if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES) && +       (!util_is_power_of_two(width) || +        !util_is_power_of_two(height))) { +      goto fallback; +   } + +   /* If the base internal format and the texture format don't match, we have +    * to use the slow path. */ +   if (rb->_BaseFormat != +       _mesa_get_format_base_format(rb->Format)) { +      goto fallback; +   } + +   /* See if the texture format already matches the format and type, +    * in which case the memcpy-based fast path will likely be used and +    * we don't have to blit. */ +   if (_mesa_format_matches_format_and_type(rb->Format, format, +                                            type, pack->SwapBytes)) { +      goto fallback; +   } + +   if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_TRUE)) { +      goto fallback; +   } + +   /* Convert the source format to what is expected by ReadPixels +    * and see if it's supported. */ +   src_format = util_format_linear(src->format); +   src_format = util_format_luminance_to_red(src_format); +   src_format = util_format_intensity_to_red(src_format); + +   if (!src_format || +       !screen->is_format_supported(screen, src_format, src->target, +                                    src->nr_samples, +                                    PIPE_BIND_SAMPLER_VIEW)) { +      printf("fallback: src format unsupported %s\n", util_format_short_name(src_format)); +      goto fallback; +   } + +   if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL) +      bind |= PIPE_BIND_DEPTH_STENCIL; +   else +      bind |= PIPE_BIND_RENDER_TARGET; + +   /* Choose the destination format by finding the best match +    * for the format+type combo. */ +   dst_format = st_choose_matching_format(screen, bind, format, type, +                                          pack->SwapBytes); +   if (dst_format == PIPE_FORMAT_NONE) { +      printf("fallback: no matching format for %s, %s\n", +             _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type)); +      goto fallback; +   } + +   /* create the destination texture */ +   memset(&dst_templ, 0, sizeof(dst_templ)); +   dst_templ.target = PIPE_TEXTURE_2D; +   dst_templ.format = dst_format; +   dst_templ.bind = bind; +   dst_templ.usage = PIPE_USAGE_STAGING; + +   st_gl_texture_dims_to_pipe_dims(GL_TEXTURE_2D, width, height, 1, +                                   &dst_templ.width0, &dst_templ.height0, +                                   &dst_templ.depth0, &dst_templ.array_size); + +   dst = screen->resource_create(screen, &dst_templ); +   if (!dst) { +      goto fallback; +   } + +   blit.src.resource = src; +   blit.src.level = strb->rtt_level; +   blit.src.format = src_format; +   blit.dst.resource = dst; +   blit.dst.level = 0; +   blit.dst.format = dst->format; +   blit.src.box.x = x; +   blit.dst.box.x = 0; +   blit.src.box.y = y; +   blit.dst.box.y = 0; +   blit.src.box.z = strb->rtt_face + strb->rtt_slice; +   blit.dst.box.z = 0; +   blit.src.box.width = blit.dst.box.width = width; +   blit.src.box.height = blit.dst.box.height = height; +   blit.src.box.depth = blit.dst.box.depth = 1; +   blit.mask = st_get_blit_mask(rb->_BaseFormat, format); +   blit.filter = PIPE_TEX_FILTER_NEAREST; +   blit.scissor_enable = FALSE; + +   if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { +      blit.src.box.y = rb->Height - blit.src.box.y; +      blit.src.box.height = -blit.src.box.height; +   } + +   /* blit */ +   st->pipe->blit(st->pipe, &blit); + +   /* map resources */ +   pixels = _mesa_map_pbo_dest(ctx, pack, pixels); + +   map = pipe_transfer_map_3d(pipe, dst, 0, PIPE_TRANSFER_READ, +                              0, 0, 0, width, height, 1, &tex_xfer); +   if (!map) { +      _mesa_unmap_pbo_dest(ctx, pack); +      pipe_resource_reference(&dst, NULL); +      goto fallback; +   } + +   /* memcpy data into a user buffer */ +   { +      const uint bytesPerRow = width * util_format_get_blocksize(dst_format); +      GLuint row; + +      for (row = 0; row < height; row++) { +         GLvoid *dest = _mesa_image_address3d(pack, pixels, +                                              width, height, format, +                                              type, 0, row, 0); +         memcpy(dest, map, bytesPerRow); +         map += tex_xfer->stride; +      } +   } + +   pipe_transfer_unmap(pipe, tex_xfer); +   _mesa_unmap_pbo_dest(ctx, pack); +   pipe_resource_reference(&dst, NULL); +   return; + +fallback: +   _mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels); +}  void st_init_readpixels_functions(struct dd_function_table *functions)  { diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index c922a3164..94fbbf7be 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -68,7 +68,7 @@  #define DBG if (0) printf -static enum pipe_texture_target +enum pipe_texture_target  gl_target_to_pipe(GLenum target)  {     switch (target) { @@ -542,8 +542,8 @@ prep_teximage(struct gl_context *ctx, struct gl_texture_image *texImage,   * Return a writemask for the gallium blit. The parameters can be base   * formats or "format" from glDrawPixels/glTexImage/glGetTexImage.   */ -static unsigned -get_blit_mask(GLenum srcFormat, GLenum dstFormat) +unsigned +st_get_blit_mask(GLenum srcFormat, GLenum dstFormat)  {     switch (dstFormat) {     case GL_DEPTH_STENCIL: @@ -608,6 +608,10 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims,     unsigned bind;     GLubyte *map; +   if (!st->prefer_blit_based_texture_transfer) { +      goto fallback; +   } +     if (!dst) {        goto fallback;     } @@ -769,7 +773,7 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims,     blit.src.box.width = blit.dst.box.width = width;     blit.src.box.height = blit.dst.box.height = height;     blit.src.box.depth = blit.dst.box.depth = depth; -   blit.mask = get_blit_mask(format, texImage->_BaseFormat); +   blit.mask = st_get_blit_mask(format, texImage->_BaseFormat);     blit.filter = PIPE_TEX_FILTER_NEAREST;     blit.scissor_enable = FALSE; @@ -860,6 +864,10 @@ st_GetTexImage(struct gl_context * ctx,     ubyte *map = NULL;     boolean done = FALSE; +   if (!st->prefer_blit_based_texture_transfer) { +      goto fallback; +   } +     if (!stImage->pt) {        goto fallback;     } @@ -996,7 +1004,7 @@ st_GetTexImage(struct gl_context * ctx,     blit.src.box.width = blit.dst.box.width = width;     blit.src.box.height = blit.dst.box.height = height;     blit.src.box.depth = blit.dst.box.depth = depth; -   blit.mask = get_blit_mask(texImage->_BaseFormat, format); +   blit.mask = st_get_blit_mask(texImage->_BaseFormat, format);     blit.filter = PIPE_TEX_FILTER_NEAREST;     blit.scissor_enable = FALSE; @@ -1370,7 +1378,7 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,     blit.dst.box.width = width;     blit.dst.box.height = height;     blit.dst.box.depth = 1; -   blit.mask = get_blit_mask(rb->_BaseFormat, texImage->_BaseFormat); +   blit.mask = st_get_blit_mask(rb->_BaseFormat, texImage->_BaseFormat);     blit.filter = PIPE_TEX_FILTER_NEAREST;     /* 1D array textures need special treatment. diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.h b/mesalib/src/mesa/state_tracker/st_cb_texture.h index 27956bcc2..7f70d0b25 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.h +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.h @@ -38,6 +38,12 @@ struct gl_texture_object;  struct pipe_context;  struct st_context; +extern enum pipe_texture_target +gl_target_to_pipe(GLenum target); + +unsigned +st_get_blit_mask(GLenum srcFormat, GLenum dstFormat); +  extern GLboolean  st_finalize_texture(struct gl_context *ctx,  		    struct pipe_context *pipe,  diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c index f9a584ba0..cc87f2bb3 100644 --- a/mesalib/src/mesa/state_tracker/st_context.c +++ b/mesalib/src/mesa/state_tracker/st_context.c @@ -182,6 +182,11 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe,     st->has_stencil_export =        screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT);     st->has_shader_model3 = screen->get_param(screen, PIPE_CAP_SM3); +   st->prefer_blit_based_texture_transfer = screen->get_param(screen, +                              PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER); + +   st->needs_texcoord_semantic = +      screen->get_param(screen, PIPE_CAP_TGSI_TEXCOORD);     /* GL limits and extensions */     st_init_limits(st); diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index b9a98cd05..8786a036f 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -84,6 +84,9 @@ struct st_context     boolean has_stencil_export; /**< can do shader stencil export? */     boolean has_time_elapsed;     boolean has_shader_model3; +   boolean prefer_blit_based_texture_transfer; + +   boolean needs_texcoord_semantic;     /* On old libGL's for linux we need to invalidate the drawables      * on glViewpport calls, this is set via a option. diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c index 5fd44e76d..a15706a03 100644 --- a/mesalib/src/mesa/state_tracker/st_format.c +++ b/mesalib/src/mesa/state_tracker/st_format.c @@ -1769,13 +1769,15 @@ st_ChooseTextureFormat(struct gl_context *ctx, GLenum target,   * Called via ctx->Driver.ChooseTextureFormat().   */  size_t -st_QuerySamplesForFormat(struct gl_context *ctx, GLenum internalFormat, -                         int samples[16]) +st_QuerySamplesForFormat(struct gl_context *ctx, GLenum target, +                         GLenum internalFormat, int samples[16])  {     struct st_context *st = st_context(ctx);     enum pipe_format format;     unsigned i, bind, num_sample_counts = 0; +   (void) target; +     if (_mesa_is_depth_or_stencil_format(internalFormat))        bind = PIPE_BIND_DEPTH_STENCIL;     else diff --git a/mesalib/src/mesa/state_tracker/st_format.h b/mesalib/src/mesa/state_tracker/st_format.h index 3db409b74..0a1c18d92 100644 --- a/mesalib/src/mesa/state_tracker/st_format.h +++ b/mesalib/src/mesa/state_tracker/st_format.h @@ -67,8 +67,8 @@ st_ChooseTextureFormat(struct gl_context * ctx, GLenum target,                         GLenum format, GLenum type);  size_t -st_QuerySamplesForFormat(struct gl_context *ctx, GLenum internalFormat, -                         int samples[16]); +st_QuerySamplesForFormat(struct gl_context *ctx, GLenum target, +                         GLenum internalFormat, int samples[16]);  /* can we use a sampler view to translate these formats     only used to make TFP so far */ diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 0cef092d3..e3718eeda 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -85,6 +85,11 @@ extern "C" {   */  #define MAX_TEMPS         4096 +/** + * Maximum number of arrays + */ +#define MAX_ARRAYS        256 +  /* will be 4 for GLSL 4.00 */  #define MAX_GLSL_TEXTURE_OFFSET 1 @@ -315,9 +320,11 @@ public:     int next_temp; +   unsigned array_sizes[MAX_ARRAYS]; +   unsigned next_array; +     int num_address_regs;     int samplers_used; -   bool indirect_addr_temps;     bool indirect_addr_consts;     int glsl_version; @@ -549,9 +556,6 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,     /* Update indirect addressing status used by TGSI */     if (dst.reladdr) {        switch(dst.file) { -      case PROGRAM_TEMPORARY: -         this->indirect_addr_temps = true; -         break;        case PROGRAM_LOCAL_PARAM:        case PROGRAM_ENV_PARAM:        case PROGRAM_STATE_VAR: @@ -570,9 +574,6 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op,        for (i=0; i<3; i++) {           if(inst->src[i].reladdr) {              switch(inst->src[i].file) { -            case PROGRAM_TEMPORARY: -               this->indirect_addr_temps = true; -               break;              case PROGRAM_LOCAL_PARAM:              case PROGRAM_ENV_PARAM:              case PROGRAM_STATE_VAR: @@ -1005,17 +1006,26 @@ glsl_to_tgsi_visitor::get_temp(const glsl_type *type)     st_src_reg src;     src.type = native_integers ? type->base_type : GLSL_TYPE_FLOAT; -   src.file = PROGRAM_TEMPORARY; -   src.index = next_temp;     src.reladdr = NULL; -   next_temp += type_size(type); +   src.negate = 0; + +   if (type->is_array() || type->is_matrix()) { +      src.file = PROGRAM_ARRAY; +      src.index = next_array << 16 | 0x8000; +      array_sizes[next_array] = type_size(type); +      ++next_array; + +   } else { +      src.file = PROGRAM_TEMPORARY; +      src.index = next_temp; +      next_temp += type_size(type); +   }     if (type->is_array() || type->is_record()) {        src.swizzle = SWIZZLE_NOOP;     } else {        src.swizzle = swizzle_for_size(type->vector_elements);     } -   src.negate = 0;     return src;  } @@ -1078,13 +1088,11 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)            */           assert((int) ir->num_state_slots == type_size(ir->type)); -         storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY, -        					 this->next_temp); -         this->variables.push_tail(storage); -         this->next_temp += type_size(ir->type); +         dst = st_dst_reg(get_temp(ir->type)); + +         storage = new(mem_ctx) variable_storage(ir, dst.file, dst.index); -         dst = st_dst_reg(st_src_reg(PROGRAM_TEMPORARY, storage->index, -               native_integers ? ir->type->base_type : GLSL_TYPE_FLOAT)); +         this->variables.push_tail(storage);        } @@ -2052,11 +2060,11 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir)           break;        case ir_var_auto:        case ir_var_temporary: -         entry = new(mem_ctx) variable_storage(var, PROGRAM_TEMPORARY, -        				       this->next_temp); +         st_src_reg src = get_temp(var->type); + +         entry = new(mem_ctx) variable_storage(var, src.file, src.index);           this->variables.push_tail(entry); -         next_temp += type_size(var->type);           break;        } @@ -2574,11 +2582,10 @@ glsl_to_tgsi_visitor::get_function_signature(ir_function_signature *sig)        storage = find_variable_storage(param);        assert(!storage); -      storage = new(mem_ctx) variable_storage(param, PROGRAM_TEMPORARY, -        				      this->next_temp); -      this->variables.push_tail(storage); +      st_src_reg src = get_temp(param->type); -      this->next_temp += type_size(param->type); +      storage = new(mem_ctx) variable_storage(param, src.file, src.index); +      this->variables.push_tail(storage);     }     if (!sig->return_type->is_void()) { @@ -2978,12 +2985,12 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor()  {     result.file = PROGRAM_UNDEFINED;     next_temp = 1; +   next_array = 0;     next_signature_id = 1;     num_immediates = 0;     current_function = NULL;     num_address_regs = 0;     samplers_used = 0; -   indirect_addr_temps = false;     indirect_addr_consts = false;     glsl_version = 0;     native_integers = false; @@ -3183,7 +3190,8 @@ glsl_to_tgsi_visitor::simplify_cmp(void)           assert(inst->dst.index < MAX_TEMPS);           prevWriteMask = tempWrites[inst->dst.index];           tempWrites[inst->dst.index] |= inst->dst.writemask; -      } +      } else +         break;        /* For a CMP to be considered a conditional write, the destination         * register and source register two must be the same. */ @@ -3821,7 +3829,6 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp,     v->next_temp = original->next_temp;     v->num_address_regs = original->num_address_regs;     v->samplers_used = prog->SamplersUsed = original->samplers_used; -   v->indirect_addr_temps = original->indirect_addr_temps;     v->indirect_addr_consts = original->indirect_addr_consts;     memcpy(&v->immediates, &original->immediates, sizeof(v->immediates));     v->num_immediates = original->num_immediates; @@ -3952,7 +3959,6 @@ get_bitmap_visitor(struct st_fragment_program *fp,     v->next_temp = original->next_temp;     v->num_address_regs = original->num_address_regs;     v->samplers_used = prog->SamplersUsed = original->samplers_used; -   v->indirect_addr_temps = original->indirect_addr_temps;     v->indirect_addr_consts = original->indirect_addr_consts;     memcpy(&v->immediates, &original->immediates, sizeof(v->immediates));     v->num_immediates = original->num_immediates; @@ -4014,6 +4020,7 @@ struct st_translate {     struct ureg_program *ureg;     struct ureg_dst temps[MAX_TEMPS]; +   struct ureg_dst arrays[MAX_ARRAYS];     struct ureg_src *constants;     struct ureg_src *immediates;     struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS]; @@ -4022,6 +4029,8 @@ struct st_translate {     struct ureg_src samplers[PIPE_MAX_SAMPLERS];     struct ureg_src systemValues[SYSTEM_VALUE_MAX]; +   unsigned array_sizes[MAX_ARRAYS]; +     const GLuint *inputMapping;     const GLuint *outputMapping; @@ -4132,16 +4141,34 @@ dst_register(struct st_translate *t,               gl_register_file file,               GLuint index)  { +   unsigned array; +     switch(file) {     case PROGRAM_UNDEFINED:        return ureg_dst_undef();     case PROGRAM_TEMPORARY: +      assert(index >= 0); +      assert(index < (int) Elements(t->temps)); +         if (ureg_dst_is_undef(t->temps[index]))           t->temps[index] = ureg_DECL_local_temporary(t->ureg);        return t->temps[index]; +   case PROGRAM_ARRAY: +      array = index >> 16; + +      assert(array >= 0); +      assert(array < (int) Elements(t->arrays)); + +      if (ureg_dst_is_undef(t->arrays[array])) +         t->arrays[array] = ureg_DECL_array_temporary( +            t->ureg, t->array_sizes[array], TRUE); + +      return ureg_dst_array_offset(t->arrays[array], +                                   (int)(index & 0xFFFF) - 0x8000); +     case PROGRAM_OUTPUT:        if (t->procType == TGSI_PROCESSOR_VERTEX)           assert(index < VARYING_SLOT_MAX); @@ -4176,11 +4203,8 @@ src_register(struct st_translate *t,        return ureg_src_undef();     case PROGRAM_TEMPORARY: -      assert(index >= 0); -      assert(index < (int) Elements(t->temps)); -      if (ureg_dst_is_undef(t->temps[index])) -         t->temps[index] = ureg_DECL_local_temporary(t->ureg); -      return ureg_src(t->temps[index]); +   case PROGRAM_ARRAY: +      return ureg_src(dst_register(t, file, index));     case PROGRAM_ENV_PARAM:     case PROGRAM_LOCAL_PARAM: @@ -4262,8 +4286,10 @@ translate_dst(struct st_translate *t,        }     } -   if (dst_reg->reladdr != NULL) +   if (dst_reg->reladdr != NULL) { +      assert(dst_reg->file != PROGRAM_TEMPORARY);        dst = ureg_dst_indirect(dst, ureg_src(t->address[0])); +   }     return dst;  } @@ -4286,26 +4312,8 @@ translate_src(struct st_translate *t, const st_src_reg *src_reg)        src = ureg_negate(src);     if (src_reg->reladdr != NULL) { -      /* Normally ureg_src_indirect() would be used here, but a stupid compiler  -       * bug in g++ makes ureg_src_indirect (an inline C function) erroneously  -       * set the bit for src.Negate.  So we have to do the operation manually -       * here to work around the compiler's problems. */ -      /*src = ureg_src_indirect(src, ureg_src(t->address[0]));*/ -      struct ureg_src addr = ureg_src(t->address[0]); -      src.Indirect = 1; -      src.IndirectFile = addr.File; -      src.IndirectIndex = addr.Index; -      src.IndirectSwizzle = addr.SwizzleX; -       -      if (src_reg->file != PROGRAM_INPUT && -          src_reg->file != PROGRAM_OUTPUT) { -         /* If src_reg->index was negative, it was set to zero in -          * src_register().  Reassign it now.  But don't do this -          * for input/output regs since they get remapped while -          * const buffers don't. -          */ -         src.Index = src_reg->index; -      } +      assert(src_reg->file != PROGRAM_TEMPORARY); +      src = ureg_src_indirect(src, ureg_src(t->address[0]));     }     return src; @@ -4820,16 +4828,9 @@ st_translate_program(        }     } -   if (program->indirect_addr_temps) { -      /* If temps are accessed with indirect addressing, declare temporaries -       * in sequential order.  Else, we declare them on demand elsewhere. -       * (Note: the number of temporaries is equal to program->next_temp) -       */ -      for (i = 0; i < (unsigned)program->next_temp; i++) { -         /* XXX use TGSI_FILE_TEMPORARY_ARRAY when it's supported by ureg */ -         t->temps[i] = ureg_DECL_local_temporary(t->ureg); -      } -   } +   /* Copy over array sizes +    */ +   memcpy(t->array_sizes, program->array_sizes, sizeof(unsigned) * program->next_array);     /* Emit constants and uniforms.  TGSI uses a single index space for these,       * so we put all the translated regs in t->constants. @@ -5064,16 +5065,9 @@ get_mesa_program(struct gl_context *ctx,     v->copy_propagate();     while (v->eliminate_dead_code_advanced()); -   /* FIXME: These passes to optimize temporary registers don't work when there -    * is indirect addressing of the temporary register space.  We need proper  -    * array support so that we don't have to give up these passes in every  -    * shader that uses arrays. -    */ -   if (!v->indirect_addr_temps) { -      v->eliminate_dead_code(); -      v->merge_registers(); -      v->renumber_registers(); -   } +   v->eliminate_dead_code(); +   v->merge_registers(); +   v->renumber_registers();     /* Write the END instruction. */     v->emit(NULL, TGSI_OPCODE_END); diff --git a/mesalib/src/mesa/state_tracker/st_program.c b/mesalib/src/mesa/state_tracker/st_program.c index 6af8df316..7a38da84f 100644 --- a/mesalib/src/mesa/state_tracker/st_program.c +++ b/mesalib/src/mesa/state_tracker/st_program.c @@ -177,6 +177,7 @@ void  st_prepare_vertex_program(struct gl_context *ctx,                              struct st_vertex_program *stvp)  { +   struct st_context *st = st_context(ctx);     GLuint attr;     stvp->num_inputs = 0; @@ -267,7 +268,8 @@ st_prepare_vertex_program(struct gl_context *ctx,           case VARYING_SLOT_TEX5:           case VARYING_SLOT_TEX6:           case VARYING_SLOT_TEX7: -            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; +            stvp->output_semantic_name[slot] = st->needs_texcoord_semantic ? +               TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC;              stvp->output_semantic_index[slot] = attr - VARYING_SLOT_TEX0;              break; @@ -275,10 +277,8 @@ st_prepare_vertex_program(struct gl_context *ctx,           default:              assert(attr < VARYING_SLOT_MAX);              stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -            stvp->output_semantic_index[slot] = (VARYING_SLOT_VAR0 -  -                                                VARYING_SLOT_TEX0 + -                                                attr -  -                                                VARYING_SLOT_VAR0); +            stvp->output_semantic_index[slot] = st->needs_texcoord_semantic ? +               (attr - VARYING_SLOT_VAR0) : (attr - VARYING_SLOT_TEX0);              break;           }        } @@ -585,11 +585,18 @@ st_translate_fragment_program(struct st_context *st,               * fragment shader plus fixed-function hardware (such as               * BFC).               * -             * There is no requirement that semantic indexes start at -             * zero or be restricted to a particular range -- nobody -             * should be building tables based on semantic index. +             * However, some drivers may need us to identify the PNTC and TEXi +             * varyings if, for example, their capability to replace them with +             * sprite coordinates is limited.               */           case VARYING_SLOT_PNTC: +            if (st->needs_texcoord_semantic) { +               input_semantic_name[slot] = TGSI_SEMANTIC_PCOORD; +               input_semantic_index[slot] = 0; +               interpMode[slot] = TGSI_INTERPOLATE_LINEAR; +               break; +            } +            /* fall through */           case VARYING_SLOT_TEX0:           case VARYING_SLOT_TEX1:           case VARYING_SLOT_TEX2: @@ -598,13 +605,29 @@ st_translate_fragment_program(struct st_context *st,           case VARYING_SLOT_TEX5:           case VARYING_SLOT_TEX6:           case VARYING_SLOT_TEX7: +            if (st->needs_texcoord_semantic) { +               input_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD; +               input_semantic_index[slot] = attr - VARYING_SLOT_TEX0; +               interpMode[slot] = +                  st_translate_interp(stfp->Base.InterpQualifier[attr], FALSE); +               break; +            } +            /* fall through */           case VARYING_SLOT_VAR0:           default: -            /* Actually, let's try and zero-base this just for -             * readability of the generated TGSI. +            /* Semantic indices should be zero-based because drivers may choose +             * to assign a fixed slot determined by that index. +             * This is useful because ARB_separate_shader_objects uses location +             * qualifiers for linkage, and if the semantic index corresponds to +             * these locations, linkage passes in the driver become unecessary. +             * +             * If needs_texcoord_semantic is true, no semantic indices will be +             * consumed for the TEXi varyings, and we can base the locations of +             * the user varyings on VAR0.  Otherwise, we use TEX0 as base index.               */              assert(attr >= VARYING_SLOT_TEX0); -            input_semantic_index[slot] = (attr - VARYING_SLOT_TEX0); +            input_semantic_index[slot] = st->needs_texcoord_semantic ? +               (attr - VARYING_SLOT_VAR0) : (attr - VARYING_SLOT_TEX0);              input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;              if (attr == VARYING_SLOT_PNTC)                 interpMode[slot] = TGSI_INTERPOLATE_LINEAR; | 
