/**
 * @param for_bo Indicates that the caller is
 *        intel_miptree_create_for_bo(). If true, then do not create
 *        \c stencil_mt.
 */
struct intel_mipmap_tree *
intel_miptree_create_layout(struct intel_context *intel,
                            GLenum target,
                            mesa_format format,
                            GLuint first_level,
                            GLuint last_level,
                            GLuint width0,
                            GLuint height0,
                            GLuint depth0,
                            bool for_bo)
{
    struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
    if (!mt)
        return NULL;

    DBG("%s target %s format %s level %d..%d <-- %p\n", __func__,
        _mesa_enum_to_string(target),
        _mesa_get_format_name(format),
        first_level, last_level, mt);

    mt->target = target_to_target(target);
    mt->format = format;
    mt->first_level = first_level;
    mt->last_level = last_level;
    mt->logical_width0 = width0;
    mt->logical_height0 = height0;
    mt->logical_depth0 = depth0;

    /* The cpp is bytes per (1, blockheight)-sized block for compressed
     * textures.  This is why you'll see divides by blockheight all over
     */
    unsigned bw, bh;
    _mesa_get_format_block_size(format, &bw, &bh);
    assert(_mesa_get_format_bytes(mt->format) % bw == 0);
    mt->cpp = _mesa_get_format_bytes(mt->format) / bw;

    mt->compressed = _mesa_is_format_compressed(format);
    mt->refcount = 1;

    if (target == GL_TEXTURE_CUBE_MAP) {
        assert(depth0 == 1);
        depth0 = 6;
    }

    mt->physical_width0 = width0;
    mt->physical_height0 = height0;
    mt->physical_depth0 = depth0;

    intel_get_texture_alignment_unit(intel, mt->format,
                                     &mt->align_w, &mt->align_h);

    (void) intel;
    if (intel->is_945)
        i945_miptree_layout(mt);
    else
        i915_miptree_layout(mt);

    return mt;
}
Beispiel #2
0
/**
 * Copy mipmap image between trees
 */
void
intel_miptree_image_copy(struct intel_context *intel,
                         struct intel_mipmap_tree *dst,
                         GLuint face, GLuint level,
                         struct intel_mipmap_tree *src)
{
    GLuint width = src->level[level].width;
    GLuint height = src->level[level].height;
    GLuint depth = src->level[level].depth;
    GLuint src_x, src_y, dst_x, dst_y;
    GLuint i;
    GLboolean success;

    if (dst->compressed) {
        GLuint align_w, align_h;

        intel_get_texture_alignment_unit(dst->internal_format,
                                         &align_w, &align_h);
        height = (height + 3) / 4;
        width = ALIGN(width, align_w);
    }

    intel_prepare_render(intel);

