Beispiel #1
0
/**
 * Binds a region to a texture image, like it was uploaded by glTexImage2D().
 *
 * Used for GLX_EXT_texture_from_pixmap and EGL image extensions,
 */
static void
intel_set_texture_image_region(struct gl_context *ctx,
			       struct gl_texture_image *image,
			       struct intel_region *region,
			       GLenum target,
			       GLenum internalFormat,
			       gl_format format,
                               uint32_t offset,
                               GLuint width,
                               GLuint height,
                               GLuint tile_x,
                               GLuint tile_y)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_texture_image *intel_image = intel_texture_image(image);
   struct gl_texture_object *texobj = image->TexObject;
   struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
   bool has_surface_tile_offset = false;
   uint32_t draw_x, draw_y;

   _mesa_init_teximage_fields(&intel->ctx, image,
			      width, height, 1,
			      0, internalFormat, format);

   ctx->Driver.FreeTextureImageBuffer(ctx, image);

   intel_image->mt = intel_miptree_create_layout(intel, target, image->TexFormat,
                                                 0, 0,
                                                 width, height, 1,
                                                 true);
   if (intel_image->mt == NULL)
       return;
   intel_region_reference(&intel_image->mt->region, region);
   intel_image->mt->total_width = width;
   intel_image->mt->total_height = height;
   intel_image->mt->level[0].slice[0].x_offset = tile_x;
   intel_image->mt->level[0].slice[0].y_offset = tile_y;

   intel_miptree_get_tile_offsets(intel_image->mt, 0, 0, &draw_x, &draw_y);

   /* From "OES_EGL_image" error reporting. We report GL_INVALID_OPERATION
    * for EGL images from non-tile aligned sufaces in gen4 hw and earlier which has
    * trouble resolving back to destination image due to alignment issues.
    */
   if (!has_surface_tile_offset &&
       (draw_x != 0 || draw_y != 0)) {
      _mesa_error(ctx, GL_INVALID_OPERATION, __func__);
      intel_miptree_release(&intel_image->mt);
      return;
   }

   intel_texobj->needs_validate = true;

   intel_image->mt->offset = offset;
   assert(region->pitch % region->cpp == 0);
   intel_image->base.RowStride = region->pitch / region->cpp;

   /* Immediately validate the image to the object. */
   intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
}
Beispiel #2
0
void
intel_renderbuffer_move_to_temp(struct intel_context *intel,
                                struct intel_renderbuffer *irb)
{
   struct intel_texture_image *intel_image =
      intel_texture_image(irb->tex_image);
   struct intel_mipmap_tree *new_mt;
   int width, height, depth;

   intel_miptree_get_dimensions_for_image(irb->tex_image, &width, &height, &depth);

   new_mt = intel_miptree_create(intel, irb->tex_image->TexObject->Target,
                                 intel_image->base.Base.TexFormat,
                                 intel_image->base.Base.Level,
                                 intel_image->base.Base.Level,
                                 width, height, depth,
                                 true,
                                 irb->mt->num_samples,
                                 false /* force_y_tiling */);

   intel_miptree_copy_teximage(intel, intel_image, new_mt);
   intel_miptree_reference(&irb->mt, intel_image->mt);
   intel_renderbuffer_set_draw_offset(irb);
   intel_miptree_release(&new_mt);
}
Beispiel #3
0
static GLboolean
intel_alloc_texture_image_buffer(struct gl_context *ctx,
				 struct gl_texture_image *image)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_texture_image *intel_image = intel_texture_image(image);
   struct gl_texture_object *texobj = image->TexObject;
   struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
   GLuint slices;

   assert(image->Border == 0);

   /* Because the driver uses AllocTextureImageBuffer() internally, it may end
    * up mismatched with FreeTextureImageBuffer(), but that is safe to call
    * multiple times.
    */
   ctx->Driver.FreeTextureImageBuffer(ctx, image);

   /* Allocate the swrast_texture_image::ImageOffsets array now */
   switch (texobj->Target) {
   case GL_TEXTURE_3D:
   case GL_TEXTURE_2D_ARRAY:
      slices = image->Depth;
      break;
   case GL_TEXTURE_1D_ARRAY:
      slices = image->Height;
      break;
   default:
      slices = 1;
   }
   assert(!intel_image->base.ImageOffsets);
   intel_image->base.ImageOffsets = malloc(slices * sizeof(GLuint));

   _swrast_init_texture_image(image);

   if (intel_texobj->mt &&
       intel_miptree_match_image(intel_texobj->mt, image)) {
      intel_miptree_reference(&intel_image->mt, intel_texobj->mt);
      DBG("%s: alloc obj %p level %d %dx%dx%d using object's miptree %p\n",
          __FUNCTION__, texobj, image->Level,
          image->Width, image->Height, image->Depth, intel_texobj->mt);
   } else {
      intel_image->mt = intel_miptree_create_for_teximage(intel, intel_texobj,
                                                          intel_image,
                                                          false);

      /* Even if the object currently has a mipmap tree associated
       * with it, this one is a more likely candidate to represent the
       * whole object since our level didn't fit what was there
       * before, and any lower levels would fit into our miptree.
       */
      intel_miptree_reference(&intel_texobj->mt, intel_image->mt);

      DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n",
          __FUNCTION__, texobj, image->Level,
          image->Width, image->Height, image->Depth, intel_image->mt);
   }

   return true;
}
Beispiel #4
0
static GLboolean
intel_bind_renderbuffer_tex_image(struct gl_context *ctx,
                                  struct gl_renderbuffer *rb,
                                  struct gl_texture_image *image)
{
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
   struct intel_texture_image *intel_image = intel_texture_image(image);
   struct gl_texture_object *texobj = image->TexObject;
   struct intel_texture_object *intel_texobj = intel_texture_object(texobj);

