Esempio n. 1
0
/**
 * Compute/return the offset of the stencil value in a pixel.
 * For example, if the format is Z24+S8, the position of the stencil bits
 * within the 4-byte pixel will be either 0 or 3.
 */
static GLint
get_stencil_offset(gl_format format)
{
   const GLubyte one = 1;
   GLubyte pixel[MAX_PIXEL_BYTES];
   GLint bpp = _mesa_get_format_bytes(format);
   GLint i;

   assert(_mesa_get_format_bits(format, GL_STENCIL_BITS) == 8);
   memset(pixel, 0, sizeof(pixel));
   _mesa_pack_ubyte_stencil_row(format, 1, &one, pixel);

   for (i = 0; i < bpp; i++) {
      if (pixel[i])
         return i;
   }

   _mesa_problem(NULL, "get_stencil_offset() failed\n");
   return 0;
}
Esempio n. 2
0
/**
 * Determine if we need to clear the combiend depth/stencil buffer by
 * drawing a quad.
 */
static INLINE GLboolean
check_clear_depth_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
   const GLuint stencilMax = 0xff;
   GLboolean maskStencil
      = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;

   assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0);

   if (ctx->Scissor.Enabled &&
       (ctx->Scissor.X != 0 ||
        ctx->Scissor.Y != 0 ||
        ctx->Scissor.Width < rb->Width ||
        ctx->Scissor.Height < rb->Height))
      return GL_TRUE;

   if (maskStencil)
      return GL_TRUE;

   return GL_FALSE;
}
Esempio n. 3
0
/* common formats supported as both textures and render targets */
unsigned r200_check_blit(gl_format mesa_format)
{
    /* XXX others?  BE/LE? */
    switch (mesa_format) {
    case MESA_FORMAT_ARGB8888:
    case MESA_FORMAT_XRGB8888:
    case MESA_FORMAT_RGB565:
    case MESA_FORMAT_ARGB4444:
    case MESA_FORMAT_ARGB1555:
    case MESA_FORMAT_A8:
	    break;
    default:
	    return 0;
    }

    /* ??? */
    if (_mesa_get_format_bits(mesa_format, GL_DEPTH_BITS) > 0)
	    return 0;

    return 1;
}
Esempio n. 4
0
void untile_image(const void * src, unsigned src_pitch,
                  void *dst, unsigned dst_pitch,
                  gl_format format, unsigned width, unsigned height)
{
    assert(src_pitch >= width);
    assert(dst_pitch >= width);

    radeon_print(RADEON_TEXTURE, RADEON_TRACE,
                 "Software untiling: src_pitch %d, dst_pitch %d, width %d, height %d, bpp %d\n",
                 src_pitch, dst_pitch, width, height, _mesa_get_format_bytes(format));

    switch (_mesa_get_format_bytes(format))
    {
        case 16:
            micro_untile_1_x_1_128bit(src, src_pitch, dst, dst_pitch, width, height);
            break;
        case 8:
            micro_untile_2_x_2_64bit(src, src_pitch, dst, dst_pitch, width, height);
            break;
        case 4:
            micro_untile_4_x_2_32bit(src, src_pitch, dst, dst_pitch, width, height);
            break;
        case 2:
            if (_mesa_get_format_bits(format, GL_DEPTH_BITS))
            {
                micro_untile_4_x_4_16bit(src, src_pitch, dst, dst_pitch, width, height);
            }
            else
            {
                micro_untile_8_x_2_16bit(src, src_pitch, dst, dst_pitch, width, height);
            }
            break;
        case 1:
            micro_untile_8_x_4_8bit(src, src_pitch, dst, dst_pitch, width, height);
            break;
        default:
            assert(0);
            break;
    }
}
Esempio n. 5
0
void get_tile_size(gl_format format, unsigned *block_width, unsigned *block_height)
{
    switch (_mesa_get_format_bytes(format))
    {
        case 16:
            *block_width = 1;
            *block_height = 1;
            break;
        case 8:
            *block_width = 2;
            *block_height = 2;
            break;
        case 4:
            *block_width = 4;
            *block_height = 2;
            break;
        case 2:
            if (_mesa_get_format_bits(format, GL_DEPTH_BITS))
            {
                *block_width = 4;
                *block_height = 4;
            }
            else
            {
                *block_width = 8;
                *block_height = 2;
            }
            break;
        case 1:
            *block_width = 8;
            *block_height = 4;
            break;
        default:
            assert(0);
            break;
    }
}
/**
 * Check if the renderbuffer for a read/draw operation exists.
 * \param format  a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA,
 *                GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL.
 * \param reading  if TRUE, we're going to read from the buffer,
                   if FALSE, we're going to write to the buffer.
 * \return GL_TRUE if buffer exists, GL_FALSE otherwise
 */
