Example #1
0
/**
 * Normally, we'll only _write_ texel data to a texture when we map it.
 * But if the user is providing depth or stencil values and the texture
 * image is a combined depth/stencil format, we'll actually read from
 * the texture buffer too (in order to insert the depth or stencil values.
 * \param userFormat  the user-provided image format
 * \param texFormat  the destination texture format
 */
static GLbitfield
get_read_write_mode(GLenum userFormat, mesa_format texFormat)
{
   if ((userFormat == GL_STENCIL_INDEX || userFormat == GL_DEPTH_COMPONENT)
       && _mesa_get_format_base_format(texFormat) == GL_DEPTH_STENCIL)
      return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
   else
      return GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
}
Example #2
0
/**
 * Return true if the conversion L=R+G+B is needed.
 */
static GLboolean
need_rgb_to_luminance_conversion(mesa_format texFormat, GLenum format)
{
   GLenum baseTexFormat = _mesa_get_format_base_format(texFormat);

   return (baseTexFormat == GL_RG ||
           baseTexFormat == GL_RGB ||
           baseTexFormat == GL_RGBA) &&
          (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA);
}
Example #3
0
GLboolean
_mesa_texstore_red_rgtc1(TEXSTORE_PARAMS)
{
   GLubyte *dst;
   const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
   const GLubyte *tempImage = NULL;
   int i, j;
   int numxpixels, numypixels;
   const GLubyte *srcaddr;
   GLubyte srcpixels[4][4];
   GLubyte *blkaddr;
   GLint dstRowDiff;
   ASSERT(dstFormat == MESA_FORMAT_RED_RGTC1 ||
          dstFormat == MESA_FORMAT_L_LATC1);
   ASSERT(dstXoffset % 4 == 0);
   ASSERT(dstYoffset % 4 == 0);
   ASSERT(dstZoffset % 4 == 0);
   (void) dstZoffset;


   tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
					  baseInternalFormat,
					  _mesa_get_format_base_format(dstFormat),
					  srcWidth, srcHeight, srcDepth,
					  srcFormat, srcType, srcAddr,
					  srcPacking);
   if (!tempImage)
      return GL_FALSE; /* out of memory */

   dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
                                        dstFormat,
                                        texWidth, dstSlices[0]);

   blkaddr = dst;
   dstRowDiff = dstRowStride >= (srcWidth * 2) ? dstRowStride - (((srcWidth + 3) & ~3) * 2) : 0;
   for (j = 0; j < srcHeight; j+=4) {
      if (srcHeight > j + 3) numypixels = 4;
      else numypixels = srcHeight - j;
      srcaddr = tempImage + j * srcWidth;
      for (i = 0; i < srcWidth; i += 4) {
	 if (srcWidth > i + 3) numxpixels = 4;
	 else numxpixels = srcWidth - i;
	 extractsrc_u(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 1);
	 unsigned_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
	 srcaddr += numxpixels;
	 blkaddr += 8;
      }
      blkaddr += dstRowDiff;
   }
   if (tempImage)
      free((void *) tempImage);

   return GL_TRUE;
}
Example #4
0
GLboolean
_mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
{
   GLbyte *dst;
   const GLfloat *tempImage = NULL;
   int i, j;
   int numxpixels, numypixels;
   const GLfloat *srcaddr;
   GLbyte srcpixels[4][4];
   GLbyte *blkaddr;
   GLint dstRowDiff;

   ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2_SNORM ||
          dstFormat == MESA_FORMAT_LA_LATC2_SNORM);

   tempImage = _mesa_make_temp_float_image(ctx, dims,
					   baseInternalFormat,
					   _mesa_get_format_base_format(dstFormat),
					   srcWidth, srcHeight, srcDepth,
					   srcFormat, srcType, srcAddr,
					   srcPacking, 0x0);
   if (!tempImage)
      return GL_FALSE; /* out of memory */

   dst = (GLbyte *) dstSlices[0];

   blkaddr = dst;
   dstRowDiff = dstRowStride >= (srcWidth * 4) ? dstRowStride - (((srcWidth + 3) & ~3) * 4) : 0;
   for (j = 0; j < srcHeight; j += 4) {
      if (srcHeight > j + 3) numypixels = 4;
      else numypixels = srcHeight - j;
      srcaddr = tempImage + j * srcWidth * 2;
      for (i = 0; i < srcWidth; i += 4) {
	 if (srcWidth > i + 3) numxpixels = 4;
	 else numxpixels = srcWidth - i;

	 extractsrc_s(srcpixels, srcaddr, srcWidth, numxpixels, numypixels, 2);
	 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
	 blkaddr += 8;

	 extractsrc_s(srcpixels, srcaddr + 1, srcWidth, numxpixels, numypixels, 2);
	 signed_encode_rgtc_ubyte(blkaddr, srcpixels, numxpixels, numypixels);
	 blkaddr += 8;

	 srcaddr += numxpixels * 2;

      }
      blkaddr += dstRowDiff;
   }

   free((void *) tempImage);

   return GL_TRUE;
}
Example #5
0
/**
 * Store user's image in rgb_dxt1 format.
 */
GLboolean
_mesa_texstore_rgb_dxt1(TEXSTORE_PARAMS)
{
   const GLchan *pixels;
   GLubyte *dst;
   const GLint texWidth = dstRowStride * 4 / 8; /* a bit of a hack */
   const GLchan *tempImage = NULL;

   ASSERT(dstFormat == MESA_FORMAT_RGB_DXT1 ||
          dstFormat == MESA_FORMAT_SRGB_DXT1);
   ASSERT(dstXoffset % 4 == 0);
   ASSERT(dstYoffset % 4 == 0);
   ASSERT(dstZoffset % 4 == 0);
   (void) dstZoffset;
   (void) dstImageOffsets;

   if (srcFormat != GL_RGB ||
       srcType != CHAN_TYPE ||
       ctx->_ImageTransferState ||
       srcPacking->SwapBytes) {
      /* convert image to RGB/GLchan */
      tempImage = _mesa_make_temp_chan_image(ctx, dims,
                                             baseInternalFormat,
                                             _mesa_get_format_base_format(dstFormat),
                                             srcWidth, srcHeight, srcDepth,
                                             srcFormat, srcType, srcAddr,
                                             srcPacking);
      if (!tempImage)
         return GL_FALSE; /* out of memory */
      pixels = tempImage;
      srcFormat = GL_RGB;
   }
   else {
      pixels = (const GLchan *) srcAddr;
   }

   dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
                                        dstFormat,
                                        texWidth, (GLubyte *) dstAddr);

   if (ext_tx_compress_dxtn) {
      (*ext_tx_compress_dxtn)(3, srcWidth, srcHeight, pixels,
                              GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
                              dst, dstRowStride);
   }
   else {
      _mesa_warning(ctx, "external dxt library not available: texstore_rgb_dxt1");
   }

   if (tempImage)
      free((void *) tempImage);

   return GL_TRUE;
}
Example #6
0
static unsigned int
intel_horizontal_texture_alignment_unit(struct brw_context *brw,
                                       gl_format format)
{
   /**
    * From the "Alignment Unit Size" section of various specs, namely:
    * - Gen3 Spec: "Memory Data Formats" Volume,         Section 1.20.1.4
    * - i965 and G45 PRMs:             Volume 1,         Section 6.17.3.4.
    * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4
    * - BSpec (for Ivybridge and slight variations in separate stencil)
    *
    * +----------------------------------------------------------------------+
    * |                                        | alignment unit width  ("i") |
    * | Surface Property                       |-----------------------------|
    * |                                        | 915 | 965 | ILK | SNB | IVB |
    * +----------------------------------------------------------------------+
    * | YUV 4:2:2 format                       |  8  |  4  |  4  |  4  |  4  |
    * | BC1-5 compressed format (DXTn/S3TC)    |  4  |  4  |  4  |  4  |  4  |
    * | FXT1  compressed format                |  8  |  8  |  8  |  8  |  8  |
    * | Depth Buffer (16-bit)                  |  4  |  4  |  4  |  4  |  8  |
    * | Depth Buffer (other)                   |  4  |  4  |  4  |  4  |  4  |
    * | Separate Stencil Buffer                | N/A | N/A |  8  |  8  |  8  |
    * | All Others                             |  4  |  4  |  4  |  4  |  4  |
    * +----------------------------------------------------------------------+
    *
    * On IVB+, non-special cases can be overridden by setting the SURFACE_STATE
    * "Surface Horizontal Alignment" field to HALIGN_4 or HALIGN_8.
    */
    if (_mesa_is_format_compressed(format)) {
       /* The hardware alignment requirements for compressed textures
        * happen to match the block boundaries.
        */
      unsigned int i, j;
      _mesa_get_format_block_size(format, &i, &j);
      return i;
    }

   if (format == MESA_FORMAT_S8)
      return 8;

   /* The depth alignment requirements in the table above are for rendering to
    * depth miplevels using the LOD control fields.  We don't use LOD control
    * fields, and instead use page offsets plus intra-tile x/y offsets, which
    * require that the low 3 bits are zero.  To reduce the number of x/y
    * offset workaround blits we do, align the X to 8, which depth texturing
    * can handle (sadly, it can't handle 8 in the Y direction).
    */
   if (brw->gen >= 7 &&
       _mesa_get_format_base_format(format) == GL_DEPTH_COMPONENT)
      return 8;

   return 4;
}
Example #7
0
/**
 * Return transfer op flags for this ReadPixels operation.
 */