   /* We can only handle RB allocated with AllocRenderbufferStorage, or
    * window-system renderbuffers.
    */
   assert(!rb->TexImage);

   if (!irb->mt)
      return false;

   _mesa_lock_texture(ctx, texobj);
   _mesa_init_teximage_fields(ctx, image,
			      rb->Width, rb->Height, 1,
			      0, rb->InternalFormat, rb->Format);
   image->NumSamples = rb->NumSamples;

   intel_miptree_reference(&intel_image->mt, irb->mt);

   /* Immediately validate the image to the object. */
   intel_miptree_reference(&intel_texobj->mt, intel_image->mt);

   intel_texobj->needs_validate = true;
   _mesa_unlock_texture(ctx, texobj);

   return true;
}
Beispiel #5
0
static void
intelFreeTextureImageData(struct gl_context * ctx, struct gl_texture_image *texImage)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_texture_image *intelImage = intel_texture_image(texImage);

   DBG("%s\n", __FUNCTION__);

   if (intelImage->mt) {
      intel_miptree_release(intel, &intelImage->mt);
   }

   if (texImage->Data) {
      _mesa_free_texmemory(texImage->Data);
      texImage->Data = NULL;
   }

   if (intelImage->depth_rb) {
      _mesa_reference_renderbuffer(&intelImage->depth_rb, NULL);
   }

   if (intelImage->stencil_rb) {
      _mesa_reference_renderbuffer(&intelImage->stencil_rb, NULL);
   }
}
Beispiel #6
0
/**
 * Binds a region to a texture image, like it was uploaded by glTexImage2D().
 *
 * Used for GLX_EXT_texture_from_pixmap and EGL image extensions,
 */
static void
intel_set_texture_image_region(struct gl_context *ctx,
			       struct gl_texture_image *image,
			       struct intel_region *region,
			       GLenum target,
			       GLenum internalFormat,
			       gl_format format)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_texture_image *intel_image = intel_texture_image(image);
   struct gl_texture_object *texobj = image->TexObject;
   struct intel_texture_object *intel_texobj = intel_texture_object(texobj);

   _mesa_init_teximage_fields(&intel->ctx, image,
			      region->width, region->height, 1,
			      0, internalFormat, format);

   ctx->Driver.FreeTextureImageBuffer(ctx, image);

   intel_image->mt = intel_miptree_create_for_region(intel, target,
						     image->TexFormat,
						     region);
   if (intel_image->mt == NULL)
       return;

   intel_image->base.RowStride = region->pitch;

   /* Immediately validate the image to the object. */
   intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
}
Beispiel #7
0
void
intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
                    GLenum internalFormat,
                    GLint x, GLint y, GLsizei width, GLint border)
{
   struct gl_texture_unit *texUnit =
      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
   struct gl_texture_object *texObj =
      _mesa_select_tex_object(ctx, texUnit, target);
   struct gl_texture_image *texImage =
      _mesa_select_tex_image(ctx, texObj, target, level);

   if (border)
      goto fail;

   /* Setup or redefine the texture object, mipmap tree and texture
    * image.  Don't populate yet.  
    */
   ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
                          width, border,
                          GL_RGBA, CHAN_TYPE, NULL,
                          &ctx->DefaultPacking, texObj, texImage);

   if (!do_copy_texsubimage(intel_context(ctx),
                            intel_texture_image(texImage),
                            internalFormat, 0, 0, x, y, width, 1))
      goto fail;

   return;

 fail:
   _swrast_copy_teximage1d(ctx, target, level, internalFormat, x, y,
                           width, border);
}
Beispiel #8
0
static void
intelCopyTexSubImage(struct gl_context *ctx, GLuint dims,
                     struct gl_texture_image *texImage,
                     GLint xoffset, GLint yoffset, GLint slice,
                     struct gl_renderbuffer *rb,
                     GLint x, GLint y,
                     GLsizei width, GLsizei height)
{
   struct brw_context *brw = brw_context(ctx);

   /* Try BLORP first.  It can handle almost everything. */
   if (brw_blorp_copytexsubimage(brw, rb, texImage, slice, x, y,
                                 xoffset, yoffset, width, height))
      return;

   /* Next, try the BLT engine. */
   if (intel_copy_texsubimage(brw,
                              intel_texture_image(texImage),
                              xoffset, yoffset, slice,
                              intel_renderbuffer(rb), x, y, width, height)) {
      return;
   }

   /* Finally, fall back to meta.  This will likely be slow. */
   perf_debug("%s - fallback to swrast\n", __func__);
   _mesa_meta_CopyTexSubImage(ctx, dims, texImage,
                              xoffset, yoffset, slice,
                              rb, x, y, width, height);
}
Beispiel #9
0
/**
 * Map texture memory/buffer into user space.
 * Note: the region of interest parameters are ignored here.
 * \param mode  bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
 * \param mapOut  returns start of mapping of region of interest
 * \param rowStrideOut  returns row stride in bytes
 */