static GLboolean
renderbuffer_exists(struct gl_context *ctx,
                    struct gl_framebuffer *fb,
                    GLenum format,
                    GLboolean reading)
{
   const struct gl_renderbuffer_attachment *att = fb->Attachment;

   /* If we don't know the framebuffer status, update it now */
   if (fb->_Status == 0) {
      _mesa_test_framebuffer_completeness(ctx, fb);
   }

   if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      return GL_FALSE;
   }

   switch (format) {
   case GL_COLOR:
   case GL_RED:
   case GL_GREEN:
   case GL_BLUE:
   case GL_ALPHA:
   case GL_LUMINANCE:
   case GL_LUMINANCE_ALPHA:
   case GL_INTENSITY:
   case GL_RG:
   case GL_RGB:
   case GL_BGR:
   case GL_RGBA:
   case GL_BGRA:
   case GL_ABGR_EXT:
   case GL_RED_INTEGER_EXT:
   case GL_RG_INTEGER:
   case GL_GREEN_INTEGER_EXT:
   case GL_BLUE_INTEGER_EXT:
   case GL_ALPHA_INTEGER_EXT:
   case GL_RGB_INTEGER_EXT:
   case GL_RGBA_INTEGER_EXT:
   case GL_BGR_INTEGER_EXT:
   case GL_BGRA_INTEGER_EXT:
   case GL_LUMINANCE_INTEGER_EXT:
   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
      if (reading) {
         /* about to read from a color buffer */
         const struct gl_renderbuffer *readBuf = fb->_ColorReadBuffer;
         if (!readBuf) {
            return GL_FALSE;
         }
         assert(_mesa_get_format_bits(readBuf->Format, GL_RED_BITS) > 0 ||
                _mesa_get_format_bits(readBuf->Format, GL_ALPHA_BITS) > 0 ||
                _mesa_get_format_bits(readBuf->Format, GL_TEXTURE_LUMINANCE_SIZE) > 0 ||
                _mesa_get_format_bits(readBuf->Format, GL_TEXTURE_INTENSITY_SIZE) > 0 ||
                _mesa_get_format_bits(readBuf->Format, GL_INDEX_BITS) > 0);
      }
      else {
         /* about to draw to zero or more color buffers (none is OK) */
         return GL_TRUE;
      }
      break;
   case GL_DEPTH:
   case GL_DEPTH_COMPONENT:
      if (att[BUFFER_DEPTH].Type == GL_NONE) {
         return GL_FALSE;
      }
      break;
   case GL_STENCIL:
   case GL_STENCIL_INDEX:
      if (att[BUFFER_STENCIL].Type == GL_NONE) {
         return GL_FALSE;
      }
      break;
   case GL_DEPTH_STENCIL_EXT:
      if (att[BUFFER_DEPTH].Type == GL_NONE ||
          att[BUFFER_STENCIL].Type == GL_NONE) {
         return GL_FALSE;
      }
      break;
   default:
      _mesa_problem(ctx,
                    "Unexpected format 0x%x in renderbuffer_exists",
                    format);
      return GL_FALSE;
   }

   /* OK */
   return GL_TRUE;
}
/**
 * The glGet queries of the framebuffer red/green/blue size, stencil size,
 * etc. are satisfied by the fields of ctx->DrawBuffer->Visual.  These can
 * change depending on the renderbuffer bindings.  This function updates
 * the given framebuffer's Visual from the current renderbuffer bindings.
 *
 * This may apply to user-created framebuffers or window system framebuffers.
 *
 * Also note: ctx->DrawBuffer->Visual.depthBits might not equal
 * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits.
 * The former one is used to convert floating point depth values into
 * integer Z values.
 */
void
_mesa_update_framebuffer_visual(struct gl_context *ctx,
				struct gl_framebuffer *fb)
{
   GLuint i;

   memset(&fb->Visual, 0, sizeof(fb->Visual));
   fb->Visual.rgbMode = GL_TRUE; /* assume this */

   /* find first RGB renderbuffer */
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
         const mesa_format fmt = rb->Format;

         /* Grab samples and sampleBuffers from any attachment point (assuming
          * the framebuffer is complete, we'll get the same answer from all
          * attachments).
          */
         fb->Visual.samples = rb->NumSamples;
         fb->Visual.sampleBuffers = rb->NumSamples > 0 ? 1 : 0;