GLbitfield
_mesa_get_readpixels_transfer_ops(const struct gl_context *ctx,
                                  mesa_format texFormat,
                                  GLenum format, GLenum type,
                                  GLboolean uses_blit)
{
   GLbitfield transferOps = ctx->_ImageTransferState;
   GLenum srcBaseFormat = _mesa_get_format_base_format(texFormat);
   GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);

   if (format == GL_DEPTH_COMPONENT ||
       format == GL_DEPTH_STENCIL ||
       format == GL_STENCIL_INDEX) {
      return 0;
   }

   /* Pixel transfer ops (scale, bias, table lookup) do not apply
    * to integer formats.
    */
   if (_mesa_is_enum_format_integer(format)) {
      return 0;
   }

   if (uses_blit) {
      /* For blit-based ReadPixels packing, the clamping is done automatically
       * unless the type is float. */
      if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) &&
          (type == GL_FLOAT || type == GL_HALF_FLOAT)) {
         transferOps |= IMAGE_CLAMP_BIT;
      }
   }
   else {
      /* For CPU-based ReadPixels packing, the clamping must always be done
       * for non-float types, */
      if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) ||
          (type != GL_FLOAT && type != GL_HALF_FLOAT)) {
         transferOps |= IMAGE_CLAMP_BIT;
      }
   }

   /* If the format is unsigned normalized, we can ignore clamping
    * because the values are already in the range [0,1] so it won't
    * have any effect anyway.
    */
   if (_mesa_get_format_datatype(texFormat) == GL_UNSIGNED_NORMALIZED &&
       !_mesa_need_rgb_to_luminance_conversion(srcBaseFormat, dstBaseFormat)) {
      transferOps &= ~IMAGE_CLAMP_BIT;
   }

   return transferOps;
}
Example #8
0
static void
intel_image_target_texture_2d(struct gl_context *ctx, GLenum target,
			      struct gl_texture_object *texObj,
			      struct gl_texture_image *texImage,
			      GLeglImageOES image_handle)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_mipmap_tree *mt;
   __DRIscreen *dri_screen = brw->screen->driScrnPriv;
   __DRIimage *image;

   image = dri_screen->dri2.image->lookupEGLImage(dri_screen, image_handle,
                                                  dri_screen->loaderPrivate);
   if (image == NULL)
      return;

   /* We support external textures only for EGLImages created with
    * EGL_EXT_image_dma_buf_import. We may lift that restriction in the future.
    */
   if (target == GL_TEXTURE_EXTERNAL_OES && !image->dma_buf_imported) {
      _mesa_error(ctx, GL_INVALID_OPERATION,
            "glEGLImageTargetTexture2DOES(external target is enabled only "
               "for images created with EGL_EXT_image_dma_buf_import");
      return;
   }

   /* Disallow depth/stencil textures: we don't have a way to pass the
    * separate stencil miptree of a GL_DEPTH_STENCIL texture through.
    */
   if (image->has_depthstencil) {
      _mesa_error(ctx, GL_INVALID_OPERATION, __func__);
      return;
   }

   if (image->planar_format && image->planar_format->nplanes > 0)
      mt = create_mt_for_planar_dri_image(brw, target, image);
   else
      mt = create_mt_for_dri_image(brw, target, image);
   if (mt == NULL)
      return;

   struct intel_texture_object *intel_texobj = intel_texture_object(texObj);
   intel_texobj->planar_format = image->planar_format;

   const GLenum internal_format =
      image->internal_format != 0 ?
      image->internal_format : _mesa_get_format_base_format(mt->format);
   intel_set_texture_image_mt(brw, texImage, internal_format, mt);
   intel_miptree_release(&mt);
}
Example #9
0
/**
 * Store user's image in rgba_dxt1 format.
 */
GLboolean
_mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS)
{
   const GLubyte *pixels;
   GLubyte *dst;
   const GLubyte *tempImage = NULL;

   ASSERT(dstFormat == MESA_FORMAT_RGBA_DXT1 ||
          dstFormat == MESA_FORMAT_SRGBA_DXT1);

   if (srcFormat != GL_RGBA ||
       srcType != GL_UNSIGNED_BYTE ||
       ctx->_ImageTransferState ||
       srcPacking->RowLength != srcWidth ||
       srcPacking->SwapBytes) {
      /* convert image to RGBA/GLubyte */
      tempImage = _mesa_make_temp_ubyte_image(ctx, dims,
                                             baseInternalFormat,
                                             _mesa_get_format_base_format(dstFormat),
                                             srcWidth, srcHeight, srcDepth,
                                             srcFormat, srcType, srcAddr,
                                             srcPacking);
      if (!tempImage)
         return GL_FALSE; /* out of memory */
      pixels = tempImage;
      srcFormat = GL_RGBA;
   }
   else {
      pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight,
                                     srcFormat, srcType, 0, 0);
   }

   dst = dstSlices[0];

   if (ext_tx_compress_dxtn) {
      (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels,
                              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
                              dst, dstRowStride);
   }
   else {
      _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt1");
   }

   free((void*) tempImage);

   return GL_TRUE;
}
Example #10
0
static void
intel_image_target_renderbuffer_storage(struct gl_context *ctx,
					struct gl_renderbuffer *rb,
					void *image_handle)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_renderbuffer *irb;
   __DRIscreen *screen;
   __DRIimage *image;

   screen = intel->intelScreen->driScrnPriv;
   image = screen->dri2.image->lookupEGLImage(screen, image_handle,
					      screen->loaderPrivate);
   if (image == NULL)
      return;

   /* __DRIimage is opaque to the core so it has to be checked here */
   switch (image->format) {
   case MESA_FORMAT_R8G8B8A8_UNORM:
      _mesa_error(&intel->ctx, GL_INVALID_OPERATION,
            "glEGLImageTargetRenderbufferStorage(unsupported image format");
      return;
      break;
   default:
      break;
   }

   irb = intel_renderbuffer(rb);
   intel_miptree_release(&irb->mt);
   irb->mt = intel_miptree_create_for_bo(intel,
                                         image->region->bo,
                                         image->format,
                                         image->offset,
                                         image->region->width,
                                         image->region->height,
                                         image->region->pitch,
                                         image->region->tiling);
   if (!irb->mt)
      return;

   rb->InternalFormat = image->internal_format;
   rb->Width = image->region->width;
   rb->Height = image->region->height;
   rb->Format = image->format;
   rb->_BaseFormat = _mesa_get_format_base_format(image->format);
   rb->NeedsFinishRenderTexture = true;
}
Example #11
0
static __DRIimage *
intel_allocate_image(int dri_format, void *loaderPrivate)
{
    __DRIimage *image;

    image = calloc(1, sizeof *image);
    if (image == NULL)
	return NULL;

    image->dri_format = dri_format;
    image->offset = 0;

    switch (dri_format) {
    case __DRI_IMAGE_FORMAT_RGB565:
       image->format = MESA_FORMAT_RGB565;
       break;
    case __DRI_IMAGE_FORMAT_XRGB8888:
       image->format = MESA_FORMAT_XRGB8888;
       break;
    case __DRI_IMAGE_FORMAT_ARGB8888:
       image->format = MESA_FORMAT_ARGB8888;
       break;
    case __DRI_IMAGE_FORMAT_ABGR8888:
       image->format = MESA_FORMAT_RGBA8888_REV;
       break;
    case __DRI_IMAGE_FORMAT_XBGR8888:
       image->format = MESA_FORMAT_RGBX8888_REV;
       break;
    case __DRI_IMAGE_FORMAT_R8:
       image->format = MESA_FORMAT_R8;
       break;
    case __DRI_IMAGE_FORMAT_GR88:
       image->format = MESA_FORMAT_GR88;
       break;
    case __DRI_IMAGE_FORMAT_NONE:
       image->format = MESA_FORMAT_NONE;
       break;
    default:
       free(image);
       return NULL;
    }

    image->internal_format = _mesa_get_format_base_format(image->format);
    image->data = loaderPrivate;

    return image;
}
Example #12
0
/**
 * Creates a new named renderbuffer that wraps the first slice
 * of an existing miptree.
 *
 * Clobbers the current renderbuffer binding (ctx->CurrentRenderbuffer).
 */