static void
intel_map_texture_image(struct gl_context *ctx,
			struct gl_texture_image *tex_image,
			GLuint slice,
			GLuint x, GLuint y, GLuint w, GLuint h,
			GLbitfield mode,
			GLubyte **map,
			GLint *stride)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_texture_image *intel_image = intel_texture_image(tex_image);
   struct intel_mipmap_tree *mt = intel_image->mt;

   /* Our texture data is always stored in a miptree. */
   assert(mt);

   /* intel_miptree_map operates on a unified "slice" number that references the
    * cube face, since it's all just slices to the miptree code.
    */
   if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
      slice = tex_image->Face;

   intel_miptree_map(intel, mt, tex_image->Level, slice, x, y, w, h, mode,
		     (void **)map, stride);
}
Beispiel #10
0
/**
 * Generate new mipmap data from BASE+1 to BASE+p (the minimally-sized mipmap
 * level).
 *
 * The texture object's miptree must be mapped.
 *
 * It would be really nice if this was just called by Mesa whenever mipmaps
 * needed to be regenerated, rather than us having to remember to do so in
 * each texture image modification path.
 *
 * This function should also include an accelerated path.
 */
void
intel_generate_mipmap(GLcontext *ctx, GLenum target,
                      struct gl_texture_object *texObj)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_texture_object *intelObj = intel_texture_object(texObj);
   GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
   int face, i;

   _mesa_generate_mipmap(ctx, target, texObj);

   /* Update the level information in our private data in the new images, since
    * it didn't get set as part of a normal TexImage path.
    */
   for (face = 0; face < nr_faces; face++) {
      for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) {
         struct intel_texture_image *intelImage;

	 intelImage = intel_texture_image(texObj->Image[face][i]);
	 if (intelImage == NULL)
	    break;

	 intelImage->level = i;
	 intelImage->face = face;
	 /* Unreference the miptree to signal that the new Data is a bare
	  * pointer from mesa.
	  */
	 intel_miptree_release(intel, &intelImage->mt);
      }
   }
}
Beispiel #11
0
void
intel_tex_map_level_images(struct intel_context *intel,
			   struct intel_texture_object *intelObj,
			   int level)
{
   GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
   GLuint face;

   for (face = 0; face < nr_faces; face++) {
      struct intel_texture_image *intelImage =
	 intel_texture_image(intelObj->base.Image[face][level]);

      if (intelImage->mt) {
	 intelImage->base.Data =
	    intel_miptree_image_map(intel,
				    intelImage->mt,
				    intelImage->face,
				    intelImage->level,
				    &intelImage->base.RowStride,
				    intelImage->base.ImageOffsets);
	 /* convert stride to texels, not bytes */
	 intelImage->base.RowStride /= intelImage->mt->cpp;
	 /* intelImage->base.ImageStride /= intelImage->mt->cpp; */
      }
   }
}
Beispiel #12
0
/**
 * Can the image be pulled into a unified mipmap tree?  This mirrors
 * the completeness test in a lot of ways.
 *
 * Not sure whether I want to pass gl_texture_image here.
 */
GLboolean
intel_miptree_match_image(struct intel_mipmap_tree *mt,
                          struct gl_texture_image *image)
{
    GLboolean isCompressed = _mesa_is_format_compressed(image->TexFormat);
    struct intel_texture_image *intelImage = intel_texture_image(image);
    GLuint level = intelImage->level;

    /* Images with borders are never pulled into mipmap trees. */
    if (image->Border)
        return GL_FALSE;

    if (image->InternalFormat != mt->internal_format ||
            isCompressed != mt->compressed)
        return GL_FALSE;

    if (!isCompressed &&
            !mt->compressed &&
            _mesa_get_format_bytes(image->TexFormat) != mt->cpp)
        return GL_FALSE;

    /* Test image dimensions against the base level image adjusted for
     * minification.  This will also catch images not present in the
     * tree, changed targets, etc.
     */
    if (image->Width != mt->level[level].width ||
            image->Height != mt->level[level].height ||
            image->Depth != mt->level[level].depth)
        return GL_FALSE;