         if (_mesa_is_legal_color_format(ctx, baseFormat)) {
            fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
            fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
            fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
            fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
            fb->Visual.rgbBits = fb->Visual.redBits
               + fb->Visual.greenBits + fb->Visual.blueBits;
            if (_mesa_get_format_color_encoding(fmt) == GL_SRGB)
                fb->Visual.sRGBCapable = ctx->Extensions.EXT_framebuffer_sRGB;
            break;
         }
      }
   }

   fb->Visual.floatMode = GL_FALSE;
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         const mesa_format fmt = rb->Format;

         if (_mesa_get_format_datatype(fmt) == GL_FLOAT) {
            fb->Visual.floatMode = GL_TRUE;
            break;
         }
      }
   }

   if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_DEPTH].Renderbuffer;
      const mesa_format fmt = rb->Format;
      fb->Visual.haveDepthBuffer = GL_TRUE;
      fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS);
   }

   if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_STENCIL].Renderbuffer;
      const mesa_format fmt = rb->Format;
      fb->Visual.haveStencilBuffer = GL_TRUE;
      fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS);
   }

   if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_ACCUM].Renderbuffer;
      const mesa_format fmt = rb->Format;
      fb->Visual.haveAccumBuffer = GL_TRUE;
      fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
      fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
      fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
      fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
   }

   compute_depth_max(fb);
}
Esempio n. 8
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));
}
Esempio n. 9
0
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) {
      /* 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:
         if (img->_BaseFormat == GL_RED) {
            *params = _mesa_get_format_bits(texFormat, pname);
	    break;
	 }
	 /* FALLTHROUGH */
      case GL_TEXTURE_GREEN_SIZE:
         if (img->_BaseFormat == GL_RG) {
            *params = _mesa_get_format_bits(texFormat, pname);
	    break;
	 }
	 /* FALLTHROUGH */
      case GL_TEXTURE_BLUE_SIZE:
         if (img->_BaseFormat == GL_RGB || img->_BaseFormat == GL_RGBA)
            *params = _mesa_get_format_bits(texFormat, pname);
         else
            *params = 0;
         break;
      case GL_TEXTURE_ALPHA_SIZE:
         if (img->_BaseFormat == GL_ALPHA ||
             img->_BaseFormat == GL_LUMINANCE_ALPHA ||
             img->_BaseFormat == GL_RGBA)
            *params = _mesa_get_format_bits(texFormat, pname);
         else
            *params = 0;
         break;
      case GL_TEXTURE_INTENSITY_SIZE:
         if (img->_BaseFormat != GL_INTENSITY)
            *params = 0;
         else {
            *params = _mesa_get_format_bits(texFormat, pname);
            if (*params == 0) {
               /* intensity probably stored as rgb texture */
               *params = MIN2(_mesa_get_format_bits(texFormat, GL_TEXTURE_RED_SIZE),
                              _mesa_get_format_bits(texFormat, GL_TEXTURE_GREEN_SIZE));
            }
         }
         break;
      case GL_TEXTURE_LUMINANCE_SIZE:
         if (img->_BaseFormat != GL_LUMINANCE &&
             img->_BaseFormat != GL_LUMINANCE_ALPHA)
            *params = 0;
         else {
            *params = _mesa_get_format_bits(texFormat, pname);
            if (*params == 0) {
               /* luminance probably stored as rgb texture */
               *params = MIN2(_mesa_get_format_bits(texFormat, GL_TEXTURE_RED_SIZE),
                              _mesa_get_format_bits(texFormat, GL_TEXTURE_GREEN_SIZE));
            }
         }
         break;
      case GL_TEXTURE_INDEX_SIZE_EXT:
         if (img->_BaseFormat == GL_COLOR_INDEX)
            *params = _mesa_get_format_bits(texFormat, pname);
         else
            *params = 0;
         break;
      case GL_TEXTURE_DEPTH_SIZE_ARB:
         if (ctx->Extensions.ARB_depth_texture)
            *params = _mesa_get_format_bits(texFormat, pname);
         else
            goto invalid_pname;
         break;
      case GL_TEXTURE_STENCIL_SIZE_EXT:
         if (ctx->Extensions.EXT_packed_depth_stencil ||
             ctx->Extensions.ARB_framebuffer_object) {
            *params = _mesa_get_format_bits(texFormat, pname);
         }
         else {
            goto invalid_pname;
         }
         break;
      case GL_TEXTURE_SHARED_SIZE:
         if (ctx->VersionMajor >= 3 ||
             ctx->Extensions.EXT_texture_shared_exponent) {
            *params = texFormat == MESA_FORMAT_RGB9_E5_FLOAT ? 5 : 0;
         }
         else {
            goto invalid_pname;
         }
         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:
         if (ctx->Extensions.ARB_texture_float) {
            *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_RED_SIZE) ?
               _mesa_get_format_datatype(texFormat) : GL_NONE;
         }
         else {
            goto invalid_pname;
         }
         break;
      case GL_TEXTURE_GREEN_TYPE_ARB:
         if (ctx->Extensions.ARB_texture_float) {
            *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_GREEN_SIZE) ?
               _mesa_get_format_datatype(texFormat) : GL_NONE;
         }
         else {
            goto invalid_pname;
         }
         break;
      case GL_TEXTURE_BLUE_TYPE_ARB:
         if (ctx->Extensions.ARB_texture_float) {
            *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_BLUE_SIZE) ?
               _mesa_get_format_datatype(texFormat) : GL_NONE;
         }
         else {
            goto invalid_pname;
         }
         break;
      case GL_TEXTURE_ALPHA_TYPE_ARB:
         if (ctx->Extensions.ARB_texture_float) {
            *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_ALPHA_SIZE) ?
               _mesa_get_format_datatype(texFormat) : GL_NONE;
         }
         else {
            goto invalid_pname;
         }
         break;
      case GL_TEXTURE_LUMINANCE_TYPE_ARB:
         if (ctx->Extensions.ARB_texture_float) {
            *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_LUMINANCE_SIZE) ?
               _mesa_get_format_datatype(texFormat) : GL_NONE;
         }
         else {
            goto invalid_pname;
         }
         break;
      case GL_TEXTURE_INTENSITY_TYPE_ARB:
         if (ctx->Extensions.ARB_texture_float) {
            *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_INTENSITY_SIZE) ?
               _mesa_get_format_datatype(texFormat) : GL_NONE;
         }
         else {
            goto invalid_pname;
         }
         break;
      case GL_TEXTURE_DEPTH_TYPE_ARB:
         if (ctx->Extensions.ARB_texture_float) {
            *params = _mesa_get_format_bits(texFormat, GL_TEXTURE_DEPTH_SIZE) ?
               _mesa_get_format_datatype(texFormat) : GL_NONE;
         }
         else {
            goto invalid_pname;
         }
         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));
}
Esempio n. 10
0
static GLboolean
do_copy_texsubimage(GLcontext *ctx,
                    GLenum target, GLint level,
                    struct radeon_tex_obj *tobj,
                    radeon_texture_image *timg,
                    GLint dstx, GLint dsty,
                    GLint x, GLint y,
                    GLsizei width, GLsizei height)
{
    radeonContextPtr radeon = RADEON_CONTEXT(ctx);
    struct radeon_renderbuffer *rrb;
    unsigned src_bpp;
    unsigned dst_bpp;
    gl_format src_mesaformat;
    gl_format dst_mesaformat;
    unsigned src_width;
    unsigned dst_width;
    unsigned flip_y;

    if (!radeon->vtbl.blit) {
        return GL_FALSE;
    }

    if (_mesa_get_format_bits(timg->base.TexFormat, GL_DEPTH_BITS) > 0) {
        if (ctx->ReadBuffer->_DepthBuffer && ctx->ReadBuffer->_DepthBuffer->Wrapped) {
            rrb = radeon_renderbuffer(ctx->ReadBuffer->_DepthBuffer->Wrapped);
        } else {
            rrb = radeon_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
        }
        flip_y = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Type == GL_NONE;
    } else {
        rrb = radeon_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
        flip_y = ctx->ReadBuffer->Attachment[BUFFER_COLOR0].Type == GL_NONE;
    }

    // This is software renderbuffer, fallback to swrast
    if (!rrb) {
        return GL_FALSE;
    }

    if (!timg->mt) {
        radeon_validate_texture_miptree(ctx, &tobj->base);
    }

    assert(rrb->bo);
    assert(timg->mt);
    assert(timg->mt->bo);
    assert(timg->base.Width >= dstx + width);
    assert(timg->base.Height >= dsty + height);

    intptr_t src_offset = rrb->draw_offset;
    intptr_t dst_offset = radeon_miptree_image_offset(timg->mt, _mesa_tex_target_to_face(target), level);

    if (0) {
        fprintf(stderr, "%s: copying to face %d, level %d\n",
                __FUNCTION__, _mesa_tex_target_to_face(target), level);
        fprintf(stderr, "to: x %d, y %d, offset %d\n", dstx, dsty, (uint32_t) dst_offset);
        fprintf(stderr, "from (%dx%d) width %d, height %d, offset %d, pitch %d\n",
                x, y, rrb->base.Width, rrb->base.Height, (uint32_t) src_offset, rrb->pitch/rrb->cpp);
        fprintf(stderr, "src size %d, dst size %d\n", rrb->bo->size, timg->mt->bo->size);

    }

    src_mesaformat = rrb->base.Format;
    dst_mesaformat = timg->base.TexFormat;
    src_width = rrb->base.Width;
    dst_width = timg->base.Width;
    src_bpp = _mesa_get_format_bytes(src_mesaformat);
    dst_bpp = _mesa_get_format_bytes(dst_mesaformat);
    if (!radeon->vtbl.check_blit(dst_mesaformat)) {
	    /* depth formats tend to be special */
	    if (_mesa_get_format_bits(dst_mesaformat, GL_DEPTH_BITS) > 0)
		    return GL_FALSE;

	    if (src_bpp != dst_bpp)
		    return GL_FALSE;

	    switch (dst_bpp) {
	    case 2:
		    src_mesaformat = MESA_FORMAT_RGB565;
		    dst_mesaformat = MESA_FORMAT_RGB565;
		    break;
	    case 4:
		    src_mesaformat = MESA_FORMAT_ARGB8888;
		    dst_mesaformat = MESA_FORMAT_ARGB8888;
		    break;
	    case 1:
		    src_mesaformat = MESA_FORMAT_A8;
		    dst_mesaformat = MESA_FORMAT_A8;
		    break;
	    default:
		    return GL_FALSE;
	    }
    }

    /* blit from src buffer to texture */
    return radeon->vtbl.blit(ctx, rrb->bo, src_offset, src_mesaformat, rrb->pitch/rrb->cpp,
                             src_width, rrb->base.Height, x, y,
                             timg->mt->bo, dst_offset, dst_mesaformat,
                             timg->mt->levels[level].rowstride / dst_bpp,
                             dst_width, timg->base.Height,
                             dstx, dsty, width, height, flip_y);
}
Esempio n. 11
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;
}
Esempio n. 12
0
/**
 * Implements a rectangular block transfer (blit) of pixels between two
 * miptrees.
 *
 * Our blitter can operate on 1, 2, or 4-byte-per-pixel data, with generous,
 * but limited, pitches and sizes allowed.
 *
 * The src/dst coordinates are relative to the given level/slice of the
 * miptree.
 *
 * If @src_flip or @dst_flip is set, then the rectangle within that miptree
 * will be inverted (including scanline order) when copying.  This is common
 * in GL when copying between window system and user-created
 * renderbuffers/textures.
 */