    for (i = 0; i < depth; i++) {
        intel_miptree_get_image_offset(src, level, face, i, &src_x, &src_y);
        intel_miptree_get_image_offset(dst, level, face, i, &dst_x, &dst_y);
        success = intel_region_copy(intel,
                                    dst->region, 0, dst_x, dst_y,
                                    src->region, 0, src_x, src_y,
                                    width, height, GL_FALSE,
                                    GL_COPY);
        if (!success) {
            GLubyte *src_ptr, *dst_ptr;

            src_ptr = intel_region_map(intel, src->region);
            dst_ptr = intel_region_map(intel, dst->region);

            _mesa_copy_rect(dst_ptr,
                            dst->cpp,
                            dst->region->pitch,
                            dst_x, dst_y, width, height,
                            src_ptr,
                            src->region->pitch,
                            src_x, src_y);
            intel_region_unmap(intel, src->region);
            intel_region_unmap(intel, dst->region);
        }
    }
}
Beispiel #3
0
GLboolean brw_miptree_layout(struct intel_context *intel,
			     struct intel_mipmap_tree *mt,
			     uint32_t tiling)
{
   /* XXX: these vary depending on image format: */
   /* GLint align_w = 4; */

   switch (mt->target) {
   case GL_TEXTURE_CUBE_MAP:
      if (intel->gen == 5) {
          GLuint align_h = 2;
          GLuint level;
          GLuint qpitch = 0;
	  int h0, h1, q;

	  /* On Ironlake, cube maps are finally represented as just a series
	   * of MIPLAYOUT_BELOW 2D textures (like 2D texture arrays), separated
	   * by a pitch of qpitch rows, where qpitch is defined by the equation
	   * given in Volume 1 of the BSpec.
	   */
	  h0 = ALIGN(mt->height0, align_h);
	  h1 = ALIGN(minify(h0), align_h);
	  qpitch = (h0 + h1 + 11 * align_h);
          if (mt->compressed)
	     qpitch /= 4;

	  i945_miptree_layout_2d(intel, mt, tiling, 6);

          for (level = mt->first_level; level <= mt->last_level; level++) {
	     for (q = 0; q < 6; q++) {
		intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch);
	     }
          }
	  mt->total_height = qpitch * 6;

          break;
      }

   case GL_TEXTURE_3D: {
      GLuint width  = mt->width0;
      GLuint height = mt->height0;
      GLuint depth = mt->depth0;
      GLuint pack_x_pitch, pack_x_nr;
      GLuint pack_y_pitch;
      GLuint level;
      GLuint align_h = 2;
      GLuint align_w = 4;

      mt->total_height = 0;
      intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h);

      if (mt->compressed) {
          mt->pitch = ALIGN(width, align_w);
          pack_y_pitch = (height + 3) / 4;
      } else {
	 mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0);
	 pack_y_pitch = ALIGN(mt->height0, align_h);
      }

      pack_x_pitch = width;
      pack_x_nr = 1;

      for (level = mt->first_level ; level <= mt->last_level ; level++) {
	 GLuint nr_images = mt->target == GL_TEXTURE_3D ? depth : 6;
	 GLint x = 0;
	 GLint y = 0;
	 GLint q, j;

	 intel_miptree_set_level_info(mt, level, nr_images,
				      0, mt->total_height,
				      width, height, depth);

	 for (q = 0; q < nr_images;) {
	    for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
	       intel_miptree_set_image_offset(mt, level, q, x, y);
	       x += pack_x_pitch;
	    }

	    x = 0;
	    y += pack_y_pitch;
	 }


	 mt->total_height += y;
	 width  = minify(width);
	 height = minify(height);
	 depth  = minify(depth);

	 if (mt->compressed) {
	    pack_y_pitch = (height + 3) / 4;

	    if (pack_x_pitch > ALIGN(width, align_w)) {
	       pack_x_pitch = ALIGN(width, align_w);
	       pack_x_nr <<= 1;
	    }
	 } else {
	    if (pack_x_pitch > 4) {
	       pack_x_pitch >>= 1;
	       pack_x_nr <<= 1;
	       assert(pack_x_pitch * pack_x_nr <= mt->pitch);
	    }

	    if (pack_y_pitch > 2) {
	       pack_y_pitch >>= 1;
	       pack_y_pitch = ALIGN(pack_y_pitch, align_h);
	    }
	 }

      }
      /* The 965's sampler lays cachelines out according to how accesses
       * in the texture surfaces run, so they may be "vertical" through
       * memory.  As a result, the docs say in Surface Padding Requirements:
       * Sampling Engine Surfaces that two extra rows of padding are required.
       * We don't know of similar requirements for pre-965, but given that
       * those docs are silent on padding requirements in general, let's play
       * it safe.
       */
      if (mt->target == GL_TEXTURE_CUBE_MAP)
	 mt->total_height += 2;
      break;
   }