    return GL_TRUE;
}
Beispiel #13
0
/**
 * Map texture memory/buffer into user space.
 * Note: the region of interest parameters are ignored here.
 * \param mode  bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
 * \param mapOut  returns start of mapping of region of interest
 * \param rowStrideOut  returns row stride in bytes
 */
static void
intel_map_texture_image(struct gl_context *ctx,
			struct gl_texture_image *tex_image,
			GLuint slice,
			GLuint x, GLuint y, GLuint w, GLuint h,
			GLbitfield mode,
			GLubyte **map,
			GLint *stride)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_texture_image *intel_image = intel_texture_image(tex_image);
   struct intel_mipmap_tree *mt = intel_image->mt;

   /* Our texture data is always stored in a miptree. */
   assert(mt);

   /* Check that our caller wasn't confused about how to map a 1D texture. */
   assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY ||
	  h == 1);

   /* intel_miptree_map operates on a unified "slice" number that references the
    * cube face, since it's all just slices to the miptree code.
    */
   if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
      slice = tex_image->Face;

   intel_miptree_map(brw, mt,
                     tex_image->Level + tex_image->TexObject->MinLevel,
                     slice + tex_image->TexObject->MinLayer,
                     x, y, w, h, mode,
                     (void **)map, stride);
}
Beispiel #14
0
static void
intel_set_texture_image_mt(struct brw_context *brw,
                           struct gl_texture_image *image,
                           GLenum internal_format,
                           struct intel_mipmap_tree *mt)

{
   struct gl_texture_object *texobj = image->TexObject;
   struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
   struct intel_texture_image *intel_image = intel_texture_image(image);

   _mesa_init_teximage_fields(&brw->ctx, image,
			      mt->logical_width0, mt->logical_height0, 1,
			      0, internal_format, mt->format);

   brw->ctx.Driver.FreeTextureImageBuffer(&brw->ctx, image);

   intel_texobj->needs_validate = true;
   intel_image->base.RowStride = mt->pitch / mt->cpp;
   assert(mt->pitch % mt->cpp == 0);

   intel_miptree_reference(&intel_image->mt, mt);

   /* Immediately validate the image to the object. */
   intel_miptree_reference(&intel_texobj->mt, mt);
}
Beispiel #15
0
void
intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
                       GLint xoffset, GLint yoffset,
                       GLint x, GLint y, GLsizei width, GLsizei height)
{
   struct gl_texture_unit *texUnit =
      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
   struct gl_texture_object *texObj =
      _mesa_select_tex_object(ctx, texUnit, target);
   struct gl_texture_image *texImage =
      _mesa_select_tex_image(ctx, texObj, target, level);
   GLenum internalFormat = texImage->InternalFormat;


   /* Need to check texture is compatible with source format. 
    */

   if (!do_copy_texsubimage(intel_context(ctx),
                            intel_texture_image(texImage),
                            internalFormat,
                            xoffset, yoffset, x, y, width, height)) {

      DBG("%s - fallback to swrast\n", __FUNCTION__);

      _swrast_copy_texsubimage2d(ctx, target, level,
                                 xoffset, yoffset, x, y, width, height);
   }
}
Beispiel #16
0
void
intel_renderbuffer_move_to_temp(struct brw_context *brw,
                                struct intel_renderbuffer *irb,
                                bool invalidate)
{
   struct gl_renderbuffer *rb =&irb->Base.Base;
   struct intel_texture_image *intel_image = intel_texture_image(rb->TexImage);
   struct intel_mipmap_tree *new_mt;
   int width, height, depth;

   intel_miptree_get_dimensions_for_image(rb->TexImage, &width, &height, &depth);

   new_mt = intel_miptree_create(brw, rb->TexImage->TexObject->Target,
                                 intel_image->base.Base.TexFormat,
                                 intel_image->base.Base.Level,
                                 intel_image->base.Base.Level,
                                 width, height, depth,
                                 true,
                                 irb->mt->num_samples,
                                 INTEL_MIPTREE_TILING_ANY);

   if (brw_is_hiz_depth_format(brw, new_mt->format)) {
      intel_miptree_alloc_hiz(brw, new_mt);
   }

   intel_miptree_copy_teximage(brw, intel_image, new_mt, invalidate);

   intel_miptree_reference(&irb->mt, intel_image->mt);
   intel_renderbuffer_set_draw_offset(irb);
   intel_miptree_release(&new_mt);
}
Beispiel #17
0
static void
intelCopyTexSubImage(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 intel_context *intel = intel_context(ctx);
    if (dims != 3) {
#ifndef I915
        /* Try BLORP first.  It can handle almost everything. */
        if (brw_blorp_copytexsubimage(intel, rb, texImage, x, y,
                                      xoffset, yoffset, width, height))
            return;
#endif

        /* Next, try the BLT engine. */
        if (intel_copy_texsubimage(intel,
                                   intel_texture_image(texImage),
                                   xoffset, yoffset,
                                   intel_renderbuffer(rb), x, y, width, height))
            return;
    }

    /* Finally, fall back to meta.  This will likely be slow. */
    fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
    _mesa_meta_CopyTexSubImage(ctx, dims, texImage,
                               xoffset, yoffset, zoffset,
                               rb, x, y, width, height);
}
Beispiel #18
0
static bool
intel_set_texture_storage_for_buffer_object(struct gl_context *ctx,
                                            struct gl_texture_object *tex_obj,
                                            struct gl_buffer_object *buffer_obj,
                                            uint32_t buffer_offset,
                                            uint32_t row_stride,
                                            bool read_only)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_texture_object *intel_texobj = intel_texture_object(tex_obj);
   struct gl_texture_image *image = tex_obj->Image[0][0];
   struct intel_texture_image *intel_image = intel_texture_image(image);
   struct intel_buffer_object *intel_buffer_obj = intel_buffer_object(buffer_obj);

   if (!read_only) {
      /* Renderbuffers have the restriction that the buffer offset and
       * surface pitch must be a multiple of the element size.  If it's
       * not, we have to fail and fall back to software.
       */
      int cpp = _mesa_get_format_bytes(image->TexFormat);
      if (buffer_offset % cpp || row_stride % cpp) {
         perf_debug("Bad PBO alignment; fallback to CPU mapping\n");
         return false;
      }

      if (!brw->format_supported_as_render_target[image->TexFormat]) {
         perf_debug("Non-renderable PBO format; fallback to CPU mapping\n");
         return false;
      }
   }

   assert(intel_texobj->mt == NULL);

   drm_intel_bo *bo = intel_bufferobj_buffer(brw, intel_buffer_obj,
                                             buffer_offset,
                                             row_stride * image->Height);
   intel_texobj->mt =
      intel_miptree_create_for_bo(brw, bo,
                                  image->TexFormat,
                                  buffer_offset,
                                  image->Width, image->Height, image->Depth,
                                  row_stride,
                                  0);
   if (!intel_texobj->mt)
      return false;

   if (!_swrast_init_texture_image(image))
      return false;

   intel_miptree_reference(&intel_image->mt, intel_texobj->mt);

   /* The miptree is in a validated state, so no need to check later. */
   intel_texobj->needs_validate = false;
   intel_texobj->validated_first_level = 0;
   intel_texobj->validated_last_level = 0;
   intel_texobj->_Format = intel_texobj->mt->format;

   return true;
}
Beispiel #19
0
/**
 * ctx->Driver.AllocTextureStorage() handler.
 *
 * Compare this to _mesa_alloc_texture_storage, which would call into
 * intel_alloc_texture_image_buffer() above.
 */