bool
intel_miptree_blit(struct brw_context *brw,
                   struct intel_mipmap_tree *src_mt,
                   int src_level, int src_slice,
                   uint32_t src_x, uint32_t src_y, bool src_flip,
                   struct intel_mipmap_tree *dst_mt,
                   int dst_level, int dst_slice,
                   uint32_t dst_x, uint32_t dst_y, bool dst_flip,
                   uint32_t width, uint32_t height,
                   enum gl_logicop_mode logicop)
{
   /* The blitter doesn't understand multisampling at all. */
   if (src_mt->surf.samples > 1 || dst_mt->surf.samples > 1)
      return false;

   /* No sRGB decode or encode is done by the hardware blitter, which is
    * consistent with what we want in many callers (glCopyTexSubImage(),
    * texture validation, etc.).
    */
   mesa_format src_format = _mesa_get_srgb_format_linear(src_mt->format);
   mesa_format dst_format = _mesa_get_srgb_format_linear(dst_mt->format);

   /* The blitter doesn't support doing any format conversions.  We do also
    * support blitting ARGB8888 to XRGB8888 (trivial, the values dropped into
    * the X channel don't matter), and XRGB8888 to ARGB8888 by setting the A
    * channel to 1.0 at the end. Also trivially ARGB2101010 to XRGB2101010,
    * but not XRGB2101010 to ARGB2101010 yet.
    */
   if (!intel_miptree_blit_compatible_formats(src_format, dst_format)) {
      perf_debug("%s: Can't use hardware blitter from %s to %s, "
                 "falling back.\n", __func__,
                 _mesa_get_format_name(src_format),
                 _mesa_get_format_name(dst_format));
      return false;
   }

   /* The blitter has no idea about HiZ or fast color clears, so we need to
    * resolve the miptrees before we do anything.
    */
   intel_miptree_access_raw(brw, src_mt, src_level, src_slice, false);
   intel_miptree_access_raw(brw, dst_mt, dst_level, dst_slice, true);

   if (src_flip) {
      const unsigned h0 = src_mt->surf.phys_level0_sa.height;
      src_y = minify(h0, src_level - src_mt->first_level) - src_y - height;
   }

   if (dst_flip) {
      const unsigned h0 = dst_mt->surf.phys_level0_sa.height;
      dst_y = minify(h0, dst_level - dst_mt->first_level) - dst_y - height;
   }

   uint32_t src_image_x, src_image_y, dst_image_x, dst_image_y;
   intel_miptree_get_image_offset(src_mt, src_level, src_slice,
                                  &src_image_x, &src_image_y);
   intel_miptree_get_image_offset(dst_mt, dst_level, dst_slice,
                                  &dst_image_x, &dst_image_y);
   src_x += src_image_x;
   src_y += src_image_y;
   dst_x += dst_image_x;
   dst_y += dst_image_y;

   if (!emit_miptree_blit(brw, src_mt, src_x, src_y,
                          dst_mt, dst_x, dst_y, width, height,
                          src_flip != dst_flip, logicop)) {
      return false;
   }

   /* XXX This could be done in a single pass using XY_FULL_MONO_PATTERN_BLT */
   if (_mesa_get_format_bits(src_format, GL_ALPHA_BITS) == 0 &&
       _mesa_get_format_bits(dst_format, GL_ALPHA_BITS) > 0) {
      intel_miptree_set_alpha_to_one(brw, dst_mt,
                                     dst_x, dst_y,
                                     width, height);
   }

   return true;
}
Esempio n. 13
0
/**
 * Convert the given color to a bitfield suitable for ORing into DWORD 7 of
 * SURFACE_STATE (DWORD 12-15 on SKL+).
 */