Beispiel #4
0
GLboolean brw_miptree_layout(struct intel_context *intel,
                             struct intel_mipmap_tree *mt,
                             uint32_t tiling)
{
    /* XXX: these vary depending on image format: */
    /* GLint align_w = 4; */

    switch (mt->target) {
    case GL_TEXTURE_CUBE_MAP:
        if (IS_IGDNG(intel->intelScreen->deviceID)) {
            GLuint align_h = 2, align_w = 4;
            GLuint level;
            GLuint x = 0;
            GLuint y = 0;
            GLuint width = mt->width0;
            GLuint height = mt->height0;
            GLuint qpitch = 0;
            GLuint y_pitch = 0;

            mt->pitch = mt->width0;
            intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h);
            y_pitch = ALIGN(height, align_h);

            if (mt->compressed) {
                mt->pitch = ALIGN(mt->width0, align_w);
            }

            if (mt->first_level != mt->last_level) {
                GLuint mip1_width;

                if (mt->compressed) {
                    mip1_width = ALIGN(minify(mt->width0), align_w)
                                 + ALIGN(minify(minify(mt->width0)), align_w);
                } else {
                    mip1_width = ALIGN(minify(mt->width0), align_w)
                                 + minify(minify(mt->width0));
                }

                if (mip1_width > mt->pitch) {
                    mt->pitch = mip1_width;
                }
            }

            mt->pitch = intel_miptree_pitch_align(intel, mt, tiling, mt->pitch);

            if (mt->compressed) {
                qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4;
                mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) / 4 * 6;
            } else {
                qpitch = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h);
                mt->total_height = (y_pitch + ALIGN(minify(y_pitch), align_h) + 11 * align_h) * 6;
            }

            for (level = mt->first_level; level <= mt->last_level; level++) {
                GLuint img_height;
                GLuint nr_images = 6;
                GLuint q = 0;

                intel_miptree_set_level_info(mt, level, nr_images, x, y, width,
                                             height, 1);

                for (q = 0; q < nr_images; q++)
                    intel_miptree_set_image_offset(mt, level, q,
                                                   x, y + q * qpitch);

                if (mt->compressed)
                    img_height = MAX2(1, height/4);
                else
                    img_height = ALIGN(height, align_h);

                if (level == mt->first_level + 1) {
                    x += ALIGN(width, align_w);
                }
                else {
                    y += img_height;
                }

                width  = minify(width);
                height = minify(height);
            }

            break;
        }

    case GL_TEXTURE_3D: {
        GLuint width  = mt->width0;
        GLuint height = mt->height0;
        GLuint depth = mt->depth0;
        GLuint pack_x_pitch, pack_x_nr;
        GLuint pack_y_pitch;
        GLuint level;
        GLuint align_h = 2;
        GLuint align_w = 4;

        mt->total_height = 0;
        intel_get_texture_alignment_unit(mt->internal_format, &align_w, &align_h);

        if (mt->compressed) {
            mt->pitch = ALIGN(width, align_w);
            pack_y_pitch = (height + 3) / 4;
        } else {
            mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0);
            pack_y_pitch = ALIGN(mt->height0, align_h);
        }

        pack_x_pitch = width;
        pack_x_nr = 1;

        for (level = mt->first_level ; level <= mt->last_level ; level++) {
            GLuint nr_images = mt->target == GL_TEXTURE_3D ? depth : 6;
            GLint x = 0;
            GLint y = 0;
            GLint q, j;

            intel_miptree_set_level_info(mt, level, nr_images,
                                         0, mt->total_height,
                                         width, height, depth);

            for (q = 0; q < nr_images;) {
                for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
                    intel_miptree_set_image_offset(mt, level, q, x, y);
                    x += pack_x_pitch;
                }

                x = 0;
                y += pack_y_pitch;
            }


            mt->total_height += y;
            width  = minify(width);
            height = minify(height);
            depth  = minify(depth);

            if (mt->compressed) {
                pack_y_pitch = (height + 3) / 4;

                if (pack_x_pitch > ALIGN(width, align_w)) {
                    pack_x_pitch = ALIGN(width, align_w);
                    pack_x_nr <<= 1;
                }
            } else {
                if (pack_x_pitch > 4) {
                    pack_x_pitch >>= 1;
                    pack_x_nr <<= 1;
                    assert(pack_x_pitch * pack_x_nr <= mt->pitch);
                }

                if (pack_y_pitch > 2) {
                    pack_y_pitch >>= 1;
                    pack_y_pitch = ALIGN(pack_y_pitch, align_h);
                }
            }

        }
        /* The 965's sampler lays cachelines out according to how accesses
         * in the texture surfaces run, so they may be "vertical" through
         * memory.  As a result, the docs say in Surface Padding Requirements:
         * Sampling Engine Surfaces that two extra rows of padding are required.
         * We don't know of similar requirements for pre-965, but given that
         * those docs are silent on padding requirements in general, let's play
         * it safe.
         */
        if (mt->target == GL_TEXTURE_CUBE_MAP)
            mt->total_height += 2;
        break;
    }