static GLboolean
intel_alloc_texture_storage(struct gl_context *ctx,
                            struct gl_texture_object *texobj,
                            GLsizei levels, GLsizei width,
                            GLsizei height, GLsizei depth)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_texture_object *intel_texobj = intel_texture_object(texobj);
   struct gl_texture_image *first_image = texobj->Image[0][0];
   int num_samples = intel_quantize_num_samples(brw->intelScreen,
                                                first_image->NumSamples);
   const int numFaces = _mesa_num_tex_faces(texobj->Target);
   int face;
   int level;

   /* If the object's current miptree doesn't match what we need, make a new
    * one.
    */
   if (!intel_texobj->mt ||
       !intel_miptree_match_image(intel_texobj->mt, first_image) ||
       intel_texobj->mt->last_level != levels - 1) {
      intel_miptree_release(&intel_texobj->mt);
      intel_texobj->mt = intel_miptree_create(brw, texobj->Target,
                                              first_image->TexFormat,
                                              0, levels - 1,
                                              width, height, depth,
                                              false, /* expect_accelerated */
                                              num_samples,
                                              INTEL_MIPTREE_TILING_ANY,
                                              false);

      if (intel_texobj->mt == NULL) {
         return false;
      }
   }

   for (face = 0; face < numFaces; face++) {
      for (level = 0; level < levels; level++) {
         struct gl_texture_image *image = texobj->Image[face][level];
         struct intel_texture_image *intel_image = intel_texture_image(image);

         image->NumSamples = num_samples;

         _swrast_free_texture_image_buffer(ctx, image);
         if (!_swrast_init_texture_image(image))
            return false;

         intel_miptree_reference(&intel_image->mt, intel_texobj->mt);
      }
   }

   /* The miptree is in a validated state, so no need to check later. */
   intel_texobj->needs_validate = false;
   intel_texobj->validated_first_level = 0;
   intel_texobj->validated_last_level = levels - 1;
   intel_texobj->_Format = intel_texobj->mt->format;

   return true;
}
Beispiel #20
0
static GLboolean
intel_alloc_texture_image_buffer(struct gl_context *ctx,
				 struct gl_texture_image *image)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_texture_image *intel_image = intel_texture_image(image);
   struct gl_texture_object *texobj = image->TexObject;
   struct intel_texture_object *intel_texobj = intel_texture_object(texobj);

   assert(image->Border == 0);

   /* Quantize sample count */
   if (image->NumSamples) {
      image->NumSamples = intel_quantize_num_samples(brw->screen, image->NumSamples);
      if (!image->NumSamples)
         return false;
   }

   /* Because the driver uses AllocTextureImageBuffer() internally, it may end
    * up mismatched with FreeTextureImageBuffer(), but that is safe to call
    * multiple times.
    */
   ctx->Driver.FreeTextureImageBuffer(ctx, image);

   if (!_swrast_init_texture_image(image))
      return false;

   if (intel_texobj->mt &&
       intel_miptree_match_image(intel_texobj->mt, image)) {
      intel_miptree_reference(&intel_image->mt, intel_texobj->mt);
      DBG("%s: alloc obj %p level %d %dx%dx%d using object's miptree %p\n",
          __func__, texobj, image->Level,
          image->Width, image->Height, image->Depth, intel_texobj->mt);
   } else {
      intel_image->mt = intel_miptree_create_for_teximage(brw, intel_texobj,
                                                          intel_image,
                                                          MIPTREE_CREATE_DEFAULT);
      if (!intel_image->mt)
         return false;

      /* Even if the object currently has a mipmap tree associated
       * with it, this one is a more likely candidate to represent the
       * whole object since our level didn't fit what was there
       * before, and any lower levels would fit into our miptree.
       */
      intel_miptree_reference(&intel_texobj->mt, intel_image->mt);

      DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n",
          __func__, texobj, image->Level,
          image->Width, image->Height, image->Depth, intel_image->mt);
   }

   intel_texobj->needs_validate = true;

   return true;
}
Beispiel #21
0
static bool
intel_renderbuffer_update_wrapper(struct intel_context *intel,
                                  struct intel_renderbuffer *irb,
				  struct gl_texture_image *image,
                                  uint32_t layer)
{
   struct gl_renderbuffer *rb = &irb->Base.Base;
   struct intel_texture_image *intel_image = intel_texture_image(image);
   struct intel_mipmap_tree *mt = intel_image->mt;
   int level = image->Level;

   rb->Format = image->TexFormat;
   rb->InternalFormat = image->InternalFormat;
   rb->_BaseFormat = image->_BaseFormat;
   rb->NumSamples = mt->num_samples;

   if (mt->msaa_layout != INTEL_MSAA_LAYOUT_NONE) {
      assert(level == 0);
      rb->Width = mt->logical_width0;
      rb->Height = mt->logical_height0;
   }
   else {
      rb->Width = mt->level[level].width;
      rb->Height = mt->level[level].height;
   }

   rb->Delete = intel_delete_renderbuffer;
   rb->AllocStorage = intel_nop_alloc_storage;

   intel_miptree_check_level_layer(mt, level, layer);
   irb->mt_level = level;

   switch (mt->msaa_layout) {
      case INTEL_MSAA_LAYOUT_UMS:
      case INTEL_MSAA_LAYOUT_CMS:
         irb->mt_layer = layer * mt->num_samples;
         break;

      default:
         irb->mt_layer = layer;
   }

   intel_miptree_reference(&irb->mt, mt);

   intel_renderbuffer_set_draw_offset(irb);

   if (mt->hiz_mt == NULL &&
       intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
      intel_miptree_alloc_hiz(intel, mt, 0 /* num_samples */);
      if (!mt->hiz_mt)
	 return false;
   }

   return true;
}
Beispiel #22
0
static void
intelTexImage(struct gl_context * ctx,
              GLuint dims,
              struct gl_texture_image *texImage,
              GLenum format, GLenum type, const void *pixels,
              const struct gl_pixelstore_attrib *unpack)
{
   struct intel_texture_image *intelImage = intel_texture_image(texImage);
   bool ok;

   bool tex_busy = intelImage->mt && drm_intel_bo_busy(intelImage->mt->bo);

   DBG("%s mesa_format %s target %s format %s type %s level %d %dx%dx%d\n",
       __func__, _mesa_get_format_name(texImage->TexFormat),
       _mesa_enum_to_string(texImage->TexObject->Target),
       _mesa_enum_to_string(format), _mesa_enum_to_string(type),
       texImage->Level, texImage->Width, texImage->Height, texImage->Depth);

   /* Allocate storage for texture data. */
   if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
      return;
   }

   assert(intelImage->mt);

   if (intelImage->mt->format == MESA_FORMAT_S_UINT8)
      intelImage->mt->r8stencil_needs_update = true;

   ok = _mesa_meta_pbo_TexSubImage(ctx, dims, texImage, 0, 0, 0,
                                   texImage->Width, texImage->Height,
                                   texImage->Depth,
                                   format, type, pixels,
                                   tex_busy, unpack);
   if (ok)
      return;

   ok = intel_texsubimage_tiled_memcpy(ctx, dims, texImage,
                                       0, 0, 0, /*x,y,z offsets*/
                                       texImage->Width,
                                       texImage->Height,
                                       texImage->Depth,
                                       format, type, pixels, unpack,
                                       false /*allocate_storage*/);
   if (ok)
      return;

   DBG("%s: upload image %dx%dx%d pixels %p\n",
       __func__, texImage->Width, texImage->Height, texImage->Depth,
       pixels);

   _mesa_store_teximage(ctx, dims, texImage,
                        format, type, pixels, unpack);
}
Beispiel #23
0
static void
intel_free_texture_image_buffer(struct gl_context * ctx,
				struct gl_texture_image *texImage)
{
   struct intel_texture_image *intelImage = intel_texture_image(texImage);

