示例#1
0
void GLAPIENTRY
_mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                              GLenum pname, GLint *params )
{
   struct gl_texture_object *texObj;
   const struct gl_texture_image *img = NULL;
   GLint maxLevels;
   gl_format texFormat;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   /* this will catch bad target values */
   maxLevels = _mesa_max_texture_levels(ctx, target);
   if (maxLevels == 0) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glGetTexLevelParameter[if]v(target=0x%x)", target);
      return;
   }

   if (level < 0 || level >= maxLevels) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
      return;
   }

   texObj = _mesa_select_tex_object(ctx, target);

   img = _mesa_select_tex_image(ctx, texObj, target, level);
   if (!img || img->TexFormat == MESA_FORMAT_NONE) {
      /* undefined texture image */
      if (pname == GL_TEXTURE_COMPONENTS)
         *params = 1;
      else
         *params = 0;
      return;
   }

   texFormat = img->TexFormat;

   switch (pname) {
      case GL_TEXTURE_WIDTH:
         *params = img->Width;
         break;
      case GL_TEXTURE_HEIGHT:
         *params = img->Height;
         break;
      case GL_TEXTURE_DEPTH:
         *params = img->Depth;
         break;
      case GL_TEXTURE_INTERNAL_FORMAT:
         *params = img->InternalFormat;
         break;
      case GL_TEXTURE_BORDER:
         *params = img->Border;
         break;
      case GL_TEXTURE_RED_SIZE:
      case GL_TEXTURE_GREEN_SIZE:
      case GL_TEXTURE_BLUE_SIZE:
      case GL_TEXTURE_ALPHA_SIZE:
         if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
            *params = _mesa_get_format_bits(texFormat, pname);
         else
            *params = 0;
         break;
      case GL_TEXTURE_INTENSITY_SIZE:
      case GL_TEXTURE_LUMINANCE_SIZE:
         if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) {
            *params = _mesa_get_format_bits(texFormat, pname);
            if (*params == 0) {
               /* intensity or luminance is probably stored as RGB[A] */
               *params = MIN2(_mesa_get_format_bits(texFormat,
                                                    GL_TEXTURE_RED_SIZE),
                              _mesa_get_format_bits(texFormat,
                                                    GL_TEXTURE_GREEN_SIZE));
            }
         }
         else {
            *params = 0;
         }
         break;

      /* GL_ARB_texture_float */
      case GL_TEXTURE_RED_TYPE_ARB:
      case GL_TEXTURE_GREEN_TYPE_ARB:
      case GL_TEXTURE_BLUE_TYPE_ARB:
      case GL_TEXTURE_ALPHA_TYPE_ARB:
      case GL_TEXTURE_LUMINANCE_TYPE_ARB:
      case GL_TEXTURE_INTENSITY_TYPE_ARB:
      case GL_TEXTURE_DEPTH_TYPE_ARB:
         if (!ctx->Extensions.ARB_texture_float)
            goto invalid_pname;
	 if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
	    *params = _mesa_get_format_datatype(texFormat);
	 else
	    *params = GL_NONE;
         break;

      default:
         goto invalid_pname;
   }

   /* no error if we get here */
   return;