GLuint
brw_get_rb_for_slice(struct brw_context *brw,
                     struct intel_mipmap_tree *mt,
                     unsigned level, unsigned layer, bool flat)
{
   struct gl_context *ctx = &brw->ctx;
   GLuint rbo;
   struct gl_renderbuffer *rb;
   struct intel_renderbuffer *irb;

   /* This turns the GenRenderbuffers name into an actual struct
    * intel_renderbuffer.
    */
   _mesa_GenRenderbuffers(1, &rbo);
   _mesa_BindRenderbuffer(GL_RENDERBUFFER, rbo);

   rb = ctx->CurrentRenderbuffer;
   irb = intel_renderbuffer(rb);

   rb->Format = mt->format;
   rb->_BaseFormat = _mesa_get_format_base_format(mt->format);

   /* Program takes care of msaa and mip-level access manually for stencil.
    * The surface is also treated as Y-tiled instead of as W-tiled calling for
    * twice the width and half the height in dimensions.
    */
   if (flat) {
      const unsigned halign_stencil = 8;

      rb->NumSamples = 0;
      rb->Width = ALIGN(mt->total_width, halign_stencil) * 2;
      rb->Height = (mt->total_height / mt->physical_depth0) / 2;
      irb->mt_level = 0;
   } else {
      rb->NumSamples = mt->num_samples;
      rb->Width = mt->logical_width0;
      rb->Height = mt->logical_height0;
      irb->mt_level = level;
   }

   irb->mt_layer = layer;

   intel_miptree_reference(&irb->mt, mt);

   return rbo;
}
Example #13
0
static unsigned int
intel_vertical_texture_alignment_unit(struct brw_context *brw,
                                      gl_format format, bool multisampled)
{
   /**
    * From the "Alignment Unit Size" section of various specs, namely:
    * - Gen3 Spec: "Memory Data Formats" Volume,         Section 1.20.1.4
    * - i965 and G45 PRMs:             Volume 1,         Section 6.17.3.4.
    * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4
    * - BSpec (for Ivybridge and slight variations in separate stencil)
    *
    * +----------------------------------------------------------------------+
    * |                                        | alignment unit height ("j") |
    * | Surface Property                       |-----------------------------|
    * |                                        | 915 | 965 | ILK | SNB | IVB |
    * +----------------------------------------------------------------------+
    * | BC1-5 compressed format (DXTn/S3TC)    |  4  |  4  |  4  |  4  |  4  |
    * | FXT1  compressed format                |  4  |  4  |  4  |  4  |  4  |
    * | Depth Buffer                           |  2  |  2  |  2  |  4  |  4  |
    * | Separate Stencil Buffer                | N/A | N/A | N/A |  4  |  8  |
    * | Multisampled (4x or 8x) render target  | N/A | N/A | N/A |  4  |  4  |
    * | All Others                             |  2  |  2  |  2  |  2  |  2  |
    * +----------------------------------------------------------------------+
    *
    * On SNB+, non-special cases can be overridden by setting the SURFACE_STATE
    * "Surface Vertical Alignment" field to VALIGN_2 or VALIGN_4.
    */
   if (_mesa_is_format_compressed(format))
      return 4;

   if (format == MESA_FORMAT_S8)
      return brw->gen >= 7 ? 8 : 4;

   if (multisampled)
      return 4;

   GLenum base_format = _mesa_get_format_base_format(format);

   if (brw->gen >= 6 &&
       (base_format == GL_DEPTH_COMPONENT ||
	base_format == GL_DEPTH_STENCIL)) {
      return 4;
   }

   return 2;
}
Example #14
0
unsigned
brw_miptree_get_vertical_slice_pitch(const struct brw_context *brw,
                                     const struct intel_mipmap_tree *mt,
                                     unsigned level)
{
   if (brw->gen >= 9) {
      /* ALL_SLICES_AT_EACH_LOD isn't supported on Gen8+ but this code will
       * effectively end up with a packed qpitch anyway whenever
       * mt->first_level == mt->last_level.
       */
      assert(mt->array_layout != ALL_SLICES_AT_EACH_LOD);

      /* On Gen9 we can pick whatever qpitch we like as long as it's aligned
       * to the vertical alignment so we don't need to add any extra rows.
       */
      unsigned qpitch = mt->total_height;

      /* If the surface might be used as a stencil buffer or HiZ buffer then
       * it needs to be a multiple of 8.
       */
      const GLenum base_format = _mesa_get_format_base_format(mt->format);
      if (_mesa_is_depth_or_stencil_format(base_format))
         qpitch = ALIGN(qpitch, 8);

      /* 3D textures need to be aligned to the tile height. At this point we
       * don't know which tiling will be used so let's just align it to 32
       */
      if (mt->target == GL_TEXTURE_3D)
         qpitch = ALIGN(qpitch, 32);

      return qpitch;

   } else if (mt->target == GL_TEXTURE_3D ||
              (brw->gen == 4 && mt->target == GL_TEXTURE_CUBE_MAP) ||
              mt->array_layout == ALL_SLICES_AT_EACH_LOD) {
      return ALIGN_NPOT(minify(mt->physical_height0, level), mt->align_h);

   } else {
      const unsigned h0 = ALIGN_NPOT(mt->physical_height0, mt->align_h);
      const unsigned h1 = ALIGN_NPOT(minify(mt->physical_height0, 1), mt->align_h);

      return h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->align_h;
   }
}
Example #15
0
/**
 * Update the renderbuffer wrapper for rendering to a texture.
 * For example, update the width, height of the RB based on the texture size,
 * update the internal format info, etc.
 */
static void
update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
{
   struct gl_renderbuffer *rb = att->Renderbuffer;
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   struct swrast_texture_image *swImage;
   gl_format format;
   GLuint zOffset;

   (void) ctx;

   swImage = swrast_texture_image(_mesa_get_attachment_teximage(att));
   assert(swImage);

   format = swImage->Base.TexFormat;

   if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
      zOffset = 0;
   }
   else {
      zOffset = att->Zoffset;
   }

   rb->Width = swImage->Base.Width;
   rb->Height = swImage->Base.Height;
   rb->InternalFormat = swImage->Base.InternalFormat;
   rb->_BaseFormat = _mesa_get_format_base_format(format);

   /* Want to store linear values, not sRGB */
   rb->Format = _mesa_get_srgb_format_linear(format);
 
   /* Set the gl_renderbuffer::Buffer field so that mapping the buffer
    * succeeds.
     */
   if (att->Texture->Target == GL_TEXTURE_3D ||
       att->Texture->Target == GL_TEXTURE_2D_ARRAY_EXT) {
      srb->Buffer = swImage->Buffer +
         swImage->ImageOffsets[zOffset] * _mesa_get_format_bytes(format);
   }
   else {
      srb->Buffer = swImage->Buffer;
   }
}
Example #16
0
static bool
use_linear_1d_layout(struct brw_context *brw,
                     struct intel_mipmap_tree *mt)
{
   /* On Gen9+ the mipmap levels of a 1D surface are all laid out in a
    * horizontal line. This isn't done for depth/stencil buffers however
    * because those will be using a tiled layout
    */
   if (brw->gen >= 9 &&
       (mt->target == GL_TEXTURE_1D ||
        mt->target == GL_TEXTURE_1D_ARRAY)) {
      GLenum base_format = _mesa_get_format_base_format(mt->format);

      if (base_format != GL_DEPTH_COMPONENT &&
          base_format != GL_DEPTH_STENCIL &&
          base_format != GL_STENCIL_INDEX)
         return true;
   }

   return false;
}
Example #17
0
/**
 * Adaptor for fetching a float texel from a GLchan-valued texture.
 */
static void
fetch_texel_chan_to_float(const struct gl_texture_image *texImage,
                          GLint i, GLint j, GLint k, GLfloat *texelOut)
{
   GLchan temp[4];
   GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat);

   ASSERT(texImage->FetchTexelc);
   texImage->FetchTexelc(texImage, i, j, k, temp);
   if (baseFormat == GL_DEPTH_COMPONENT ||
       baseFormat == GL_DEPTH_STENCIL_EXT) {
      /* just one channel */
      texelOut[0] = CHAN_TO_FLOAT(temp[0]);
   }
   else {
      /* four channels */
      texelOut[0] = CHAN_TO_FLOAT(temp[0]);
      texelOut[1] = CHAN_TO_FLOAT(temp[1]);
      texelOut[2] = CHAN_TO_FLOAT(temp[2]);
      texelOut[3] = CHAN_TO_FLOAT(temp[3]);
   }
}
Example #18
0
GLboolean
_mesa_texstore_can_use_memcpy(struct gl_context *ctx,
                              GLenum baseInternalFormat, mesa_format dstFormat,
                              GLenum srcFormat, GLenum srcType,
                              const struct gl_pixelstore_attrib *srcPacking)
{
   if (_mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat)) {
      return GL_FALSE;
   }

   /* The base internal format and the base Mesa format must match. */
   if (baseInternalFormat != _mesa_get_format_base_format(dstFormat)) {
      return GL_FALSE;
   }

   /* The Mesa format must match the input format and type. */
   if (!_mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
                                             srcPacking->SwapBytes)) {
      return GL_FALSE;
   }

   /* Depth texture data needs clamping in following cases:
    * - Floating point dstFormat with signed srcType: clamp to [0.0, 1.0].
    * - Fixed point dstFormat with signed srcType: clamp to [0, 2^n -1].
    *
    * All the cases except one (float dstFormat with float srcType) are ruled
    * out by _mesa_format_matches_format_and_type() check above. Handle the
    * remaining case here.
    */
   if ((baseInternalFormat == GL_DEPTH_COMPONENT ||
        baseInternalFormat == GL_DEPTH_STENCIL) &&
       (srcType == GL_FLOAT ||
        srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV)) {
      return GL_FALSE;
   }

   return GL_TRUE;
}
static __DRIimage *
intel_allocate_image(int dri_format, void *loaderPrivate)
{
    __DRIimage *image;

    image = calloc(1, sizeof *image);
    if (image == NULL)
	return NULL;

    image->dri_format = dri_format;
    image->offset = 0;

    image->format = driImageFormatToGLFormat(dri_format);
    if (dri_format != __DRI_IMAGE_FORMAT_NONE &&
        image->format == MESA_FORMAT_NONE) {
       free(image);
       return NULL;
    }

    image->internal_format = _mesa_get_format_base_format(image->format);
    image->data = loaderPrivate;

    return image;
}
Example #20
0
void
brw_miptree_layout(struct brw_context *brw, struct intel_mipmap_tree *mt)
{
   bool multisampled = mt->num_samples > 1;
   bool gen6_hiz_or_stencil = false;

   if (brw->gen == 6 && mt->array_layout == ALL_SLICES_AT_EACH_LOD) {
      const GLenum base_format = _mesa_get_format_base_format(mt->format);
      gen6_hiz_or_stencil = _mesa_is_depth_or_stencil_format(base_format);
   }

   if (gen6_hiz_or_stencil) {
      /* On gen6, we use ALL_SLICES_AT_EACH_LOD for stencil/hiz because the
       * hardware doesn't support multiple mip levels on stencil/hiz.
       *
       * PRM Vol 2, Part 1, 7.5.3 Hierarchical Depth Buffer:
       * "The hierarchical depth buffer does not support the LOD field"
       *
       * PRM Vol 2, Part 1, 7.5.4.1 Separate Stencil Buffer:
       * "The stencil depth buffer does not support the LOD field"
       */
      if (mt->format == MESA_FORMAT_S_UINT8) {
         /* Stencil uses W tiling, so we force W tiling alignment for the
          * ALL_SLICES_AT_EACH_LOD miptree layout.
          */
         mt->align_w = 64;
         mt->align_h = 64;
      } else {
         /* Depth uses Y tiling, so we force need Y tiling alignment for the
          * ALL_SLICES_AT_EACH_LOD miptree layout.
          */
         mt->align_w = 128 / mt->cpp;
         mt->align_h = 32;
      }
   } else {
      mt->align_w = intel_horizontal_texture_alignment_unit(brw, mt);
      mt->align_h =
         intel_vertical_texture_alignment_unit(brw, mt->format, multisampled);
   }

   switch (mt->target) {
   case GL_TEXTURE_CUBE_MAP:
      if (brw->gen == 4) {
         /* Gen4 stores cube maps as 3D textures. */
         assert(mt->physical_depth0 == 6);
         brw_miptree_layout_texture_3d(brw, mt);
      } else {
         /* All other hardware stores cube maps as 2D arrays. */
	 brw_miptree_layout_texture_array(brw, mt);
      }
      break;

   case GL_TEXTURE_3D:
      if (brw->gen >= 9)
         brw_miptree_layout_texture_array(brw, mt);
      else
         brw_miptree_layout_texture_3d(brw, mt);
      break;

   case GL_TEXTURE_1D_ARRAY:
   case GL_TEXTURE_2D_ARRAY:
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
   case GL_TEXTURE_CUBE_MAP_ARRAY:
      brw_miptree_layout_texture_array(brw, mt);
      break;

   default:
      switch (mt->msaa_layout) {
      case INTEL_MSAA_LAYOUT_UMS:
      case INTEL_MSAA_LAYOUT_CMS:
         brw_miptree_layout_texture_array(brw, mt);
         break;
      case INTEL_MSAA_LAYOUT_NONE:
      case INTEL_MSAA_LAYOUT_IMS:
         if (use_linear_1d_layout(brw, mt))
            gen9_miptree_layout_1d(mt);
         else
            brw_miptree_layout_2d(mt);
         break;
      }
      break;
   }
   DBG("%s: %dx%dx%d\n", __FUNCTION__,
       mt->total_width, mt->total_height, mt->cpp);
}
Example #21
0
/**
 * This uses a blit to copy the read buffer to a texture format which matches
 * the format and type combo and then a fast read-back is done using memcpy.
 * We can do arbitrary X/Y/Z/W/0/1 swizzling here as long as there is
 * a format which matches the swizzling.
 *
 * If such a format isn't available, we fall back to _mesa_readpixels.
 *
 * NOTE: Some drivers use a blit to convert between tiled and linear
 *       texture layouts during texture uploads/downloads, so the blit
 *       we do here should be free in such cases.
 */