   DBG("%s\n", __FUNCTION__);

   intel_miptree_release(&intelImage->mt);

   _swrast_free_texture_image_buffer(ctx, texImage);
}
Beispiel #24
0
static void
intel_unmap_texture_image(struct gl_context *ctx,
			  struct gl_texture_image *tex_image, GLuint slice)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_texture_image *intel_image = intel_texture_image(tex_image);
   struct intel_mipmap_tree *mt = intel_image->mt;

   if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
      slice = tex_image->Face;

   intel_miptree_unmap(intel, mt, tex_image->Level, slice);
}
/**
 * Need to map texture image into memory before copying image data,
 * then unmap it.
 */
static void
intel_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
		    GLenum format, GLenum type, GLvoid * pixels,
		    struct gl_texture_object *texObj,
		    struct gl_texture_image *texImage, int compressed)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_texture_image *intelImage = intel_texture_image(texImage);

   /* Map */
   if (intelImage->mt) {
      /* Image is stored in hardware format in a buffer managed by the
       * kernel.  Need to explicitly map and unmap it.
       */
      intelImage->base.Data =
         intel_miptree_image_map(intel,
                                 intelImage->mt,
                                 intelImage->face,
                                 intelImage->level,
                                 &intelImage->base.RowStride,
                                 intelImage->base.ImageOffsets);
      intelImage->base.RowStride /= intelImage->mt->cpp;
   }
   else {
      /* Otherwise, the image should actually be stored in
       * intelImage->base.Data.  This is pretty confusing for
       * everybody, I'd much prefer to separate the two functions of
       * texImage->Data - storage for texture images in main memory
       * and access (ie mappings) of images.  In other words, we'd
       * create a new texImage->Map field and leave Data simply for
       * storage.
       */
      assert(intelImage->base.Data);
   }


   if (compressed) {
      _mesa_get_compressed_teximage(ctx, target, level, pixels,
				    texObj, texImage);
   } else {
      _mesa_get_teximage(ctx, target, level, format, type, pixels,
			 texObj, texImage);
   }
     

   /* Unmap */
   if (intelImage->mt) {
      intel_miptree_image_unmap(intel, intelImage->mt);
      intelImage->base.Data = NULL;
   }
}
/**
 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
 * We can do this when the dst renderbuffer is actually a texture and
 * there is no scaling, mirroring or scissoring.
 *
 * \return new buffer mask indicating the buffers left to blit using the
 *         normal path.
 */