union isl_color_value
brw_meta_convert_fast_clear_color(const struct brw_context *brw,
                                  const struct intel_mipmap_tree *mt,
                                  const union gl_color_union *color)
{
   union isl_color_value override_color = {
      .u32 = {
         color->ui[0],
         color->ui[1],
         color->ui[2],
         color->ui[3],
      },
   };

   /* The sampler doesn't look at the format of the surface when the fast
    * clear color is used so we need to implement luminance, intensity and
    * missing components manually.
    */
   switch (_mesa_get_format_base_format(mt->format)) {
   case GL_INTENSITY:
      override_color.u32[3] = override_color.u32[0];
      /* flow through */
   case GL_LUMINANCE:
   case GL_LUMINANCE_ALPHA:
      override_color.u32[1] = override_color.u32[0];
      override_color.u32[2] = override_color.u32[0];
      break;
   default:
      for (int i = 0; i < 3; i++) {
         if (!_mesa_format_has_color_component(mt->format, i))
            override_color.u32[i] = 0;
      }
      break;
   }

   switch (_mesa_get_format_datatype(mt->format)) {
   case GL_UNSIGNED_NORMALIZED:
      for (int i = 0; i < 4; i++)
         override_color.f32[i] = CLAMP(override_color.f32[i], 0.0f, 1.0f);
      break;

   case GL_SIGNED_NORMALIZED:
      for (int i = 0; i < 4; i++)
         override_color.f32[i] = CLAMP(override_color.f32[i], -1.0f, 1.0f);
      break;

   case GL_UNSIGNED_INT:
      for (int i = 0; i < 4; i++) {
         unsigned bits = _mesa_get_format_bits(mt->format, GL_RED_BITS + i);
         if (bits < 32) {
            uint32_t max = (1u << bits) - 1;
            override_color.u32[i] = MIN2(override_color.u32[i], max);
         }
      }
      break;

   case GL_INT:
      for (int i = 0; i < 4; i++) {
         unsigned bits = _mesa_get_format_bits(mt->format, GL_RED_BITS + i);
         if (bits < 32) {
            int32_t max = (1 << (bits - 1)) - 1;
            int32_t min = -(1 << (bits - 1));
            override_color.i32[i] = CLAMP(override_color.i32[i], min, max);
         }
      }
      break;

   case GL_FLOAT:
      if (!_mesa_is_format_signed(mt->format)) {
         for (int i = 0; i < 4; i++)
            override_color.f32[i] = MAX2(override_color.f32[i], 0.0f);
      }
      break;
   }

   if (!_mesa_format_has_color_component(mt->format, 3)) {
      if (_mesa_is_format_integer_color(mt->format))
         override_color.u32[3] = 1;
      else
         override_color.f32[3] = 1.0f;
   }

   /* Handle linear to SRGB conversion */
   if (brw->ctx.Color.sRGBEnabled &&
       _mesa_get_srgb_format_linear(mt->format) != mt->format) {
      for (int i = 0; i < 3; i++) {
         override_color.f32[i] =
            util_format_linear_to_srgb_float(override_color.f32[i]);
      }
   }

   return override_color;
}
Esempio n. 14
0
/**
 * The glGet queries of the framebuffer red/green/blue size, stencil size,
 * etc. are satisfied by the fields of ctx->DrawBuffer->Visual.  These can
 * change depending on the renderbuffer bindings.  This function updates
 * the given framebuffer's Visual from the current renderbuffer bindings.
 *
 * This may apply to user-created framebuffers or window system framebuffers.
 *
 * Also note: ctx->DrawBuffer->Visual.depthBits might not equal
 * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits.
 * The former one is used to convert floating point depth values into
 * integer Z values.
 */
void
_mesa_update_framebuffer_visual(struct gl_context *ctx,
				struct gl_framebuffer *fb)
{
   GLuint i;

   memset(&fb->Visual, 0, sizeof(fb->Visual));
   fb->Visual.rgbMode = GL_TRUE; /* assume this */

#if 0 /* this _might_ be needed */
   if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      /* leave visual fields zero'd */
      return;
   }
#endif

   /* find first RGB renderbuffer */
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
         const gl_format fmt = rb->Format;

         if (_mesa_is_legal_color_format(ctx, baseFormat)) {
            fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
            fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
            fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
            fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
            fb->Visual.rgbBits = fb->Visual.redBits
               + fb->Visual.greenBits + fb->Visual.blueBits;
            fb->Visual.samples = rb->NumSamples;
            fb->Visual.sampleBuffers = rb->NumSamples > 0 ? 1 : 0;
            if (_mesa_get_format_color_encoding(fmt) == GL_SRGB)
                fb->Visual.sRGBCapable = ctx->Const.sRGBCapable;
            break;
         }
      }
   }

   fb->Visual.floatMode = GL_FALSE;
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         const gl_format fmt = rb->Format;

         if (_mesa_get_format_datatype(fmt) == GL_FLOAT) {
            fb->Visual.floatMode = GL_TRUE;
            break;
         }
      }
   }

   if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_DEPTH].Renderbuffer;
      const gl_format fmt = rb->Format;
      fb->Visual.haveDepthBuffer = GL_TRUE;
      fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS);
   }

   if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_STENCIL].Renderbuffer;
      const gl_format fmt = rb->Format;
      fb->Visual.haveStencilBuffer = GL_TRUE;
      fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS);
   }

   if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_ACCUM].Renderbuffer;
      const gl_format fmt = rb->Format;
      fb->Visual.haveAccumBuffer = GL_TRUE;
      fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
      fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
      fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
      fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
   }

   compute_depth_max(fb);
}
Esempio n. 15
0
bool
brw_blorp_copytexsubimage(struct brw_context *brw,
                          struct gl_renderbuffer *src_rb,
                          struct gl_texture_image *dst_image,
                          int slice,
                          int srcX0, int srcY0,
                          int dstX0, int dstY0,
                          int width, int height)
{
   struct gl_context *ctx = &brw->ctx;
   struct intel_renderbuffer *src_irb = intel_renderbuffer(src_rb);
   struct intel_texture_image *intel_image = intel_texture_image(dst_image);

   /* No pixel transfer operations (zoom, bias, mapping), just a blit */
   if (brw->ctx._ImageTransferState)
      return false;

   /* Sync up the state of window system buffers.  We need to do this before
    * we go looking at the src renderbuffer's miptree.
    */
   intel_prepare_render(brw);

   struct intel_mipmap_tree *src_mt = src_irb->mt;
   struct intel_mipmap_tree *dst_mt = intel_image->mt;

   /* There is support for only up to eight samples. */
   if (src_mt->num_samples > 8 || dst_mt->num_samples > 8)
      return false;

   /* BLORP is only supported from Gen6 onwards. */
   if (brw->gen < 6)
      return false;

   if (_mesa_get_format_base_format(src_rb->Format) !=
       _mesa_get_format_base_format(dst_image->TexFormat)) {
      return false;
   }

   /* We can't handle format conversions between Z24 and other formats since
    * we have to lie about the surface format.  See the comments in
    * brw_blorp_surface_info::set().
    */
   if ((src_mt->format == MESA_FORMAT_Z24_UNORM_X8_UINT) !=
       (dst_mt->format == MESA_FORMAT_Z24_UNORM_X8_UINT)) {
      return false;
   }

   if (!brw->format_supported_as_render_target[dst_image->TexFormat])
      return false;

   /* Source clipping shouldn't be necessary, since copytexsubimage (in
    * src/mesa/main/teximage.c) calls _mesa_clip_copytexsubimage() which
    * takes care of it.
    *
    * Destination clipping shouldn't be necessary since the restrictions on
    * glCopyTexSubImage prevent the user from specifying a destination rectangle
    * that falls outside the bounds of the destination texture.
    * See error_check_subtexture_dimensions().
    */

   int srcY1 = srcY0 + height;
   int srcX1 = srcX0 + width;
   int dstX1 = dstX0 + width;
   int dstY1 = dstY0 + height;

   /* Account for the fact that in the system framebuffer, the origin is at
    * the lower left.
    */
   bool mirror_y = false;
   if (_mesa_is_winsys_fbo(ctx->ReadBuffer)) {
      GLint tmp = src_rb->Height - srcY0;
      srcY0 = src_rb->Height - srcY1;
      srcY1 = tmp;
      mirror_y = true;
   }

   /* Account for face selection and texture view MinLayer */
   int dst_slice = slice + dst_image->TexObject->MinLayer + dst_image->Face;
   int dst_level = dst_image->Level + dst_image->TexObject->MinLevel;

   brw_blorp_blit_miptrees(brw,
                           src_mt, src_irb->mt_level, src_irb->mt_layer,
                           src_rb->Format, blorp_get_texture_swizzle(src_irb),
                           dst_mt, dst_level, dst_slice,
                           dst_image->TexFormat,
                           srcX0, srcY0, srcX1, srcY1,
                           dstX0, dstY0, dstX1, dstY1,
                           GL_NEAREST, false, mirror_y,
                           false, false);

   /* If we're copying to a packed depth stencil texture and the source
    * framebuffer has separate stencil, we need to also copy the stencil data
    * over.
    */
   src_rb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
   if (_mesa_get_format_bits(dst_image->TexFormat, GL_STENCIL_BITS) > 0 &&
       src_rb != NULL) {
      src_irb = intel_renderbuffer(src_rb);
      src_mt = src_irb->mt;

      if (src_mt->stencil_mt)
         src_mt = src_mt->stencil_mt;
      if (dst_mt->stencil_mt)
         dst_mt = dst_mt->stencil_mt;

      if (src_mt != dst_mt) {
         brw_blorp_blit_miptrees(brw,
                                 src_mt, src_irb->mt_level, src_irb->mt_layer,
                                 src_mt->format,
                                 blorp_get_texture_swizzle(src_irb),
                                 dst_mt, dst_level, dst_slice,
                                 dst_mt->format,
                                 srcX0, srcY0, srcX1, srcY1,
                                 dstX0, dstY0, dstX1, dstY1,
                                 GL_NEAREST, false, mirror_y,
                                 false, false);
      }
   }

   return true;
}
Esempio n. 16
0
/**
 * Clear the stencil buffer.  If the buffer is a combined
 * depth+stencil buffer, only the stencil bits will be touched.
 */