static void
st_readpixels(struct gl_context *ctx, GLint x, GLint y,
              GLsizei width, GLsizei height,
              GLenum format, GLenum type,
              const struct gl_pixelstore_attrib *pack,
              GLvoid *pixels)
{
   struct st_context *st = st_context(ctx);
   struct gl_renderbuffer *rb =
         _mesa_get_read_renderbuffer_for_format(ctx, format);
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   struct pipe_resource *src;
   struct pipe_resource *dst = NULL;
   struct pipe_resource dst_templ;
   enum pipe_format dst_format, src_format;
   struct pipe_blit_info blit;
   unsigned bind = PIPE_BIND_TRANSFER_READ;
   struct pipe_transfer *tex_xfer;
   ubyte *map = NULL;

   /* Validate state (to be sure we have up-to-date framebuffer surfaces)
    * and flush the bitmap cache prior to reading. */
   st_validate_state(st);
   st_flush_bitmap_cache(st);

   if (!st->prefer_blit_based_texture_transfer) {
      goto fallback;
   }

   /* This must be done after state validation. */
   src = strb->texture;

   /* XXX Fallback for depth-stencil formats due to an incomplete
    * stencil blit implementation in some drivers. */
   if (format == GL_DEPTH_STENCIL) {
      goto fallback;
   }

   /* We are creating a texture of the size of the region being read back.
    * Need to check for NPOT texture support. */
   if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES) &&
       (!util_is_power_of_two(width) ||
        !util_is_power_of_two(height))) {
      goto fallback;
   }

   /* If the base internal format and the texture format don't match, we have
    * to use the slow path. */
   if (rb->_BaseFormat !=
       _mesa_get_format_base_format(rb->Format)) {
      goto fallback;
   }

   /* See if the texture format already matches the format and type,
    * in which case the memcpy-based fast path will likely be used and
    * we don't have to blit. */
   if (_mesa_format_matches_format_and_type(rb->Format, format,
                                            type, pack->SwapBytes)) {
      goto fallback;
   }

   if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_TRUE)) {
      goto fallback;
   }

   /* Convert the source format to what is expected by ReadPixels
    * and see if it's supported. */
   src_format = util_format_linear(src->format);
   src_format = util_format_luminance_to_red(src_format);
   src_format = util_format_intensity_to_red(src_format);

   if (!src_format ||
       !screen->is_format_supported(screen, src_format, src->target,
                                    src->nr_samples,
                                    PIPE_BIND_SAMPLER_VIEW)) {
      goto fallback;
   }

   if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL)
      bind |= PIPE_BIND_DEPTH_STENCIL;
   else
      bind |= PIPE_BIND_RENDER_TARGET;

   /* Choose the destination format by finding the best match
    * for the format+type combo. */
   dst_format = st_choose_matching_format(screen, bind, format, type,
                                          pack->SwapBytes);
   if (dst_format == PIPE_FORMAT_NONE) {
      goto fallback;
   }

   /* create the destination texture */
   memset(&dst_templ, 0, sizeof(dst_templ));
   dst_templ.target = PIPE_TEXTURE_2D;
   dst_templ.format = dst_format;
   dst_templ.bind = bind;
   dst_templ.usage = PIPE_USAGE_STAGING;

   st_gl_texture_dims_to_pipe_dims(GL_TEXTURE_2D, width, height, 1,
                                   &dst_templ.width0, &dst_templ.height0,
                                   &dst_templ.depth0, &dst_templ.array_size);

   dst = screen->resource_create(screen, &dst_templ);
   if (!dst) {
      goto fallback;
   }

   memset(&blit, 0, sizeof(blit));
   blit.src.resource = src;
   blit.src.level = strb->surface->u.tex.level;
   blit.src.format = src_format;
   blit.dst.resource = dst;
   blit.dst.level = 0;
   blit.dst.format = dst->format;
   blit.src.box.x = x;
   blit.dst.box.x = 0;
   blit.src.box.y = y;
   blit.dst.box.y = 0;
   blit.src.box.z = strb->surface->u.tex.first_layer;
   blit.dst.box.z = 0;
   blit.src.box.width = blit.dst.box.width = width;
   blit.src.box.height = blit.dst.box.height = height;
   blit.src.box.depth = blit.dst.box.depth = 1;
   blit.mask = st_get_blit_mask(rb->_BaseFormat, format);
   blit.filter = PIPE_TEX_FILTER_NEAREST;
   blit.scissor_enable = FALSE;

   if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
      blit.src.box.y = rb->Height - blit.src.box.y;
      blit.src.box.height = -blit.src.box.height;
   }

   /* blit */
   st->pipe->blit(st->pipe, &blit);

   /* map resources */
   pixels = _mesa_map_pbo_dest(ctx, pack, pixels);

   map = pipe_transfer_map_3d(pipe, dst, 0, PIPE_TRANSFER_READ,
                              0, 0, 0, width, height, 1, &tex_xfer);
   if (!map) {
      _mesa_unmap_pbo_dest(ctx, pack);
      pipe_resource_reference(&dst, NULL);
      goto fallback;
   }

   /* memcpy data into a user buffer */
   {
      const uint bytesPerRow = width * util_format_get_blocksize(dst_format);
      GLuint row;

      for (row = 0; row < (unsigned) height; row++) {
         GLvoid *dest = _mesa_image_address3d(pack, pixels,
                                              width, height, format,
                                              type, 0, row, 0);
         memcpy(dest, map, bytesPerRow);
         map += tex_xfer->stride;
      }
   }

   pipe_transfer_unmap(pipe, tex_xfer);
   _mesa_unmap_pbo_dest(ctx, pack);
   pipe_resource_reference(&dst, NULL);
   return;

fallback:
   _mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels);
}
Example #22
0
/**
 * Allocate a renderbuffer for a an on-screen window (not a user-created
 * renderbuffer).  The window system code determines the format.
 */