static GLbitfield
intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
                                          GLint srcX0, GLint srcY0,
                                          GLint srcX1, GLint srcY1,
                                          GLint dstX0, GLint dstY0,
                                          GLint dstX1, GLint dstY1,
                                          GLbitfield mask, GLenum filter)
{
   if (mask & GL_COLOR_BUFFER_BIT) {
      const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
      const struct gl_framebuffer *readFb = ctx->ReadBuffer;
      const struct gl_renderbuffer_attachment *drawAtt =
         &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
      struct intel_renderbuffer *srcRb = 
         intel_renderbuffer(readFb->_ColorReadBuffer);

      /* If the source and destination are the same size with no
         mirroring, the rectangles are within the size of the
         texture and there is no scissor then we can use
         glCopyTexSubimage2D to implement the blit. This will end
         up as a fast hardware blit on some drivers */
      if (srcRb && drawAtt && drawAtt->Texture &&
          srcX0 - srcX1 == dstX0 - dstX1 &&
          srcY0 - srcY1 == dstY0 - dstY1 &&
          srcX1 >= srcX0 &&
          srcY1 >= srcY0 &&
          srcX0 >= 0 && srcX1 <= readFb->Width &&
          srcY0 >= 0 && srcY1 <= readFb->Height &&
          dstX0 >= 0 && dstX1 <= drawFb->Width &&
          dstY0 >= 0 && dstY1 <= drawFb->Height &&
          !ctx->Scissor.Enabled) {
         const struct gl_texture_object *texObj = drawAtt->Texture;
         const GLuint dstLevel = drawAtt->TextureLevel;
         const GLenum target = texObj->Target;

         struct gl_texture_image *texImage =
            _mesa_select_tex_image(ctx, texObj, target, dstLevel);

         if (intel_copy_texsubimage(intel_context(ctx),
                                    intel_texture_image(texImage),
                                    dstX0, dstY0,
                                    srcRb,
                                    srcX0, srcY0,
                                    srcX1 - srcX0, /* width */
                                    srcY1 - srcY0))
            mask &= ~GL_COLOR_BUFFER_BIT;
      }
   }

   return mask;
}
/**
 * Can the image be pulled into a unified mipmap tree?  This mirrors
 * the completeness test in a lot of ways.
 *
 * Not sure whether I want to pass gl_texture_image here.
 */