invalid_pname:
   _mesa_error(ctx, GL_INVALID_ENUM,
               "glGetTexLevelParameter[if]v(pname=%s)",
               _mesa_lookup_enum_by_nr(pname));
}
示例#2
0
文件: gen6_cc.c 项目: gqmelo/mesa
static void
gen6_upload_blend_state(struct brw_context *brw)
{
   bool is_buffer_zero_integer_format = false;
   struct gl_context *ctx = &brw->ctx;
   struct gen6_blend_state *blend;
   int b;
   int nr_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers;
   int size;

   /* We need at least one BLEND_STATE written, because we might do
    * thread dispatch even if _NumColorDrawBuffers is 0 (for example
    * for computed depth or alpha test), which will do an FB write
    * with render target 0, which will reference BLEND_STATE[0] for
    * alpha test enable.
    */
   if (nr_draw_buffers == 0)
      nr_draw_buffers = 1;

   size = sizeof(*blend) * nr_draw_buffers;
   blend = brw_state_batch(brw, AUB_TRACE_BLEND_STATE,
			   size, 64, &brw->cc.blend_state_offset);

   memset(blend, 0, size);

   for (b = 0; b < nr_draw_buffers; b++) {
      /* _NEW_BUFFERS */
      struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[b];
      GLenum rb_type;
      bool integer;

      if (rb)
	 rb_type = _mesa_get_format_datatype(rb->Format);
      else
	 rb_type = GL_UNSIGNED_NORMALIZED;

      /* Used for implementing the following bit of GL_EXT_texture_integer:
       *     "Per-fragment operations that require floating-point color
       *      components, including multisample alpha operations, alpha test,
       *      blending, and dithering, have no effect when the corresponding
       *      colors are written to an integer color buffer."
      */
      integer = (rb_type == GL_INT || rb_type == GL_UNSIGNED_INT);

      if(b == 0 && integer)
         is_buffer_zero_integer_format = true;

      /* _NEW_COLOR */
      if (ctx->Color.ColorLogicOpEnabled) {
	 /* Floating point RTs should have no effect from LogicOp,
	  * except for disabling of blending, but other types should.
	  *
	  * However, from the Sandy Bridge PRM, Vol 2 Par 1, Section 8.1.11,
	  * "Logic Ops",
	  *
	  *     "Logic Ops are only supported on *_UNORM surfaces (excluding
	  *      _SRGB variants), otherwise Logic Ops must be DISABLED."
	  */
         WARN_ONCE(ctx->Color.LogicOp != GL_COPY &&
                   rb_type != GL_UNSIGNED_NORMALIZED &&
                   rb_type != GL_FLOAT, "Ignoring %s logic op on %s "
                   "renderbuffer\n",
                   _mesa_enum_to_string(ctx->Color.LogicOp),
                   _mesa_enum_to_string(rb_type));
	 if (rb_type == GL_UNSIGNED_NORMALIZED) {
	    blend[b].blend1.logic_op_enable = 1;
	    blend[b].blend1.logic_op_func =
	       intel_translate_logic_op(ctx->Color.LogicOp);
	 }
      } else if (ctx->Color.BlendEnabled & (1 << b) && !integer) {
	 GLenum eqRGB = ctx->Color.Blend[b].EquationRGB;
	 GLenum eqA = ctx->Color.Blend[b].EquationA;
	 GLenum srcRGB = ctx->Color.Blend[b].SrcRGB;
	 GLenum dstRGB = ctx->Color.Blend[b].DstRGB;
	 GLenum srcA = ctx->Color.Blend[b].SrcA;
	 GLenum dstA = ctx->Color.Blend[b].DstA;

	 if (eqRGB == GL_MIN || eqRGB == GL_MAX) {
	    srcRGB = dstRGB = GL_ONE;
	 }

	 if (eqA == GL_MIN || eqA == GL_MAX) {
	    srcA = dstA = GL_ONE;
	 }

         /* Due to hardware limitations, the destination may have information
          * in an alpha channel even when the format specifies no alpha
          * channel. In order to avoid getting any incorrect blending due to
          * that alpha channel, coerce the blend factors to values that will
          * not read the alpha channel, but will instead use the correct
          * implicit value for alpha.
          */
         if (rb && !_mesa_base_format_has_channel(rb->_BaseFormat, GL_TEXTURE_ALPHA_TYPE))
         {
            srcRGB = brw_fix_xRGB_alpha(srcRGB);
            srcA = brw_fix_xRGB_alpha(srcA);
            dstRGB = brw_fix_xRGB_alpha(dstRGB);
            dstA = brw_fix_xRGB_alpha(dstA);
         }

	 blend[b].blend0.dest_blend_factor = brw_translate_blend_factor(dstRGB);
	 blend[b].blend0.source_blend_factor = brw_translate_blend_factor(srcRGB);
	 blend[b].blend0.blend_func = brw_translate_blend_equation(eqRGB);

	 blend[b].blend0.ia_dest_blend_factor = brw_translate_blend_factor(dstA);
	 blend[b].blend0.ia_source_blend_factor = brw_translate_blend_factor(srcA);
	 blend[b].blend0.ia_blend_func = brw_translate_blend_equation(eqA);

	 blend[b].blend0.blend_enable = 1;
	 blend[b].blend0.ia_blend_enable = (srcA != srcRGB ||
					 dstA != dstRGB ||
					 eqA != eqRGB);
      }

      /* See section 8.1.6 "Pre-Blend Color Clamping" of the
       * SandyBridge PRM Volume 2 Part 1 for HW requirements.
       *
       * We do our ARB_color_buffer_float CLAMP_FRAGMENT_COLOR
       * clamping in the fragment shader.  For its clamping of
       * blending, the spec says:
       *
       *     "RESOLVED: For fixed-point color buffers, the inputs and
       *      the result of the blending equation are clamped.  For
       *      floating-point color buffers, no clamping occurs."
       *
       * So, generally, we want clamping to the render target's range.
       * And, good news, the hardware tables for both pre- and
       * post-blend color clamping are either ignored, or any are
       * allowed, or clamping is required but RT range clamping is a
       * valid option.
       */
      blend[b].blend1.pre_blend_clamp_enable = 1;
      blend[b].blend1.post_blend_clamp_enable = 1;
      blend[b].blend1.clamp_range = BRW_RENDERTARGET_CLAMPRANGE_FORMAT;

      /* _NEW_COLOR */
      if (ctx->Color.AlphaEnabled && !integer) {
	 blend[b].blend1.alpha_test_enable = 1;
	 blend[b].blend1.alpha_test_func =
	    intel_translate_compare_func(ctx->Color.AlphaFunc);

      }

      /* _NEW_COLOR */
      if (ctx->Color.DitherFlag && !integer) {
	 blend[b].blend1.dither_enable = 1;
	 blend[b].blend1.y_dither_offset = 0;
	 blend[b].blend1.x_dither_offset = 0;
      }

      blend[b].blend1.write_disable_r = !ctx->Color.ColorMask[b][0];
      blend[b].blend1.write_disable_g = !ctx->Color.ColorMask[b][1];
      blend[b].blend1.write_disable_b = !ctx->Color.ColorMask[b][2];
      blend[b].blend1.write_disable_a = !ctx->Color.ColorMask[b][3];

      /* OpenGL specification 3.3 (page 196), section 4.1.3 says:
       * "If drawbuffer zero is not NONE and the buffer it references has an
       * integer format, the SAMPLE_ALPHA_TO_COVERAGE and SAMPLE_ALPHA_TO_ONE
       * operations are skipped."
       */
      if(!is_buffer_zero_integer_format) {
         /* _NEW_MULTISAMPLE */
         blend[b].blend1.alpha_to_coverage =
            _mesa_is_multisample_enabled(ctx) && ctx->Multisample.SampleAlphaToCoverage;

	/* From SandyBridge PRM, volume 2 Part 1, section 8.2.3, BLEND_STATE:
	 * DWord 1, Bit 30 (AlphaToOne Enable):
	 * "If Dual Source Blending is enabled, this bit must be disabled"
	 */
         WARN_ONCE(ctx->Color.Blend[b]._UsesDualSrc &&
                   _mesa_is_multisample_enabled(ctx) &&
                   ctx->Multisample.SampleAlphaToOne,
                   "HW workaround: disabling alpha to one with dual src "
                   "blending\n");
	 if (ctx->Color.Blend[b]._UsesDualSrc)
            blend[b].blend1.alpha_to_one = false;
	 else
	    blend[b].blend1.alpha_to_one =
	       _mesa_is_multisample_enabled(ctx) && ctx->Multisample.SampleAlphaToOne;

         blend[b].blend1.alpha_to_coverage_dither = (brw->gen >= 7);
      }
      else {
         blend[b].blend1.alpha_to_coverage = false;
         blend[b].blend1.alpha_to_one = false;
      }
   }

   /* Point the GPU at the new indirect state. */
   if (brw->gen == 6) {
      BEGIN_BATCH(4);
      OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (4 - 2));
      OUT_BATCH(brw->cc.blend_state_offset | 1);
      OUT_BATCH(0);
      OUT_BATCH(0);
      ADVANCE_BATCH();
   } else {
      BEGIN_BATCH(2);
      OUT_BATCH(_3DSTATE_BLEND_STATE_POINTERS << 16 | (2 - 2));
      OUT_BATCH(brw->cc.blend_state_offset | 1);
      ADVANCE_BATCH();
   }
}
示例#3
0
void GLAPIENTRY
_mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname,
                          GLsizei bufSize, GLint *params)
{
   GLint buffer[16];
   GET_CURRENT_CONTEXT(ctx);

   ASSERT_OUTSIDE_BEGIN_END(ctx);

   /* ARB_internalformat_query is also mandatory for ARB_internalformat_query2 */
   if (!(_mesa_has_ARB_internalformat_query(ctx) ||
         _mesa_is_gles3(ctx))) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetInternalformativ");
      return;
   }

   assert(ctx->Driver.QueryInternalFormat != NULL);

   if (!_legal_parameters(ctx, target, internalformat, pname, bufSize, params))
      return;

   /* initialize the contents of the temporary buffer */
   memcpy(buffer, params, MIN2(bufSize, 16) * sizeof(GLint));

   /* Use the 'unsupported' response defined by the spec for every pname
    * as the default answer.
    */
   _set_default_response(pname, buffer);

   if (!_is_target_supported(ctx, target) ||
       !_is_internalformat_supported(ctx, target, internalformat) ||
       !_is_resource_supported(ctx, target, internalformat, pname))
      goto end;

   switch (pname) {
   case GL_SAMPLES:
      /* fall-through */
   case GL_NUM_SAMPLE_COUNTS:
      /* The ARB_internalformat_query2 sets the response as 'unsupported' for
       * SAMPLES and NUM_SAMPLE_COUNTS:
       *
       *     "If <internalformat> is not color-renderable, depth-renderable, or
       *     stencil-renderable (as defined in section 4.4.4), or if <target>
       *     does not support multiple samples (ie other than
       *     TEXTURE_2D_MULTISAMPLE,  TEXTURE_2D_MULTISAMPLE_ARRAY,
       *     or RENDERBUFFER)."
       */
      if ((target != GL_RENDERBUFFER &&
           target != GL_TEXTURE_2D_MULTISAMPLE &&
           target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY) ||
          !_is_renderable(ctx, internalformat))
         goto end;

      /* The GL ES 3.0 specification, section 6.1.15 page 236 says:
       *
       *     "Since multisampling is not supported for signed and unsigned
       *     integer internal formats, the value of NUM_SAMPLE_COUNTS will be
       *     zero for such formats.
       *
       * Since OpenGL ES 3.1 adds support for multisampled integer formats, we
       * have to check the version for 30 exactly.
       */
      if (pname == GL_NUM_SAMPLE_COUNTS && ctx->API == API_OPENGLES2 &&
          ctx->Version == 30 && _mesa_is_enum_format_integer(internalformat)) {
         goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_INTERNALFORMAT_SUPPORTED:
      /* Having a supported <internalformat> is implemented as a prerequisite
       * for all the <pnames>. Thus,  if we reach this point, the internalformat is
       * supported.
       */
      buffer[0] = GL_TRUE;
      break;

   case GL_INTERNALFORMAT_PREFERRED:
      /* The ARB_internalformat_query2 spec says:
       *
       *     "- INTERNALFORMAT_PREFERRED: The implementation-preferred internal
       *     format for representing resources of the specified <internalformat> is
       *     returned in <params>.
       *
       * Therefore, we let the driver answer. Note that if we reach this
       * point, it means that the internalformat is supported, so the driver
       * is called just to try to get a preferred format. If not supported,
       * GL_NONE was already returned and the driver is not called.
       */
      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_INTERNALFORMAT_RED_SIZE:
   case GL_INTERNALFORMAT_GREEN_SIZE:
   case GL_INTERNALFORMAT_BLUE_SIZE:
   case GL_INTERNALFORMAT_ALPHA_SIZE:
   case GL_INTERNALFORMAT_DEPTH_SIZE:
   case GL_INTERNALFORMAT_STENCIL_SIZE:
   case GL_INTERNALFORMAT_SHARED_SIZE:
   case GL_INTERNALFORMAT_RED_TYPE:
   case GL_INTERNALFORMAT_GREEN_TYPE:
   case GL_INTERNALFORMAT_BLUE_TYPE:
   case GL_INTERNALFORMAT_ALPHA_TYPE:
   case GL_INTERNALFORMAT_DEPTH_TYPE:
   case GL_INTERNALFORMAT_STENCIL_TYPE: {
      GLint baseformat;
      mesa_format texformat;

      if (target != GL_RENDERBUFFER) {
         if (!_mesa_legal_get_tex_level_parameter_target(ctx, target, true))
            goto end;

         baseformat = _mesa_base_tex_format(ctx, internalformat);
      } else {
         baseformat = _mesa_base_fbo_format(ctx, internalformat);
      }

      /* Let the driver choose the texture format.
       *
       * Disclaimer: I am considering that drivers use for renderbuffers the
       * same format-choice logic as for textures.
       */
      texformat = ctx->Driver.ChooseTextureFormat(ctx, target, internalformat,
                                                  GL_NONE /*format */, GL_NONE /* type */);

      if (texformat == MESA_FORMAT_NONE || baseformat <= 0)
         goto end;

      /* Implementation based on what Mesa does for glGetTexLevelParameteriv
       * and glGetRenderbufferParameteriv functions.
       */
      if (pname == GL_INTERNALFORMAT_SHARED_SIZE) {
         if (_mesa_has_EXT_texture_shared_exponent(ctx) &&
             target != GL_TEXTURE_BUFFER &&
             target != GL_RENDERBUFFER &&
             texformat == MESA_FORMAT_R9G9B9E5_FLOAT) {
            buffer[0] = 5;
         }
         goto end;
      }

      if (!_mesa_base_format_has_channel(baseformat, pname))
         goto end;

      switch (pname) {
      case GL_INTERNALFORMAT_DEPTH_SIZE:
         if (ctx->API != API_OPENGL_CORE &&
             !_mesa_has_ARB_depth_texture(ctx) &&
             target != GL_RENDERBUFFER &&
             target != GL_TEXTURE_BUFFER)
            goto end;
         /* fallthrough */
      case GL_INTERNALFORMAT_RED_SIZE:
      case GL_INTERNALFORMAT_GREEN_SIZE:
      case GL_INTERNALFORMAT_BLUE_SIZE:
      case GL_INTERNALFORMAT_ALPHA_SIZE:
      case GL_INTERNALFORMAT_STENCIL_SIZE:
         buffer[0] = _mesa_get_format_bits(texformat, pname);
         break;

      case GL_INTERNALFORMAT_DEPTH_TYPE:
         if (!_mesa_has_ARB_texture_float(ctx))
            goto end;
         /* fallthrough */
      case GL_INTERNALFORMAT_RED_TYPE:
      case GL_INTERNALFORMAT_GREEN_TYPE:
      case GL_INTERNALFORMAT_BLUE_TYPE:
      case GL_INTERNALFORMAT_ALPHA_TYPE:
      case GL_INTERNALFORMAT_STENCIL_TYPE:
         buffer[0]  = _mesa_get_format_datatype(texformat);
         break;

      default:
         break;

      }
      break;
   }

      /* For WIDTH/HEIGHT/DEPTH/LAYERS there is no reason to think that the
       * returned values should be different to the values returned by
       * GetInteger with MAX_TEXTURE_SIZE, MAX_3D_TEXTURE_SIZE, etc.*/
   case GL_MAX_WIDTH:
   case GL_MAX_HEIGHT:
   case GL_MAX_DEPTH: {
      GLenum get_pname;
      GLint dimensions;
      GLint min_dimensions;

      /* From query2:MAX_HEIGHT spec (as example):
       *
       * "If the resource does not have at least two dimensions, or if the
       * resource is unsupported, zero is returned."
       */
      dimensions = _get_target_dimensions(target);
      min_dimensions = _get_min_dimensions(pname);
      if (dimensions < min_dimensions)
         goto end;

      get_pname = _equivalent_size_pname(target, pname);
      if (get_pname == 0)
         goto end;

      _mesa_GetIntegerv(get_pname, buffer);
      break;
   }

   case GL_MAX_LAYERS:
      if (!_mesa_has_EXT_texture_array(ctx))
         goto end;

      if (!_mesa_is_array_texture(target))
         goto end;

      _mesa_GetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, buffer);
      break;

   case GL_MAX_COMBINED_DIMENSIONS:{
      GLint64 combined_value = 1;
      GLenum max_dimensions_pnames[] = {
         GL_MAX_WIDTH,
         GL_MAX_HEIGHT,
         GL_MAX_DEPTH,
         GL_SAMPLES
      };
      unsigned i;
      GLint current_value;

      /* Combining the dimensions. Note that for array targets, this would
       * automatically include the value of MAX_LAYERS, as that value is
       * returned as MAX_HEIGHT or MAX_DEPTH */
      for (i = 0; i < 4; i++) {
         if (max_dimensions_pnames[i] == GL_SAMPLES &&
             !_is_multisample_target(target))
            continue;

         _mesa_GetInternalformativ(target, internalformat,
                                   max_dimensions_pnames[i],
                                   1, &current_value);

         if (current_value != 0)
            combined_value *= current_value;
      }

      if (_mesa_is_cube_map_texture(target))
         combined_value *= 6;

      /* We pack the 64-bit value on two 32-bit values. Calling the 32-bit
       * query, this would work as far as the value can be hold on a 32-bit
       * signed integer. For the 64-bit query, the wrapper around the 32-bit
       * query will unpack the value */
      memcpy(buffer, &combined_value, sizeof(GLint64));
      break;
   }

   case GL_COLOR_COMPONENTS:
      /* The ARB_internalformat_query2 spec says:
       *
       *     "- COLOR_COMPONENTS: If the internal format contains any color
       *     components (R, G, B, or A), TRUE is returned in <params>.
       *     If the internal format is unsupported or contains no color
       *     components, FALSE is returned."
       */
      if (_mesa_is_color_format(internalformat))
         buffer[0] = GL_TRUE;
      break;

   case GL_DEPTH_COMPONENTS:
      /* The ARB_internalformat_query2 spec says:
       *
       *     "- DEPTH_COMPONENTS: If the internal format contains a depth
       *     component (D), TRUE is returned in <params>. If the internal format
       *     is unsupported or contains no depth component, FALSE is returned."
       */
      if (_mesa_is_depth_format(internalformat) ||
          _mesa_is_depthstencil_format(internalformat))
         buffer[0] = GL_TRUE;
      break;

   case GL_STENCIL_COMPONENTS:
      /* The ARB_internalformat_query2 spec says:
       *
       *     "- STENCIL_COMPONENTS: If the internal format contains a stencil
       *     component (S), TRUE is returned in <params>. If the internal format
       *     is unsupported or contains no stencil component, FALSE is returned.
       */
      if (_mesa_is_stencil_format(internalformat) ||
          _mesa_is_depthstencil_format(internalformat))
         buffer[0] = GL_TRUE;
      break;

   case GL_COLOR_RENDERABLE:
   case GL_DEPTH_RENDERABLE:
   case GL_STENCIL_RENDERABLE:
      if (!_is_renderable(ctx, internalformat))
         goto end;

      if (pname == GL_COLOR_RENDERABLE) {
         if (!_mesa_is_color_format(internalformat))
            goto end;
      } else {
         GLenum baseFormat = _mesa_base_fbo_format(ctx, internalformat);
         if (baseFormat != GL_DEPTH_STENCIL &&
             ((pname == GL_DEPTH_RENDERABLE && baseFormat != GL_DEPTH_COMPONENT) ||
              (pname == GL_STENCIL_RENDERABLE && baseFormat != GL_STENCIL_INDEX)))
            goto end;
      }

      buffer[0] = GL_TRUE;
      break;

   case GL_FRAMEBUFFER_RENDERABLE_LAYERED:
      if (!_mesa_has_EXT_texture_array(ctx) ||
          _legal_target_for_framebuffer_texture_layer(ctx, target))
         goto end;
      /* fallthrough */
   case GL_FRAMEBUFFER_RENDERABLE:
   case GL_FRAMEBUFFER_BLEND:
      if (!_mesa_has_ARB_framebuffer_object(ctx))
         goto end;

      if (target == GL_TEXTURE_BUFFER ||
          !_is_renderable(ctx, internalformat))
         goto end;

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_READ_PIXELS:
   case GL_READ_PIXELS_FORMAT:
   case GL_READ_PIXELS_TYPE:
      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_TEXTURE_IMAGE_FORMAT:
   case GL_GET_TEXTURE_IMAGE_FORMAT:
   case GL_TEXTURE_IMAGE_TYPE:
   case GL_GET_TEXTURE_IMAGE_TYPE:
      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_MIPMAP:
   case GL_MANUAL_GENERATE_MIPMAP:
   case GL_AUTO_GENERATE_MIPMAP:
      if (!_mesa_is_valid_generate_texture_mipmap_target(ctx, target) ||
          !_mesa_is_valid_generate_texture_mipmap_internalformat(ctx,
                                                              internalformat)) {
         goto end;
      }

      if (pname == GL_MIPMAP) {
         buffer[0] = GL_TRUE;
         goto end;
      }
      else if (pname == GL_MANUAL_GENERATE_MIPMAP) {
         if (!_mesa_has_ARB_framebuffer_object(ctx))
            goto end;
      }
      else {
         /* From ARB_internalformat_query2:
          *    "Dependencies on OpenGL 3.2 (Core Profile)
          *     In core profiles for OpenGL 3.2 and later versions, queries
          *     for the AUTO_GENERATE_MIPMAP <pname> return the appropriate
          *     unsupported response."
          */
         if (_mesa_is_desktop_gl(ctx) && ctx->Version >= 32)
            goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_COLOR_ENCODING:
      if (!_mesa_is_color_format(internalformat))
         goto end;

      if (_mesa_is_srgb_format(internalformat))
         buffer[0] = GL_SRGB;
      else
         buffer[0] = GL_LINEAR;
      break;

   case GL_SRGB_READ:
      if (!_mesa_has_EXT_texture_sRGB(ctx) ||
          !_mesa_is_srgb_format(internalformat)) {
         goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_SRGB_WRITE:
      if (!_mesa_has_EXT_framebuffer_sRGB(ctx) ||
          !_mesa_is_color_format(internalformat)) {
         goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_SRGB_DECODE_ARB:
      /* Presence of EXT_texture_sRGB_decode was already verified */
      if (!_mesa_has_EXT_texture_sRGB(ctx) ||
          target == GL_RENDERBUFFER ||
          !_mesa_is_srgb_format(internalformat)) {
         goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_FILTER:
      /* If it doesn't allow to set sampler parameters then it would not allow
       * to set a filter different to GL_NEAREST. In practice, this method
       * only filters out MULTISAMPLE/MULTISAMPLE_ARRAY */
      if (!_mesa_target_allows_setting_sampler_parameters(target))
         goto end;

      if (_mesa_is_enum_format_integer(internalformat))
         goto end;

      if (target == GL_TEXTURE_BUFFER)
         goto end;

      /* At this point we know that multi-texel filtering is supported. We
       * need to call the driver to know if it is CAVEAT_SUPPORT or
       * FULL_SUPPORT.
       */
      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_VERTEX_TEXTURE:
   case GL_TESS_CONTROL_TEXTURE:
   case GL_TESS_EVALUATION_TEXTURE:
   case GL_GEOMETRY_TEXTURE:
   case GL_FRAGMENT_TEXTURE:
   case GL_COMPUTE_TEXTURE:
      if (target == GL_RENDERBUFFER)
         goto end;

      if ((pname == GL_TESS_CONTROL_TEXTURE ||
           pname == GL_TESS_EVALUATION_TEXTURE) &&
          !_mesa_has_tessellation(ctx))
         goto end;

      if (pname == GL_GEOMETRY_TEXTURE && !_mesa_has_geometry_shaders(ctx))
         goto end;

      if (pname == GL_COMPUTE_TEXTURE && !_mesa_has_compute_shaders(ctx))
         goto end;

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_TEXTURE_GATHER:
   case GL_TEXTURE_GATHER_SHADOW:
      if (!_mesa_has_ARB_texture_gather(ctx))
         goto end;

      /* fallthrough */
   case GL_TEXTURE_SHADOW:
      /* Only depth or depth-stencil image formats make sense in shadow
         samplers */
      if (pname != GL_TEXTURE_GATHER &&
          !_mesa_is_depth_format(internalformat) &&
          !_mesa_is_depthstencil_format(internalformat))
         goto end;

      /* Validate the target for shadow and gather operations */
      switch (target) {
      case GL_TEXTURE_2D:
      case GL_TEXTURE_2D_ARRAY:
      case GL_TEXTURE_CUBE_MAP:
      case GL_TEXTURE_CUBE_MAP_ARRAY:
      case GL_TEXTURE_RECTANGLE:
         break;

      case GL_TEXTURE_1D:
      case GL_TEXTURE_1D_ARRAY:
         /* 1D and 1DArray textures are not admitted in gather operations */
         if (pname != GL_TEXTURE_SHADOW)
            goto end;
         break;

      default:
         goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_SHADER_IMAGE_LOAD:
   case GL_SHADER_IMAGE_STORE:
      if (!_mesa_has_ARB_shader_image_load_store(ctx))
         goto end;

      /* We call to _mesa_is_shader_image_format_supported
       * using "internalformat" as parameter, because the
       * the ARB_internalformat_query2 spec says:
       * "In this case the <internalformat> is the value of the <format>
       * parameter that is passed to BindImageTexture."
       */
      if (target == GL_RENDERBUFFER ||
          !_mesa_is_shader_image_format_supported(ctx, internalformat))
         goto end;

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_SHADER_IMAGE_ATOMIC:
      if (!_mesa_has_ARB_shader_image_load_store(ctx))
         goto end;

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_IMAGE_TEXEL_SIZE: {
      mesa_format image_format;

      if (!_mesa_has_ARB_shader_image_load_store(ctx) ||
          target == GL_RENDERBUFFER)
         goto end;

      image_format = _mesa_get_shader_image_format(internalformat);
      if (image_format == MESA_FORMAT_NONE)
         goto end;

      /* We return bits */
      buffer[0] = (_mesa_get_format_bytes(image_format) * 8);
      break;
   }

   case GL_IMAGE_COMPATIBILITY_CLASS:
      if (!_mesa_has_ARB_shader_image_load_store(ctx) ||
          target == GL_RENDERBUFFER)
         goto end;

      buffer[0] = _mesa_get_image_format_class(internalformat);
      break;

   case GL_IMAGE_PIXEL_FORMAT: {
      GLint base_format;

      if (!_mesa_has_ARB_shader_image_load_store(ctx) ||
          target == GL_RENDERBUFFER ||
          !_mesa_is_shader_image_format_supported(ctx, internalformat))
         goto end;

      base_format = _mesa_base_tex_format(ctx, internalformat);
      if (base_format == -1)
         goto end;

      if (_mesa_is_enum_format_integer(internalformat))
         buffer[0] = _mesa_base_format_to_integer_format(base_format);
      else
         buffer[0] = base_format;
      break;
   }

   case GL_IMAGE_PIXEL_TYPE: {
      mesa_format image_format;
      GLenum datatype;
      GLuint comps;

      if (!_mesa_has_ARB_shader_image_load_store(ctx) ||
          target == GL_RENDERBUFFER)
         goto end;

      image_format = _mesa_get_shader_image_format(internalformat);
      if (image_format == MESA_FORMAT_NONE)
         goto end;

      _mesa_uncompressed_format_to_type_and_comps(image_format, &datatype,
                                                  &comps);
      if (!datatype)
         goto end;

      buffer[0] = datatype;
      break;
   }

   case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE: {
      if (!_mesa_has_ARB_shader_image_load_store(ctx))
         goto end;

      if (!_mesa_legal_get_tex_level_parameter_target(ctx, target, true))
         goto end;

      /* From spec: "Equivalent to calling GetTexParameter with <value> set
       * to IMAGE_FORMAT_COMPATIBILITY_TYPE."
       *
       * GetTexParameter just returns
       * tex_obj->ImageFormatCompatibilityType. We create a fake tex_obj
       * just with the purpose of getting the value.
       */
      struct gl_texture_object *tex_obj = _mesa_new_texture_object(ctx, 0, target);
      buffer[0] = tex_obj->ImageFormatCompatibilityType;
      _mesa_delete_texture_object(ctx, tex_obj);

      break;
   }

   case GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST:
   case GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST:
   case GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE:
   case GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE:
      if (target == GL_RENDERBUFFER)
         goto end;

      if (!_mesa_is_depthstencil_format(internalformat)) {
         if (((pname == GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST ||
               pname == GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE) &&
              !_mesa_is_depth_format(internalformat)) ||
             ((pname == GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST ||
               pname == GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE) &&
              !_mesa_is_stencil_format(internalformat)))
            goto end;
      }

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_TEXTURE_COMPRESSED:
      buffer[0] = _mesa_is_compressed_format(ctx, internalformat);
      break;

   case GL_TEXTURE_COMPRESSED_BLOCK_WIDTH:
   case GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT:
   case GL_TEXTURE_COMPRESSED_BLOCK_SIZE: {
      mesa_format mesaformat;
      GLint block_size;

      mesaformat = _mesa_glenum_to_compressed_format(internalformat);
      if (mesaformat == MESA_FORMAT_NONE)
         goto end;

      block_size = _mesa_get_format_bytes(mesaformat);
      assert(block_size > 0);

      if (pname == GL_TEXTURE_COMPRESSED_BLOCK_SIZE) {
         buffer[0] = block_size;
      } else {
         GLuint bwidth, bheight;

         /* Returns the width and height in pixels. We return bytes */
         _mesa_get_format_block_size(mesaformat, &bwidth, &bheight);
         assert(bwidth > 0 && bheight > 0);

         if (pname == GL_TEXTURE_COMPRESSED_BLOCK_WIDTH)
            buffer[0] = block_size / bheight;
         else
            buffer[0] = block_size / bwidth;
      }
      break;
   }

   case GL_CLEAR_BUFFER:
      if (target != GL_TEXTURE_BUFFER)
         goto end;

      ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                      buffer);
      break;

   case GL_TEXTURE_VIEW:
   case GL_VIEW_COMPATIBILITY_CLASS:
      if (!_mesa_has_ARB_texture_view(ctx) ||
          target == GL_TEXTURE_BUFFER ||
          target == GL_RENDERBUFFER)
         goto end;

      if (pname == GL_TEXTURE_VIEW) {
         ctx->Driver.QueryInternalFormat(ctx, target, internalformat, pname,
                                         buffer);
      } else {
         GLenum view_class = _mesa_texture_view_lookup_view_class(ctx,
                                                                  internalformat);
         if (view_class == GL_FALSE)
            goto end;

         buffer[0] = view_class;
      }
      break;

   default:
      unreachable("bad param");
   }

 end:
   if (bufSize != 0 && params == NULL) {
      /* Emit a warning to aid application debugging, but go ahead and do the
       * memcpy (and probably crash) anyway.
       */
      _mesa_warning(ctx,
                    "glGetInternalformativ(bufSize = %d, but params = NULL)",
                    bufSize);
   }

   /* Copy the data from the temporary buffer to the buffer supplied by the
    * application.  Clamp the size of the copy to the size supplied by the
    * application.
    */
   memcpy(params, buffer, MIN2(bufSize, 16) * sizeof(GLint));

   return;
}
示例#4
0
文件: texparam.c 项目: altf4/mesa
void GLAPIENTRY
_mesa_GetTexLevelParameteriv( GLenum target, GLint level,
                              GLenum pname, GLint *params )
{
   const struct gl_texture_unit *texUnit;
   struct gl_texture_object *texObj;
   const struct gl_texture_image *img = NULL;
   GLint maxLevels;
   gl_format texFormat;
   GET_CURRENT_CONTEXT(ctx);
   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (ctx->Texture.CurrentUnit >= ctx->Const.MaxCombinedTextureImageUnits) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
                  "glGetTexLevelParameteriv(current unit)");
      return;
   }

   texUnit = _mesa_get_current_tex_unit(ctx);

   /* this will catch bad target values */
   maxLevels = _mesa_max_texture_levels(ctx, target);
   if (maxLevels == 0) {
      _mesa_error(ctx, GL_INVALID_ENUM,
                  "glGetTexLevelParameter[if]v(target=0x%x)", target);
      return;
   }

   if (level < 0 || level >= maxLevels) {
      _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
      return;
   }

   texObj = _mesa_select_tex_object(ctx, texUnit, target);

   img = _mesa_select_tex_image(ctx, texObj, target, level);
   if (!img || img->TexFormat == MESA_FORMAT_NONE) {
      /* undefined texture image */
      if (pname == GL_TEXTURE_COMPONENTS)
         *params = 1;
      else
         *params = 0;
      return;
   }

   texFormat = img->TexFormat;

   switch (pname) {
      case GL_TEXTURE_WIDTH:
         *params = img->Width;
         break;
      case GL_TEXTURE_HEIGHT:
         *params = img->Height;
         break;
      case GL_TEXTURE_DEPTH:
         *params = img->Depth;
         break;
      case GL_TEXTURE_INTERNAL_FORMAT:
         if (_mesa_is_format_compressed(texFormat)) {
            /* need to return the actual compressed format */
            *params = _mesa_compressed_format_to_glenum(ctx, texFormat);
         }
         else {
	    /* If the true internal format is not compressed but the user
	     * requested a generic compressed format, we have to return the
	     * generic base format that matches.
	     *
	     * From page 119 (page 129 of the PDF) of the OpenGL 1.3 spec:
	     *
	     *     "If no specific compressed format is available,
	     *     internalformat is instead replaced by the corresponding base
	     *     internal format."
	     *
	     * Otherwise just return the user's requested internal format
	     */
	    const GLenum f =
	       _mesa_gl_compressed_format_base_format(img->InternalFormat);

	    *params = (f != 0) ? f : img->InternalFormat;
	 }
         break;
      case GL_TEXTURE_BORDER:
         *params = img->Border;
         break;
      case GL_TEXTURE_RED_SIZE:
      case GL_TEXTURE_GREEN_SIZE:
      case GL_TEXTURE_BLUE_SIZE:
      case GL_TEXTURE_ALPHA_SIZE:
         if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
            *params = _mesa_get_format_bits(texFormat, pname);
         else
            *params = 0;
         break;
      case GL_TEXTURE_INTENSITY_SIZE:
      case GL_TEXTURE_LUMINANCE_SIZE:
         if (_mesa_base_format_has_channel(img->_BaseFormat, pname)) {
            *params = _mesa_get_format_bits(texFormat, pname);
            if (*params == 0) {
               /* intensity or luminance is probably stored as RGB[A] */
               *params = MIN2(_mesa_get_format_bits(texFormat,
                                                    GL_TEXTURE_RED_SIZE),
                              _mesa_get_format_bits(texFormat,
                                                    GL_TEXTURE_GREEN_SIZE));
            }
         }
         else {
            *params = 0;
         }
         break;
      case GL_TEXTURE_DEPTH_SIZE_ARB:
         if (!ctx->Extensions.ARB_depth_texture)
            goto invalid_pname;
         *params = _mesa_get_format_bits(texFormat, pname);
         break;
      case GL_TEXTURE_STENCIL_SIZE_EXT:
         if (!ctx->Extensions.EXT_packed_depth_stencil &&
             !ctx->Extensions.ARB_framebuffer_object)
            goto invalid_pname;
         *params = _mesa_get_format_bits(texFormat, pname);
         break;
      case GL_TEXTURE_SHARED_SIZE:
         if (ctx->Version < 30 &&
             !ctx->Extensions.EXT_texture_shared_exponent)
            goto invalid_pname;
         *params = texFormat == MESA_FORMAT_RGB9_E5_FLOAT ? 5 : 0;
         break;

      /* GL_ARB_texture_compression */
      case GL_TEXTURE_COMPRESSED_IMAGE_SIZE:
	 if (_mesa_is_format_compressed(texFormat) &&
             !_mesa_is_proxy_texture(target)) {
            *params = _mesa_format_image_size(texFormat, img->Width,
                                              img->Height, img->Depth);
	 }
	 else {
	    _mesa_error(ctx, GL_INVALID_OPERATION,
			"glGetTexLevelParameter[if]v(pname)");
	 }
         break;
      case GL_TEXTURE_COMPRESSED:
         *params = (GLint) _mesa_is_format_compressed(texFormat);
         break;

      /* GL_ARB_texture_float */
      case GL_TEXTURE_RED_TYPE_ARB:
      case GL_TEXTURE_GREEN_TYPE_ARB:
      case GL_TEXTURE_BLUE_TYPE_ARB:
      case GL_TEXTURE_ALPHA_TYPE_ARB:
      case GL_TEXTURE_LUMINANCE_TYPE_ARB:
      case GL_TEXTURE_INTENSITY_TYPE_ARB:
      case GL_TEXTURE_DEPTH_TYPE_ARB:
         if (!ctx->Extensions.ARB_texture_float)
            goto invalid_pname;
	 if (_mesa_base_format_has_channel(img->_BaseFormat, pname))
	    *params = _mesa_get_format_datatype(texFormat);
	 else
	    *params = GL_NONE;
         break;

      default:
         goto invalid_pname;
   }

   /* no error if we get here */
   return;

invalid_pname:
   _mesa_error(ctx, GL_INVALID_ENUM,
               "glGetTexLevelParameter[if]v(pname=%s)",
               _mesa_lookup_enum_by_nr(pname));
}