struct gl_renderbuffer *
st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
{
   struct st_renderbuffer *strb;

   strb = ST_CALLOC_STRUCT(st_renderbuffer);
   if (!strb) {
      _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
      return NULL;
   }

   _mesa_init_renderbuffer(&strb->Base, 0);
   strb->Base.ClassID = 0x4242; /* just a unique value */
   strb->Base.NumSamples = samples;
   strb->Base.Format = st_pipe_format_to_mesa_format(format);
   strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format);
   strb->software = sw;

   switch (format) {
   case PIPE_FORMAT_R8G8B8A8_UNORM:
   case PIPE_FORMAT_B8G8R8A8_UNORM:
   case PIPE_FORMAT_A8R8G8B8_UNORM:
      strb->Base.InternalFormat = GL_RGBA8;
      break;
   case PIPE_FORMAT_R8G8B8X8_UNORM:
   case PIPE_FORMAT_B8G8R8X8_UNORM:
   case PIPE_FORMAT_X8R8G8B8_UNORM:
      strb->Base.InternalFormat = GL_RGB8;
      break;
   case PIPE_FORMAT_R8G8B8A8_SRGB:
   case PIPE_FORMAT_B8G8R8A8_SRGB:
   case PIPE_FORMAT_A8R8G8B8_SRGB:
      strb->Base.InternalFormat = GL_SRGB8_ALPHA8;
      break;
   case PIPE_FORMAT_R8G8B8X8_SRGB:
   case PIPE_FORMAT_B8G8R8X8_SRGB:
   case PIPE_FORMAT_X8R8G8B8_SRGB:
      strb->Base.InternalFormat = GL_SRGB8;
      break;
   case PIPE_FORMAT_B5G5R5A1_UNORM:
      strb->Base.InternalFormat = GL_RGB5_A1;
      break;
   case PIPE_FORMAT_B4G4R4A4_UNORM:
      strb->Base.InternalFormat = GL_RGBA4;
      break;
   case PIPE_FORMAT_B5G6R5_UNORM:
      strb->Base.InternalFormat = GL_RGB565;
      break;
   case PIPE_FORMAT_Z16_UNORM:
      strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
      break;
   case PIPE_FORMAT_Z32_UNORM:
      strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
      break;
   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
      strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
      break;
   case PIPE_FORMAT_Z24X8_UNORM:
   case PIPE_FORMAT_X8Z24_UNORM:
      strb->Base.InternalFormat = GL_DEPTH_COMPONENT24;
      break;
   case PIPE_FORMAT_S8_UINT:
      strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
      break;
   case PIPE_FORMAT_R16G16B16A16_SNORM:
      /* accum buffer */
      strb->Base.InternalFormat = GL_RGBA16_SNORM;
      break;
   case PIPE_FORMAT_R16G16B16A16_UNORM:
      strb->Base.InternalFormat = GL_RGBA16;
      break;
   case PIPE_FORMAT_R8_UNORM:
      strb->Base.InternalFormat = GL_R8;
      break;
   case PIPE_FORMAT_R8G8_UNORM:
      strb->Base.InternalFormat = GL_RG8;
      break;
   case PIPE_FORMAT_R16_UNORM:
      strb->Base.InternalFormat = GL_R16;
      break;
   case PIPE_FORMAT_R16G16_UNORM:
      strb->Base.InternalFormat = GL_RG16;
      break;
   case PIPE_FORMAT_R32G32B32A32_FLOAT:
      strb->Base.InternalFormat = GL_RGBA32F;
      break;
   case PIPE_FORMAT_R16G16B16A16_FLOAT:
      strb->Base.InternalFormat = GL_RGBA16F;
      break;
   default:
      _mesa_problem(NULL,
		    "Unexpected format %s in st_new_renderbuffer_fb",
                    util_format_name(format));
      free(strb);
      return NULL;
   }

   /* st-specific methods */
   strb->Base.Delete = st_renderbuffer_delete;
   strb->Base.AllocStorage = st_renderbuffer_alloc_storage;

   /* surface is allocated in st_renderbuffer_alloc_storage() */
   strb->surface = NULL;

   return &strb->Base;
}
/**
 * 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);
}
Example #24
0
File: meta.c Project: GYGit/reactos
/**
 * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions.
 * Have to be careful with locking and meta state for pixel transfer.
 */
static void
copy_tex_sub_image(struct gl_context *ctx,
                   GLuint dims,
                   struct gl_texture_image *texImage,
                   GLint xoffset, GLint yoffset, GLint zoffset,
                   struct gl_renderbuffer *rb,
                   GLint x, GLint y,
                   GLsizei width, GLsizei height)
{
   struct gl_texture_object *texObj = texImage->TexObject;
   const GLenum target = texObj->Target;
   GLenum format, type;
   GLint bpp;
   void *buf;

   /* Choose format/type for temporary image buffer */
   format = _mesa_get_format_base_format(texImage->TexFormat);
   if (format == GL_LUMINANCE ||
       format == GL_LUMINANCE_ALPHA ||
       format == GL_INTENSITY) {
      /* We don't want to use GL_LUMINANCE, GL_INTENSITY, etc. for the
       * temp image buffer because glReadPixels will do L=R+G+B which is
       * not what we want (should be L=R).
       */
      format = GL_RGBA;
   }

   if (_mesa_is_format_integer_color(texImage->TexFormat)) {
      _mesa_problem(ctx, "unsupported integer color copyteximage");
      return;
   }

   type = get_temp_image_type(ctx, format);
   bpp = _mesa_bytes_per_pixel(format, type);
   if (bpp <= 0) {
      _mesa_problem(ctx, "Bad bpp in meta copy_tex_sub_image()");
      return;
   }

   /*
    * Alloc image buffer (XXX could use a PBO)
    */
   buf = malloc(width * height * bpp);
   if (!buf) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage%uD", dims);
      return;
   }

   _mesa_unlock_texture(ctx, texObj); /* need to unlock first */

   /*
    * Read image from framebuffer (disable pixel transfer ops)
    */
   _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE | MESA_META_PIXEL_TRANSFER);
   ctx->Driver.ReadPixels(ctx, x, y, width, height,
			  format, type, &ctx->Pack, buf);
   _mesa_meta_end(ctx);

   _mesa_update_state(ctx); /* to update pixel transfer state */

   /*
    * Store texture data (with pixel transfer ops)
    */
   _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE);
   if (target == GL_TEXTURE_1D) {
      ctx->Driver.TexSubImage1D(ctx, texImage,
                                xoffset, width,
                                format, type, buf, &ctx->Unpack);
   }
   else {
      ctx->Driver.TexSubImage2D(ctx, texImage,
                                xoffset, yoffset, width, height,
                                format, type, buf, &ctx->Unpack);
   }
   _mesa_meta_end(ctx);

   _mesa_lock_texture(ctx, texObj); /* re-lock */

   free(buf);
}
Example #25
0
/*
 * Read R, G, B, A, RGB, L, or LA pixels.
 */
static void
read_rgba_pixels( struct gl_context *ctx,
                  GLint x, GLint y,
                  GLsizei width, GLsizei height,
                  GLenum format, GLenum type, GLvoid *pixels,
                  const struct gl_pixelstore_attrib *packing )
{
   GLbitfield transferOps;
   bool dst_is_integer, dst_is_luminance, needs_rebase;
   int dst_stride, src_stride, rb_stride;
   uint32_t dst_format, src_format;
   GLubyte *dst, *map;
   mesa_format rb_format;
   bool needs_rgba;
   void *rgba, *src;
   bool src_is_uint = false;
   uint8_t rebase_swizzle[4];
   struct gl_framebuffer *fb = ctx->ReadBuffer;
   struct gl_renderbuffer *rb = fb->_ColorReadBuffer;

   if (!rb)
      return;

   transferOps = get_readpixels_transfer_ops(ctx, rb->Format, format, type,
                                             GL_FALSE);
   /* Describe the dst format */
   dst_is_integer = _mesa_is_enum_format_integer(format);
   dst_stride = _mesa_image_row_stride(packing, width, format, type);
   dst_format = _mesa_format_from_format_and_type(format, type);
   dst_is_luminance = format == GL_LUMINANCE ||
                      format == GL_LUMINANCE_ALPHA ||
                      format == GL_LUMINANCE_INTEGER_EXT ||
                      format == GL_LUMINANCE_ALPHA_INTEGER_EXT;
   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
                                           format, type, 0, 0);

   /* Map the source render buffer */
   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
                               &map, &rb_stride);
   if (!map) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
      return;
   }
   rb_format = _mesa_get_srgb_format_linear(rb->Format);

   /*
    * Depending on the base formats involved in the conversion we might need to
    * rebase some values, so for these formats we compute a rebase swizzle.
    */
   if (rb->_BaseFormat == GL_LUMINANCE || rb->_BaseFormat == GL_INTENSITY) {
      needs_rebase = true;
      rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
   } else if (rb->_BaseFormat == GL_LUMINANCE_ALPHA) {
      needs_rebase = true;
      rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
      rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
      rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
      rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_W;
   } else if (_mesa_get_format_base_format(rb_format) != rb->_BaseFormat) {
      needs_rebase =
         _mesa_compute_rgba2base2rgba_component_mapping(rb->_BaseFormat,
                                                        rebase_swizzle);
   } else {
      needs_rebase = false;
   }

   /* Since _mesa_format_convert does not handle transferOps we need to handle
    * them before we call the function. This requires to convert to RGBA float
    * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
    * integer transferOps do not apply.
    *
    * Converting to luminance also requires converting to RGBA first, so we can
    * then compute luminance values as L=R+G+B. Notice that this is different
    * from GetTexImage, where we compute L=R.
    */
   assert(!transferOps || (transferOps && !dst_is_integer));

   needs_rgba = transferOps || dst_is_luminance;
   rgba = NULL;
   if (needs_rgba) {
      uint32_t rgba_format;
      int rgba_stride;
      bool need_convert;

      /* Convert to RGBA float or int/uint depending on the type of the src */
      if (dst_is_integer) {
         src_is_uint = _mesa_is_format_unsigned(rb_format);
         if (src_is_uint) {
            rgba_format = RGBA32_UINT;
            rgba_stride = width * 4 * sizeof(GLuint);
         } else {
            rgba_format = RGBA32_INT;
            rgba_stride = width * 4 * sizeof(GLint);
         }
      } else {
         rgba_format = RGBA32_FLOAT;
         rgba_stride = width * 4 * sizeof(GLfloat);
      }

      /* If we are lucky and the dst format matches the RGBA format we need to
       * convert to, then we can convert directly into the dst buffer and avoid
       * the final conversion/copy from the rgba buffer to the dst buffer.
       */
      if (dst_format == rgba_format) {
         need_convert = false;
         rgba = dst;
      } else {
         need_convert = true;
         rgba = malloc(height * rgba_stride);
         if (!rgba) {
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
            goto done_unmap;
         }
      }

      /* Convert to RGBA now */
      _mesa_format_convert(rgba, rgba_format, rgba_stride,
                           map, rb_format, rb_stride,
                           width, height,
                           needs_rebase ? rebase_swizzle : NULL);

      /* Handle transfer ops if necessary */
      if (transferOps)
         _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba);

      /* If we had to rebase, we have already taken care of that */
      needs_rebase = false;

      /* If we were lucky and our RGBA conversion matches the dst format, then
       * we are done.
       */
      if (!need_convert)
         goto done_swap;

      /* Otherwise, we need to convert from RGBA to dst next */
      src = rgba;
      src_format = rgba_format;
      src_stride = rgba_stride;
   } else {
      /* No RGBA conversion needed, convert directly to dst */
      src = map;
      src_format = rb_format;
      src_stride = rb_stride;
   }

   /* Do the conversion.
    *
    * If the dst format is Luminance, we need to do the conversion by computing
    * L=R+G+B values.
    */
   if (!dst_is_luminance) {
      _mesa_format_convert(dst, dst_format, dst_stride,
                           src, src_format, src_stride,
                           width, height,
                           needs_rebase ? rebase_swizzle : NULL);
   } else if (!dst_is_integer) {
      /* Compute float Luminance values from RGBA float */
      int luminance_stride, luminance_bytes;
      void *luminance;
      uint32_t luminance_format;

      luminance_stride = width * sizeof(GL_FLOAT);
      if (format == GL_LUMINANCE_ALPHA)
         luminance_stride *= 2;
      luminance_bytes = height * luminance_stride;
      luminance = malloc(luminance_bytes);
      if (!luminance) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
         free(rgba);
         goto done_unmap;
      }
      _mesa_pack_luminance_from_rgba_float(width * height, src,
                                           luminance, format, transferOps);

      /* Convert from Luminance float to dst (this will hadle type conversion
       * from float to the type of dst if necessary)
       */
      luminance_format = _mesa_format_from_format_and_type(format, GL_FLOAT);
      _mesa_format_convert(dst, dst_format, dst_stride,
                           luminance, luminance_format, luminance_stride,
                           width, height, NULL);
   } else {
      _mesa_pack_luminance_from_rgba_integer(width * height, src, !src_is_uint,
                                             dst, format, type);
   }

   if (rgba)
      free(rgba);