bool
intel_miptree_match_image(struct intel_mipmap_tree *mt,
                          struct gl_texture_image *image)
{
    struct intel_texture_image *intelImage = intel_texture_image(image);
    GLuint level = intelImage->base.Base.Level;
    int width, height, depth;

    /* glTexImage* choose the texture object based on the target passed in, and
     * objects can't change targets over their lifetimes, so this should be
     * true.
     */
    assert(target_to_target(image->TexObject->Target) == mt->target);

    mesa_format mt_format = mt->format;

    if (image->TexFormat != mt_format)
        return false;

    intel_miptree_get_dimensions_for_image(image, &width, &height, &depth);

    if (mt->target == GL_TEXTURE_CUBE_MAP)
        depth = 6;

    /* Test image dimensions against the base level image adjusted for
     * minification.  This will also catch images not present in the
     * tree, changed targets, etc.
     */
    if (mt->target == GL_TEXTURE_2D_MULTISAMPLE ||
            mt->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) {
        /* nonzero level here is always bogus */
        assert(level == 0);

        if (width != mt->logical_width0 ||
                height != mt->logical_height0 ||
                depth != mt->logical_depth0) {
            return false;
        }
    }
    else {
        /* all normal textures, renderbuffers, etc */
        if (width != mt->level[level].width ||
                height != mt->level[level].height ||
                depth != mt->level[level].depth) {
            return false;
        }
    }

    return true;
}
Beispiel #28
0
void
intel_tex_unmap_images(struct intel_context *intel,
		       struct intel_texture_object *intelObj)
{
   GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
   int i, face;

   for (i = intelObj->base.BaseLevel; i <= intelObj->_MaxLevel; i++) {
      for (face = 0; face < nr_faces; face++) {
	 struct intel_texture_image *intel_image =
	    intel_texture_image(intelObj->base.Image[face][i]);

	 intel_tex_unmap_image_for_swrast(intel, intel_image);
      }
   }
}
Beispiel #29
0
static void
intelCopyTexSubImage1D(struct gl_context *ctx,
                       struct gl_texture_image *texImage,
                       GLint xoffset,
                       struct gl_renderbuffer *rb,
                       GLint x, GLint y, GLsizei width)
{
   if (!intel_copy_texsubimage(intel_context(ctx),
                               intel_texture_image(texImage),
                               xoffset, 0,
                               intel_renderbuffer(rb), x, y, width, 1)) {
      fallback_debug("%s - fallback to swrast\n", __FUNCTION__);
      _mesa_meta_CopyTexSubImage1D(ctx, texImage, xoffset,
                                   rb, x, y, width);
   }
}
Beispiel #30
0
static GLboolean
intel_texture_view(struct gl_context *ctx,
                   struct gl_texture_object *texObj,
                   struct gl_texture_object *origTexObj)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_texture_object *intel_tex = intel_texture_object(texObj);
   struct intel_texture_object *intel_orig_tex = intel_texture_object(origTexObj);

   assert(intel_orig_tex->mt);
   intel_miptree_reference(&intel_tex->mt, intel_orig_tex->mt);

   /* Since we can only make views of immutable-format textures,
    * we can assume that everything is in origTexObj's miptree.
    *
    * Mesa core has already made us a copy of all the teximage objects,
    * except it hasn't copied our mt pointers, etc.
    */
   const int numFaces = _mesa_num_tex_faces(texObj->Target);
   const int numLevels = texObj->NumLevels;

   int face;
   int level;

   for (face = 0; face < numFaces; face++) {
      for (level = 0; level < numLevels; level++) {
         struct gl_texture_image *image = texObj->Image[face][level];
         struct intel_texture_image *intel_image = intel_texture_image(image);

         intel_miptree_reference(&intel_image->mt, intel_orig_tex->mt);
      }
   }

   /* The miptree is in a validated state, so no need to check later. */
   intel_tex->needs_validate = false;
   intel_tex->validated_first_level = 0;
   intel_tex->validated_last_level = numLevels - 1;

   /* Set the validated texture format, with the same adjustments that
    * would have been applied to determine the underlying texture's
    * mt->format.
    */
   intel_tex->_Format = intel_depth_format_for_depthstencil_format(
         intel_lower_compressed_format(brw, texObj->Image[0][0]->TexFormat));

   return GL_TRUE;
}