void
_swrast_clear_stencil_buffer(struct gl_context *ctx)
{
   struct gl_renderbuffer *rb =
      ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
   const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
   const GLuint writeMask = ctx->Stencil.WriteMask[0];
   const GLuint stencilMax = (1 << stencilBits) - 1;
   GLint x, y, width, height;
   GLubyte *map;
   GLint rowStride, i, j;
   GLbitfield mapMode;

   if (!rb || writeMask == 0)
      return;

   /* compute region to clear */
   x = ctx->DrawBuffer->_Xmin;
   y = ctx->DrawBuffer->_Ymin;
   width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
   height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;

   mapMode = GL_MAP_WRITE_BIT;
   if ((writeMask & stencilMax) != stencilMax) {
      /* need to mask stencil values */
      mapMode |= GL_MAP_READ_BIT;
   }
   else if (_mesa_get_format_bits(rb->Format, GL_DEPTH_BITS) > 0) {
      /* combined depth+stencil, need to mask Z values */
      mapMode |= GL_MAP_READ_BIT;
   }

   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height,
                               mapMode, &map, &rowStride);
   if (!map) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(stencil)");
      return;
   }

   switch (rb->Format) {
   case MESA_FORMAT_S8:
      {
         GLubyte clear = ctx->Stencil.Clear & writeMask & 0xff;
         GLubyte mask = (~writeMask) & 0xff;
         if (mask != 0) {
            /* masked clear */
            for (i = 0; i < height; i++) {
               GLubyte *row = map;
               for (j = 0; j < width; j++) {
                  row[j] = (row[j] & mask) | clear;
               }
               map += rowStride;
            }
         }
         else if (rowStride == width) {
            /* clear whole buffer */
            memset(map, clear, width * height);
         }
         else {
            /* clear scissored */
            for (i = 0; i < height; i++) {
               memset(map, clear, width);
               map += rowStride;
            }
         }
      }
      break;
   case MESA_FORMAT_S8_Z24:
      {
         GLuint clear = (ctx->Stencil.Clear & writeMask & 0xff) << 24;
         GLuint mask = (((~writeMask) & 0xff) << 24) | 0xffffff;
         for (i = 0; i < height; i++) {
            GLuint *row = (GLuint *) map;
            for (j = 0; j < width; j++) {
               row[j] = (row[j] & mask) | clear;
            }
            map += rowStride;
         }
      }
      break;
   case MESA_FORMAT_Z24_S8:
      {
         GLuint clear = ctx->Stencil.Clear & writeMask & 0xff;
         GLuint mask = 0xffffff00 | ((~writeMask) & 0xff);
         for (i = 0; i < height; i++) {
            GLuint *row = (GLuint *) map;
            for (j = 0; j < width; j++) {
               row[j] = (row[j] & mask) | clear;
            }
            map += rowStride;
         }
      }
      break;
   default:
      _mesa_problem(ctx, "Unexpected stencil buffer format %s"
                    " in _swrast_clear_stencil_buffer()",
                    _mesa_get_format_name(rb->Format));
   }

   ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