done_swap:
   /* Handle byte swapping if required */
   if (packing->SwapBytes) {
      int components = _mesa_components_in_format(format);
      GLint swapSize = _mesa_sizeof_packed_type(type);
      if (swapSize == 2)
         _mesa_swap2((GLushort *) dst, width * height * components);
      else if (swapSize == 4)
         _mesa_swap4((GLuint *) dst, width * height * components);
   }

done_unmap:
   ctx->Driver.UnmapRenderbuffer(ctx, rb);
}
Example #26
0
/** A partial implementation of glCopyImageSubData
 *
 * This is a partial implementation of glCopyImageSubData that works only
 * if both textures are uncompressed and the destination texture is
 * renderable.  It uses a slight abuse of a texture view (see make_view) to
 * turn the source texture into the destination texture type and then uses
 * _mesa_meta_BlitFramebuffers to do the copy.
 */
bool
_mesa_meta_CopyImageSubData_uncompressed(struct gl_context *ctx,
                                         struct gl_texture_image *src_tex_image,
                                         struct gl_renderbuffer *src_renderbuffer,
                                         int src_x, int src_y, int src_z,
                                         struct gl_texture_image *dst_tex_image,
                                         struct gl_renderbuffer *dst_renderbuffer,
                                         int dst_x, int dst_y, int dst_z,
                                         int src_width, int src_height)
{
   mesa_format src_format, dst_format;
   GLint src_internal_format, dst_internal_format;
   GLuint src_view_texture = 0;
   struct gl_texture_image *src_view_tex_image;
   struct gl_framebuffer *readFb;
   struct gl_framebuffer *drawFb = NULL;
   bool success = false;
   GLbitfield mask;
   GLenum status, attachment;

   if (src_renderbuffer) {
      src_format = src_renderbuffer->Format;
      src_internal_format = src_renderbuffer->InternalFormat;
   } else {
      assert(src_tex_image);
      src_format = src_tex_image->TexFormat;
      src_internal_format = src_tex_image->InternalFormat;
   }

   if (dst_renderbuffer) {
      dst_format = dst_renderbuffer->Format;
      dst_internal_format = dst_renderbuffer->InternalFormat;
   } else {
      assert(dst_tex_image);
      dst_format = dst_tex_image->TexFormat;
      dst_internal_format = dst_tex_image->InternalFormat;
   }

   if (_mesa_is_format_compressed(src_format))
      return false;

   if (_mesa_is_format_compressed(dst_format))
      return false;

   if (src_internal_format == dst_internal_format) {
      src_view_tex_image = src_tex_image;
   } else {
      if (src_renderbuffer) {
         assert(src_tex_image == NULL);
         src_tex_image = wrap_renderbuffer(ctx, src_renderbuffer);
      }
      if (!make_view(ctx, src_tex_image, &src_view_tex_image, &src_view_texture,
                     dst_internal_format))
         goto cleanup;
   }

   /* We really only need to stash the bound framebuffers and scissor. */
   _mesa_meta_begin(ctx, MESA_META_SCISSOR);

   readFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
   if (readFb == NULL)
      goto meta_end;

   drawFb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
   if (drawFb == NULL)
      goto meta_end;

   _mesa_bind_framebuffers(ctx, drawFb, readFb);

   switch (_mesa_get_format_base_format(src_format)) {
   case GL_DEPTH_COMPONENT:
      attachment = GL_DEPTH_ATTACHMENT;
      mask = GL_DEPTH_BUFFER_BIT;
      break;
   case GL_DEPTH_STENCIL:
      attachment = GL_DEPTH_STENCIL_ATTACHMENT;
      mask = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
      break;
   case GL_STENCIL_INDEX:
      attachment = GL_STENCIL_ATTACHMENT;
      mask = GL_STENCIL_BUFFER_BIT;
      break;
   default:
      attachment = GL_COLOR_ATTACHMENT0;
      mask = GL_COLOR_BUFFER_BIT;
      _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0);
      _mesa_ReadBuffer(GL_COLOR_ATTACHMENT0);
   }

   if (src_view_tex_image) {
      /* Prefer the tex image because, even if we have a renderbuffer, we may
       * have had to wrap it in a texture view.
       */
      _mesa_meta_framebuffer_texture_image(ctx, ctx->ReadBuffer, attachment,
                                           src_view_tex_image, src_z);
   } else {
      _mesa_framebuffer_renderbuffer(ctx, ctx->ReadBuffer, attachment,
                                     src_renderbuffer);
   }

   status = _mesa_check_framebuffer_status(ctx, ctx->ReadBuffer);
   if (status != GL_FRAMEBUFFER_COMPLETE)
      goto meta_end;

   if (dst_renderbuffer) {
      _mesa_framebuffer_renderbuffer(ctx, ctx->DrawBuffer, attachment,
                                     dst_renderbuffer);
   } else {
      _mesa_meta_framebuffer_texture_image(ctx, ctx->DrawBuffer, attachment,
                                           dst_tex_image, dst_z);
   }

   status = _mesa_check_framebuffer_status(ctx, ctx->DrawBuffer);
   if (status != GL_FRAMEBUFFER_COMPLETE)
      goto meta_end;

   /* Explicitly disable sRGB encoding */
   ctx->DrawBuffer->Visual.sRGBCapable = false;

   /* Since we've bound a new draw framebuffer, we need to update its
    * derived state -- _Xmin, etc -- for BlitFramebuffer's clipping to
    * be correct.
    */
   _mesa_update_state(ctx);

   /* We skip the core BlitFramebuffer checks for format consistency.
    * We have already created views to ensure that the texture formats
    * match.
    */
   ctx->Driver.BlitFramebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer,
                               src_x, src_y,
                               src_x + src_width, src_y + src_height,
                               dst_x, dst_y,
                               dst_x + src_width, dst_y + src_height,
                               mask, GL_NEAREST);

   success = true;

meta_end:
   _mesa_reference_framebuffer(&readFb, NULL);
   _mesa_reference_framebuffer(&drawFb, NULL);
   _mesa_meta_end(ctx);

cleanup:
   _mesa_DeleteTextures(1, &src_view_texture);

   /* If we got a renderbuffer source, delete the temporary texture */
   if (src_renderbuffer && src_tex_image)
      ctx->Driver.DeleteTexture(ctx, src_tex_image->TexObject);

   return success;
}
Example #27
0
/**
 * Allocate a new driRenderbuffer object.
 * Individual drivers are free to implement different versions of
 * this function.
 *
 * At this time, this function can only be used for window-system
 * renderbuffers, not user-created RBOs.
 *
 * \param format  Either GL_RGBA, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24,
 *                GL_DEPTH_COMPONENT32, or GL_STENCIL_INDEX8_EXT (for now).
 * \param addr  address in main memory of the buffer.  Probably a memory
 *              mapped region.
 * \param cpp  chars or bytes per pixel
 * \param offset  start of renderbuffer with respect to start of framebuffer
 * \param pitch   pixels per row
 */
driRenderbuffer *
driNewRenderbuffer(gl_format format, GLvoid *addr,
                   GLint cpp, GLint offset, GLint pitch,
                   __DRIdrawablePrivate *dPriv)
{
   driRenderbuffer *drb;

   assert(format == GL_RGBA ||
          format == GL_RGB5 ||
          format == GL_RGBA8 ||
          format == GL_DEPTH_COMPONENT16 ||
          format == GL_DEPTH_COMPONENT24 ||
          format == GL_DEPTH_COMPONENT32 ||
          format == GL_STENCIL_INDEX8_EXT);

   assert(cpp > 0);
   assert(pitch > 0);

   drb = _mesa_calloc(sizeof(driRenderbuffer));
   if (drb) {
      const GLuint name = 0;

      _mesa_init_renderbuffer(&drb->Base, name);

      /* Make sure we're using a null-valued GetPointer routine */
      assert(drb->Base.GetPointer(NULL, &drb->Base, 0, 0) == NULL);

      switch (format) {
      case MESA_FORMAT_ARGB8888:
         if (cpp == 2) {
            /* override format */
            format = MESA_FORMAT_RGB565;
         }
         drb->Base.DataType = GL_UNSIGNED_BYTE;
         break;
      case MESA_FORMAT_Z16:
         /* Depth */
         /* we always Get/Put 32-bit Z values */
         drb->Base.DataType = GL_UNSIGNED_INT;
         assert(cpp == 2);
         break;
      case MESA_FORMAT_Z32:
         /* Depth */
         /* we always Get/Put 32-bit Z values */
         drb->Base.DataType = GL_UNSIGNED_INT;
         assert(cpp == 4);
         break;
      case MESA_FORMAT_Z24_S8:
         drb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
         assert(cpp == 4);
         break;
      case MESA_FORMAT_S8_Z24:
         drb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
         assert(cpp == 4);
         break;
      case MESA_FORMAT_S8:
         /* Stencil */
         drb->Base.DataType = GL_UNSIGNED_BYTE;
         break;
      default:
         _mesa_problem(NULL, "Bad format 0x%x in driNewRenderbuffer", format);
         return NULL;
      }

      drb->Base.Format = format;

      drb->Base.InternalFormat =
      drb->Base._BaseFormat = _mesa_get_format_base_format(format);

      drb->Base.AllocStorage = driRenderbufferStorage;
      drb->Base.Delete = driDeleteRenderbuffer;

      drb->Base.Data = addr;

      /* DRI renderbuffer-specific fields: */
      drb->dPriv = dPriv;
      drb->offset = offset;
      drb->pitch = pitch;
      drb->cpp = cpp;

      /* may be changed if page flipping is active: */
      drb->flippedOffset = offset;
      drb->flippedPitch = pitch;
      drb->flippedData = addr;
   }
   return drb;
}
Example #28
0
static struct gl_texture_image *
create_texture_for_pbo(struct gl_context *ctx, bool create_pbo,
                       GLenum pbo_target, int width, int height,
                       GLenum format, GLenum type, const void *pixels,
                       const struct gl_pixelstore_attrib *packing,
                       GLuint *tmp_pbo, GLuint *tmp_tex)
{
   uint32_t pbo_format;
   GLenum internal_format;
   unsigned row_stride;
   struct gl_buffer_object *buffer_obj;
   struct gl_texture_object *tex_obj;
   struct gl_texture_image *tex_image;
   bool read_only;

   if (packing->SwapBytes ||
       packing->LsbFirst ||
       packing->Invert)
      return NULL;

   pbo_format = _mesa_format_from_format_and_type(format, type);
   if (_mesa_format_is_mesa_array_format(pbo_format))
      pbo_format = _mesa_format_from_array_format(pbo_format);

   if (!pbo_format || !ctx->TextureFormatSupported[pbo_format])
      return NULL;

   /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */
   pixels = _mesa_image_address3d(packing, pixels,
                                  width, height, format, type, 0, 0, 0);
   row_stride = _mesa_image_row_stride(packing, width, format, type);

   if (_mesa_is_bufferobj(packing->BufferObj)) {
      *tmp_pbo = 0;
      buffer_obj = packing->BufferObj;
   } else {
      bool is_pixel_pack = pbo_target == GL_PIXEL_PACK_BUFFER;

      assert(create_pbo);

      _mesa_GenBuffers(1, tmp_pbo);

      /* We are not doing this inside meta_begin/end.  However, we know the
       * client doesn't have the given target bound, so we can go ahead and
       * squash it.  We'll set it back when we're done.
       */
      _mesa_BindBuffer(pbo_target, *tmp_pbo);

      /* In case of GL_PIXEL_PACK_BUFFER, pass null pointer for the pixel
       * data to avoid unnecessary data copying in _mesa_BufferData().
       */
      if (is_pixel_pack)
         _mesa_BufferData(pbo_target, row_stride * height, NULL,
                          GL_STREAM_READ);
      else
         _mesa_BufferData(pbo_target, row_stride * height, pixels,
                          GL_STREAM_DRAW);

      buffer_obj = packing->BufferObj;
      pixels = NULL;

      _mesa_BindBuffer(pbo_target, 0);
   }

   _mesa_GenTextures(1, tmp_tex);
   tex_obj = _mesa_lookup_texture(ctx, *tmp_tex);
   _mesa_initialize_texture_object(ctx, tex_obj, *tmp_tex, GL_TEXTURE_2D);
   /* This must be set after _mesa_initialize_texture_object, not before. */
   tex_obj->Immutable = GL_TRUE;
   /* This is required for interactions with ARB_texture_view. */
   tex_obj->NumLayers = 1;

   internal_format = _mesa_get_format_base_format(pbo_format);

   tex_image = _mesa_get_tex_image(ctx, tex_obj, tex_obj->Target, 0);
   _mesa_init_teximage_fields(ctx, tex_image, width, height, 1,
                              0, internal_format, pbo_format);

   read_only = pbo_target == GL_PIXEL_UNPACK_BUFFER;
   if (!ctx->Driver.SetTextureStorageForBufferObject(ctx, tex_obj,
                                                     buffer_obj,
                                                     (intptr_t)pixels,
                                                     row_stride,
                                                     read_only)) {
      _mesa_DeleteTextures(1, tmp_tex);
      _mesa_DeleteBuffers(1, tmp_pbo);
      return NULL;
   }

   return tex_image;
}
Example #29
0
static unsigned int
intel_vertical_texture_alignment_unit(struct brw_context *brw,
                                      mesa_format format, bool multisampled)
{
   /**
    * From the "Alignment Unit Size" section of various specs, namely:
    * - Gen3 Spec: "Memory Data Formats" Volume,         Section 1.20.1.4
    * - i965 and G45 PRMs:             Volume 1,         Section 6.17.3.4.
    * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4
    * - BSpec (for Ivybridge and slight variations in separate stencil)
    *
    * +----------------------------------------------------------------------+
    * |                                        | alignment unit height ("j") |
    * | Surface Property                       |-----------------------------|
    * |                                        | 915 | 965 | ILK | SNB | IVB |
    * +----------------------------------------------------------------------+
    * | BC1-5 compressed format (DXTn/S3TC)    |  4  |  4  |  4  |  4  |  4  |
    * | FXT1  compressed format                |  4  |  4  |  4  |  4  |  4  |
    * | Depth Buffer                           |  2  |  2  |  2  |  4  |  4  |
    * | Separate Stencil Buffer                | N/A | N/A | N/A |  4  |  8  |
    * | Multisampled (4x or 8x) render target  | N/A | N/A | N/A |  4  |  4  |
    * | All Others                             |  2  |  2  |  2  |  *  |  *  |
    * +----------------------------------------------------------------------+
    *
    * Where "*" means either VALIGN_2 or VALIGN_4 depending on the setting of
    * the SURFACE_STATE "Surface Vertical Alignment" field.
    */
   if (_mesa_is_format_compressed(format))
      return 4;

   if (format == MESA_FORMAT_S_UINT8)
      return brw->gen >= 7 ? 8 : 4;

   /* Broadwell only supports VALIGN of 4, 8, and 16.  The BSpec says 4
    * should always be used, except for stencil buffers, which should be 8.
    */
   if (brw->gen >= 8)
      return 4;

   if (multisampled)
      return 4;

   GLenum base_format = _mesa_get_format_base_format(format);

   if (brw->gen >= 6 &&
       (base_format == GL_DEPTH_COMPONENT ||
	base_format == GL_DEPTH_STENCIL)) {
      return 4;
   }

   if (brw->gen == 7) {
      /* On Gen7, we prefer a vertical alignment of 4 when possible, because
       * that allows Y tiled render targets.
       *
       * From the Ivy Bridge PRM, Vol4 Part1 2.12.2.1 (SURFACE_STATE for most
       * messages), on p64, under the heading "Surface Vertical Alignment":
       *
       *     Value of 1 [VALIGN_4] is not supported for format YCRCB_NORMAL
       *     (0x182), YCRCB_SWAPUVY (0x183), YCRCB_SWAPUV (0x18f), YCRCB_SWAPY
       *     (0x190)
       *
       *     VALIGN_4 is not supported for surface format R32G32B32_FLOAT.
       */
      if (base_format == GL_YCBCR_MESA || format == MESA_FORMAT_RGB_FLOAT32)
         return 2;

      return 4;
   }

   return 2;
}
Example #30
0
void
brw_workaround_depthstencil_alignment(struct brw_context *brw,
                                      GLbitfield clear_mask)
{
   struct gl_context *ctx = &brw->ctx;
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   bool rebase_depth = false;
   bool rebase_stencil = false;
   struct intel_renderbuffer *depth_irb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
   struct intel_renderbuffer *stencil_irb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
   struct intel_mipmap_tree *depth_mt = NULL;
   struct intel_mipmap_tree *stencil_mt = get_stencil_miptree(stencil_irb);
   uint32_t tile_x = 0, tile_y = 0, stencil_tile_x = 0, stencil_tile_y = 0;
   uint32_t stencil_draw_x = 0, stencil_draw_y = 0;
   bool invalidate_depth = clear_mask & BUFFER_BIT_DEPTH;
   bool invalidate_stencil = clear_mask & BUFFER_BIT_STENCIL;

   if (depth_irb)
      depth_mt = depth_irb->mt;

   /* Initialize brw->depthstencil to 'nop' workaround state.
    */
   brw->depthstencil.tile_x = 0;
   brw->depthstencil.tile_y = 0;
   brw->depthstencil.depth_offset = 0;
   brw->depthstencil.stencil_offset = 0;
   brw->depthstencil.hiz_offset = 0;
   brw->depthstencil.depth_mt = NULL;
   brw->depthstencil.stencil_mt = NULL;
   if (depth_irb)
      brw->depthstencil.depth_mt = depth_mt;
   if (stencil_irb)
      brw->depthstencil.stencil_mt = get_stencil_miptree(stencil_irb);

   /* Gen7+ doesn't require the workarounds, since we always program the
    * surface state at the start of the whole surface.
    */
   if (brw->gen >= 7)
      return;

   /* Check if depth buffer is in depth/stencil format.  If so, then it's only
    * safe to invalidate it if we're also clearing stencil, and both depth_irb
    * and stencil_irb point to the same miptree.
    *
    * Note: it's not sufficient to check for the case where
    * _mesa_get_format_base_format(depth_mt->format) == GL_DEPTH_STENCIL,
    * because this fails to catch depth/stencil buffers on hardware that uses
    * separate stencil.  To catch that case, we check whether
    * depth_mt->stencil_mt is non-NULL.
    */
   if (depth_irb && invalidate_depth &&
       (_mesa_get_format_base_format(depth_mt->format) == GL_DEPTH_STENCIL ||
        depth_mt->stencil_mt)) {
      invalidate_depth = invalidate_stencil && depth_irb && stencil_irb
         && depth_irb->mt == stencil_irb->mt;
   }

   uint32_t tile_mask_x, tile_mask_y;
   brw_get_depthstencil_tile_masks(depth_mt,
                                   depth_mt ? depth_irb->mt_level : 0,
                                   depth_mt ? depth_irb->mt_layer : 0,
                                   stencil_mt,
                                   &tile_mask_x, &tile_mask_y);

   if (depth_irb) {
      tile_x = depth_irb->draw_x & tile_mask_x;
      tile_y = depth_irb->draw_y & tile_mask_y;

      /* According to the Sandy Bridge PRM, volume 2 part 1, pp326-327
       * (3DSTATE_DEPTH_BUFFER dw5), in the documentation for "Depth
       * Coordinate Offset X/Y":
       *
       *   "The 3 LSBs of both offsets must be zero to ensure correct
       *   alignment"
       */
      if (tile_x & 7 || tile_y & 7)
         rebase_depth = true;

      /* We didn't even have intra-tile offsets before g45. */
      if (!brw->has_surface_tile_offset) {
         if (tile_x || tile_y)
            rebase_depth = true;
      }

      if (rebase_depth) {
         perf_debug("HW workaround: blitting depth level %d to a temporary "
                    "to fix alignment (depth tile offset %d,%d)\n",
                    depth_irb->mt_level, tile_x, tile_y);
         intel_renderbuffer_move_to_temp(brw, depth_irb, invalidate_depth);
         /* In the case of stencil_irb being the same packed depth/stencil
          * texture but not the same rb, make it point at our rebased mt, too.
          */
         if (stencil_irb &&
             stencil_irb != depth_irb &&
             stencil_irb->mt == depth_mt) {
            intel_miptree_reference(&stencil_irb->mt, depth_irb->mt);
            intel_renderbuffer_set_draw_offset(stencil_irb);
         }

         stencil_mt = get_stencil_miptree(stencil_irb);

         tile_x = depth_irb->draw_x & tile_mask_x;
         tile_y = depth_irb->draw_y & tile_mask_y;
      }

      if (stencil_irb) {
         stencil_mt = get_stencil_miptree(stencil_irb);
         intel_miptree_get_image_offset(stencil_mt,
                                        stencil_irb->mt_level,
                                        stencil_irb->mt_layer,
                                        &stencil_draw_x, &stencil_draw_y);
         int stencil_tile_x = stencil_draw_x & tile_mask_x;
         int stencil_tile_y = stencil_draw_y & tile_mask_y;

         /* If stencil doesn't match depth, then we'll need to rebase stencil
          * as well.  (if we hadn't decided to rebase stencil before, the
          * post-stencil depth test will also rebase depth to try to match it
          * up).
          */
         if (tile_x != stencil_tile_x ||
             tile_y != stencil_tile_y) {
            rebase_stencil = true;
         }
      }
   }

   /* If we have (just) stencil, check it for ignored low bits as well */
   if (stencil_irb) {
      intel_miptree_get_image_offset(stencil_mt,
                                     stencil_irb->mt_level,
                                     stencil_irb->mt_layer,
                                     &stencil_draw_x, &stencil_draw_y);
      stencil_tile_x = stencil_draw_x & tile_mask_x;
      stencil_tile_y = stencil_draw_y & tile_mask_y;

      if (stencil_tile_x & 7 || stencil_tile_y & 7)
         rebase_stencil = true;

      if (!brw->has_surface_tile_offset) {
         if (stencil_tile_x || stencil_tile_y)
            rebase_stencil = true;
      }
   }

   if (rebase_stencil) {
      perf_debug("HW workaround: blitting stencil level %d to a temporary "
                 "to fix alignment (stencil tile offset %d,%d)\n",
                 stencil_irb->mt_level, stencil_tile_x, stencil_tile_y);

      intel_renderbuffer_move_to_temp(brw, stencil_irb, invalidate_stencil);
      stencil_mt = get_stencil_miptree(stencil_irb);

      intel_miptree_get_image_offset(stencil_mt,
                                     stencil_irb->mt_level,
                                     stencil_irb->mt_layer,
                                     &stencil_draw_x, &stencil_draw_y);
      stencil_tile_x = stencil_draw_x & tile_mask_x;
      stencil_tile_y = stencil_draw_y & tile_mask_y;

      if (depth_irb && depth_irb->mt == stencil_irb->mt) {
         intel_miptree_reference(&depth_irb->mt, stencil_irb->mt);
         intel_renderbuffer_set_draw_offset(depth_irb);
      } else if (depth_irb && !rebase_depth) {
         if (tile_x != stencil_tile_x ||
             tile_y != stencil_tile_y) {
            perf_debug("HW workaround: blitting depth level %d to a temporary "
                       "to match stencil level %d alignment (depth tile offset "
                       "%d,%d, stencil offset %d,%d)\n",
                       depth_irb->mt_level,
                       stencil_irb->mt_level,
                       tile_x, tile_y,
                       stencil_tile_x, stencil_tile_y);

            intel_renderbuffer_move_to_temp(brw, depth_irb, invalidate_depth);

            tile_x = depth_irb->draw_x & tile_mask_x;
            tile_y = depth_irb->draw_y & tile_mask_y;

            if (stencil_irb && stencil_irb->mt == depth_mt) {
               intel_miptree_reference(&stencil_irb->mt, depth_irb->mt);
               intel_renderbuffer_set_draw_offset(stencil_irb);
            }

            WARN_ONCE(stencil_tile_x != tile_x ||
                      stencil_tile_y != tile_y,
                      "Rebased stencil tile offset (%d,%d) doesn't match depth "
                      "tile offset (%d,%d).\n",
                      stencil_tile_x, stencil_tile_y,
                      tile_x, tile_y);
         }
      }
   }

   if (!depth_irb) {
      tile_x = stencil_tile_x;
      tile_y = stencil_tile_y;
   }

   /* While we just tried to get everything aligned, we may have failed to do
    * so in the case of rendering to array or 3D textures, where nonzero faces
    * will still have an offset post-rebase.  At least give an informative
    * warning.
    */
   WARN_ONCE((tile_x & 7) || (tile_y & 7),
             "Depth/stencil buffer needs alignment to 8-pixel boundaries.\n"
             "Truncating offset, bad rendering may occur.\n");
   tile_x &= ~7;
   tile_y &= ~7;

   /* Now, after rebasing, save off the new dephtstencil state so the hardware
    * packets can just dereference that without re-calculating tile offsets.
    */
   brw->depthstencil.tile_x = tile_x;
   brw->depthstencil.tile_y = tile_y;
   if (depth_irb) {
      depth_mt = depth_irb->mt;
      brw->depthstencil.depth_mt = depth_mt;
      brw->depthstencil.depth_offset =
         intel_region_get_aligned_offset(depth_mt->region,
                                         depth_irb->draw_x & ~tile_mask_x,
                                         depth_irb->draw_y & ~tile_mask_y,
                                         false);
      if (intel_renderbuffer_has_hiz(depth_irb)) {
         brw->depthstencil.hiz_offset =
            intel_region_get_aligned_offset(depth_mt->region,
                                            depth_irb->draw_x & ~tile_mask_x,
                                            (depth_irb->draw_y & ~tile_mask_y) /
                                            2,
                                            false);
      }
   }
   if (stencil_irb) {
      stencil_mt = get_stencil_miptree(stencil_irb);

      brw->depthstencil.stencil_mt = stencil_mt;
      if (stencil_mt->format == MESA_FORMAT_S_UINT8) {
         /* Note: we can't compute the stencil offset using
          * intel_region_get_aligned_offset(), because stencil_region claims
          * that the region is untiled even though it's W tiled.
          */
         brw->depthstencil.stencil_offset =
            (stencil_draw_y & ~tile_mask_y) * stencil_mt->region->pitch +
            (stencil_draw_x & ~tile_mask_x) * 64;
      }
   }
}