Esempio n. 17
0
File: blit.c Progetto: airlied/mesa
void
_mesa_blit_framebuffer(struct gl_context *ctx,
                       struct gl_framebuffer *readFb,
                       struct gl_framebuffer *drawFb,
                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                       GLbitfield mask, GLenum filter, const char *func)
{
   const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
                                     GL_DEPTH_BUFFER_BIT |
                                     GL_STENCIL_BUFFER_BIT);

   FLUSH_VERTICES(ctx, 0);

   /* Update completeness status of readFb and drawFb. */
   _mesa_update_framebuffer(ctx, readFb, drawFb);

   /* Make sure drawFb has an initialized bounding box. */
   _mesa_update_draw_buffer_bounds(ctx, drawFb);

   if (!readFb || !drawFb) {
      /* This will normally never happen but someday we may want to
       * support MakeCurrent() with no drawables.
       */
      return;
   }

   /* check for complete framebuffers */
   if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
       readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
                  "%s(incomplete draw/read buffers)", func);
      return;
   }

   if (!is_valid_blit_filter(ctx, filter)) {
      _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid filter %s)", func,
                  _mesa_enum_to_string(filter));
      return;
   }

   if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
        filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
        (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s: invalid samples)", func,
                  _mesa_enum_to_string(filter));
      return;
   }

   if (mask & ~legalMaskBits) {
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(invalid mask bits set)", func);
      return;
   }

   /* depth/stencil must be blitted with nearest filtering */
   if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
        && filter != GL_NEAREST) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
             "%s(depth/stencil requires GL_NEAREST filter)", func);
      return;
   }

   /* get color read/draw renderbuffers */
   if (mask & GL_COLOR_BUFFER_BIT) {
      const GLuint numColorDrawBuffers = drawFb->_NumColorDrawBuffers;
      const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
      const struct gl_renderbuffer *colorDrawRb = NULL;
      GLuint i;

      /* From the EXT_framebuffer_object spec:
       *
       *     "If a buffer is specified in <mask> and does not exist in both
       *     the read and draw framebuffers, the corresponding bit is silently
       *     ignored."
       */
      if (!colorReadRb || numColorDrawBuffers == 0) {
         mask &= ~GL_COLOR_BUFFER_BIT;
      }
      else {
         for (i = 0; i < numColorDrawBuffers; i++) {
            colorDrawRb = drawFb->_ColorDrawBuffers[i];
            if (!colorDrawRb)
               continue;

            /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
             * ES 3.0.1 spec says:
             *
             *     "If the source and destination buffers are identical, an
             *     INVALID_OPERATION error is generated. Different mipmap
             *     levels of a texture, different layers of a three-
             *     dimensional texture or two-dimensional array texture, and
             *     different faces of a cube map texture do not constitute
             *     identical buffers."
             */
            if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "%s(source and destination color "
                           "buffer cannot be the same)", func);
               return;
            }

            if (!compatible_color_datatypes(colorReadRb->Format,
                                            colorDrawRb->Format)) {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "%s(color buffer datatypes mismatch)", func);
               return;
            }
            /* extra checks for multisample copies... */
            if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
               /* color formats must match on GLES. This isn't checked on
                * desktop GL because the GL 4.4 spec was changed to allow it.
                * In the section entitled “Changes in the released
                * Specification of July 22, 2013” it says:
                *
                * “Relax BlitFramebuffer in section 18.3.1 so that format
                *  conversion can take place during multisample blits, since
                *  drivers already allow this and some apps depend on it.”
                */
               if (_mesa_is_gles(ctx) &&
                   !compatible_resolve_formats(colorReadRb, colorDrawRb)) {
                  _mesa_error(ctx, GL_INVALID_OPERATION,
                         "%s(bad src/dst multisample pixel formats)", func);
                  return;
               }
            }
         }
         if (filter != GL_NEAREST) {
            /* From EXT_framebuffer_multisample_blit_scaled specification:
             * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
             * if filter is not NEAREST and read buffer contains integer data."
             */
            GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
            if (type == GL_INT || type == GL_UNSIGNED_INT) {
               _mesa_error(ctx, GL_INVALID_OPERATION,
                           "%s(integer color type)", func);
               return;
            }
         }
      }
   }

   if (mask & GL_STENCIL_BUFFER_BIT) {
      struct gl_renderbuffer *readRb =
         readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
      struct gl_renderbuffer *drawRb =
         drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;

      /* From the EXT_framebuffer_object spec:
       *
       *     "If a buffer is specified in <mask> and does not exist in both
       *     the read and draw framebuffers, the corresponding bit is silently
       *     ignored."
       */
      if ((readRb == NULL) || (drawRb == NULL)) {
         mask &= ~GL_STENCIL_BUFFER_BIT;
      }
      else {
         int read_z_bits, draw_z_bits;

         if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "%s(source and destination stencil "
                        "buffer cannot be the same)", func);
            return;
         }

         if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
             _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
            /* There is no need to check the stencil datatype here, because
             * there is only one: GL_UNSIGNED_INT.
             */
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "%s(stencil attachment format mismatch)", func);
            return;
         }

         read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
         draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);

         /* If both buffers also have depth data, the depth formats must match
          * as well.  If one doesn't have depth, it's not blitted, so we should
          * ignore the depth format check.
          */
         if (read_z_bits > 0 && draw_z_bits > 0 &&
             (read_z_bits != draw_z_bits ||
              _mesa_get_format_datatype(readRb->Format) !=
              _mesa_get_format_datatype(drawRb->Format))) {

            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "%s(stencil attachment depth format mismatch)", func);
            return;
         }
      }
   }

   if (mask & GL_DEPTH_BUFFER_BIT) {
      struct gl_renderbuffer *readRb =
         readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
      struct gl_renderbuffer *drawRb =
         drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;

      /* From the EXT_framebuffer_object spec:
       *
       *     "If a buffer is specified in <mask> and does not exist in both
       *     the read and draw framebuffers, the corresponding bit is silently
       *     ignored."
       */
      if ((readRb == NULL) || (drawRb == NULL)) {
         mask &= ~GL_DEPTH_BUFFER_BIT;
      }
      else {
         int read_s_bit, draw_s_bit;

         if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "%s(source and destination depth "
                        "buffer cannot be the same)", func);
            return;
         }

         if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
              _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
             (_mesa_get_format_datatype(readRb->Format) !=
              _mesa_get_format_datatype(drawRb->Format))) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "%s(depth attachment format mismatch)", func);
            return;
         }

         read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
         draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);

         /* If both buffers also have stencil data, the stencil formats must
          * match as well.  If one doesn't have stencil, it's not blitted, so
          * we should ignore the stencil format check.
          */
         if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "%s(depth attachment stencil bits mismatch)", func);
            return;
         }
      }
   }


   if (_mesa_is_gles3(ctx)) {
      /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
       * 3.0.1 spec says:
       *
       *     "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero,
       *     an INVALID_OPERATION error is generated."
       */
      if (drawFb->Visual.samples > 0) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "%s(destination samples must be 0)", func);
         return;
      }

      /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
       * 3.0.1 spec says:
       *
       *     "If SAMPLE_BUFFERS for the read framebuffer is greater than zero,
       *     no copy is performed and an INVALID_OPERATION error is generated
       *     if the formats of the read and draw framebuffers are not
       *     identical or if the source and destination rectangles are not
       *     defined with the same (X0, Y0) and (X1, Y1) bounds."
       *
       * The format check was made above because desktop OpenGL has the same
       * requirement.
       */
      if (readFb->Visual.samples > 0
          && (srcX0 != dstX0 || srcY0 != dstY0
              || srcX1 != dstX1 || srcY1 != dstY1)) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "%s(bad src/dst multisample region)", func);
         return;
      }
   } else {
      if (readFb->Visual.samples > 0 &&
          drawFb->Visual.samples > 0 &&
          readFb->Visual.samples != drawFb->Visual.samples) {
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "%s(mismatched samples)", func);
         return;
      }

      /* extra checks for multisample copies... */
      if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) &&
          (filter == GL_NEAREST || filter == GL_LINEAR)) {
         /* src and dest region sizes must be the same */
         if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
             abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
            _mesa_error(ctx, GL_INVALID_OPERATION,
                        "%s(bad src/dst multisample region sizes)", func);
            return;
         }
      }
   }

   /* Debug code */
   if (DEBUG_BLIT) {
      const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
      const struct gl_renderbuffer *colorDrawRb = NULL;
      GLuint i = 0;

      printf("%s(%d, %d, %d, %d,  %d, %d, %d, %d,"
             " 0x%x, 0x%x)\n", func,
             srcX0, srcY0, srcX1, srcY1,
             dstX0, dstY0, dstX1, dstY1,
             mask, filter);

      if (colorReadRb) {
         const struct gl_renderbuffer_attachment *att;

         att = find_attachment(readFb, colorReadRb);
         printf("  Src FBO %u  RB %u (%dx%d)  ",
                readFb->Name, colorReadRb->Name,
                colorReadRb->Width, colorReadRb->Height);
         if (att && att->Texture) {
            printf("Tex %u  tgt 0x%x  level %u  face %u",
                   att->Texture->Name,
                   att->Texture->Target,
                   att->TextureLevel,
                   att->CubeMapFace);
         }
         printf("\n");

         /* Print all active color render buffers */
         for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
            colorDrawRb = drawFb->_ColorDrawBuffers[i];
            if (!colorDrawRb)
               continue;

            att = find_attachment(drawFb, colorDrawRb);
            printf("  Dst FBO %u  RB %u (%dx%d)  ",
                   drawFb->Name, colorDrawRb->Name,
                   colorDrawRb->Width, colorDrawRb->Height);
            if (att && att->Texture) {
               printf("Tex %u  tgt 0x%x  level %u  face %u",
                      att->Texture->Name,
                      att->Texture->Target,
                      att->TextureLevel,
                      att->CubeMapFace);
            }
            printf("\n");
         }
      }
   }

   if (!mask ||
       (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 ||
       (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) {
      return;
   }

   assert(ctx->Driver.BlitFramebuffer);
   ctx->Driver.BlitFramebuffer(ctx, readFb, drawFb,
                               srcX0, srcY0, srcX1, srcY1,
                               dstX0, dstY0, dstX1, dstY1,
                               mask, filter);
}
Esempio n. 18
0
/**
 * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels,
 * glCopyTex[Sub]Image, etc) exists.
 * \param format  a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA,
 *                GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL.
 * \return GL_TRUE if buffer exists, GL_FALSE otherwise
 */
GLboolean
_mesa_source_buffer_exists(struct gl_context *ctx, GLenum format)
{
   const struct gl_renderbuffer_attachment *att = ctx->ReadBuffer->Attachment;

   /* If we don't know the framebuffer status, update it now */
   if (ctx->ReadBuffer->_Status == 0) {
      _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
   }

   if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      return GL_FALSE;
   }

   switch (format) {
   case GL_COLOR:
   case GL_RED:
   case GL_GREEN:
   case GL_BLUE:
   case GL_ALPHA:
   case GL_LUMINANCE:
   case GL_LUMINANCE_ALPHA:
   case GL_INTENSITY:
   case GL_RG:
   case GL_RGB:
   case GL_BGR:
   case GL_RGBA:
   case GL_BGRA:
   case GL_ABGR_EXT:
   case GL_COLOR_INDEX:
   case GL_RED_INTEGER_EXT:
   case GL_GREEN_INTEGER_EXT:
   case GL_BLUE_INTEGER_EXT:
   case GL_ALPHA_INTEGER_EXT:
   case GL_RGB_INTEGER_EXT:
   case GL_RGBA_INTEGER_EXT:
   case GL_BGR_INTEGER_EXT:
   case GL_BGRA_INTEGER_EXT:
   case GL_LUMINANCE_INTEGER_EXT:
   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
      if (ctx->ReadBuffer->_ColorReadBuffer == NULL) {
         return GL_FALSE;
      }
      ASSERT(_mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_RED_BITS) > 0 ||
             _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_ALPHA_BITS) > 0 ||
             _mesa_get_format_bits(ctx->ReadBuffer->_ColorReadBuffer->Format, GL_INDEX_BITS) > 0);
      break;
   case GL_DEPTH:
   case GL_DEPTH_COMPONENT:
      if (!att[BUFFER_DEPTH].Renderbuffer) {
         return GL_FALSE;
      }
      /*ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);*/
      break;
   case GL_STENCIL:
   case GL_STENCIL_INDEX:
      if (!att[BUFFER_STENCIL].Renderbuffer) {
         return GL_FALSE;
      }
      /*ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);*/
      break;
   case GL_DEPTH_STENCIL_EXT:
      if (!att[BUFFER_DEPTH].Renderbuffer ||
          !att[BUFFER_STENCIL].Renderbuffer) {
         return GL_FALSE;
      }
      /*
      ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0);
      ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0);
      */
      break;
   default:
      _mesa_problem(ctx,
                    "Unexpected format 0x%x in _mesa_source_buffer_exists",
                    format);
      return GL_FALSE;
   }

   /* OK */
   return GL_TRUE;
}