Example #1
0
static void
i915_miptree_layout_2d(struct intel_mipmap_tree * mt)
{
   GLuint width = mt->width0;
   GLuint height = mt->height0;
   GLuint img_height;
   GLint level;

   mt->total_width = mt->width0;
   mt->total_height = 0;

   for (level = mt->first_level; level <= mt->last_level; level++) {
      intel_miptree_set_level_info(mt, level,
				   0, mt->total_height,
				   width, height, 1);

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

      mt->total_height += img_height;

      width = minify(width);
      height = minify(height);
   }
}
Example #2
0
static void
apply_gen6_stencil_hiz_offset(struct isl_surf *surf,
                              struct intel_mipmap_tree *mt,
                              uint32_t lod,
                              uint32_t *offset)
{
   assert(mt->array_layout == ALL_SLICES_AT_EACH_LOD);

   if (mt->format == MESA_FORMAT_S_UINT8) {
      /* Note: we can't compute the stencil offset using
       * intel_miptree_get_aligned_offset(), because the miptree
       * claims that the region is untiled even though it's W tiled.
       */
      *offset = mt->level[lod].level_y * mt->pitch +
                mt->level[lod].level_x * 64;
   } else {
      *offset = intel_miptree_get_aligned_offset(mt,
                                                 mt->level[lod].level_x,
                                                 mt->level[lod].level_y);
   }

   surf->logical_level0_px.width = minify(surf->logical_level0_px.width, lod);
   surf->logical_level0_px.height = minify(surf->logical_level0_px.height, lod);
   surf->phys_level0_sa.width = minify(surf->phys_level0_sa.width, lod);
   surf->phys_level0_sa.height = minify(surf->phys_level0_sa.height, lod);
   surf->levels = 1;
   surf->array_pitch_el_rows =
      ALIGN(surf->phys_level0_sa.height, surf->image_alignment_el.height);
}
Example #3
0
static void
i915_miptree_layout_2d(struct intel_context *intel,
		       struct intel_mipmap_tree * mt,
		       uint32_t tiling)
{
   GLuint width = mt->width0;
   GLuint height = mt->height0;
   GLuint img_height;
   GLint level;

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

   for (level = mt->first_level; level <= mt->last_level; level++) {
      intel_miptree_set_level_info(mt, level, 1,
				   0, mt->total_height,
				   width, height, 1);

      if (mt->compressed)
	 img_height = MAX2(1, height / 4);
      else
	 img_height = (MAX2(2, height) + 1) & ~1;

      mt->total_height += img_height;

      width = minify(width);
      height = minify(height);
   }
}
Example #4
0
static void r300_setup_miptree(struct r300_texture* tex)
{
    struct pipe_texture* base = &tex->tex;
    int stride, size, offset;
    int i;

    for (i = 0; i <= base->last_level; i++) {
        if (i > 0) {
            base->width[i] = minify(base->width[i-1]);
            base->height[i] = minify(base->height[i-1]);
            base->depth[i] = minify(base->depth[i-1]);
        }

        base->nblocksx[i] = pf_get_nblocksx(&base->block, base->width[i]);
        base->nblocksy[i] = pf_get_nblocksy(&base->block, base->width[i]);

        /* Radeons enjoy things in multiples of 32. */
        /* XXX this can be 32 when POT */
        stride = (base->nblocksx[i] * base->block.size + 63) & ~63;
        size = stride * base->nblocksy[i] * base->depth[i];

        tex->offset[i] = (tex->size + 63) & ~63;
        tex->size = tex->offset[i] + size;

        if (i == 0) {
            tex->stride = stride;
        }
    }
}
static void calculate_miptree_layout(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
{
	GLuint curOffset, i, face, level;

	assert(mt->numLevels <= rmesa->glCtx.Const.MaxTextureLevels);

	curOffset = 0;
	for(face = 0; face < mt->faces; face++) {

		for(i = 0, level = mt->baseLevel; i < mt->numLevels; i++, level++) {
			mt->levels[level].valid = 1;
			mt->levels[level].width = minify(mt->width0, i);
			mt->levels[level].height = minify(mt->height0, i);
			mt->levels[level].depth = minify(mt->depth0, i);
			compute_tex_image_offset(rmesa, mt, face, level, &curOffset);
		}
	}

	/* Note the required size in memory */
	mt->totalsize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;

	radeon_print(RADEON_TEXTURE, RADEON_TRACE,
			"%s(%p, %p) total size %d\n",
			__func__, rmesa, mt, mt->totalsize);
}
void get_record_statistics(Record_Statistics *stats_out, Time_Record *records, int count){
    Record_Statistics stats;
    stats.max = records[0];
    stats.min = records[0];
    stats.expected = records[0];
    stats.count = count;

    Time_Record *record = records + 1;
    
    for (int i = 1; i < count; ++i, ++record){
        stats.expected = stats.expected + *record;
        
        minify(stats.min.buffer, record->buffer);
        minify(stats.min.gap_buffer, record->gap_buffer);
        minify(stats.min.multi_gap_buffer, record->multi_gap_buffer);
        minify(stats.min.rope_buffer, record->rope_buffer);
        
        maxify(stats.max.buffer, record->buffer);
        maxify(stats.max.gap_buffer, record->gap_buffer);
        maxify(stats.max.multi_gap_buffer, record->multi_gap_buffer);
        maxify(stats.max.rope_buffer, record->rope_buffer);
    }

    stats.expected /= count;
    
    *stats_out = stats;
}
Example #7
0
static void
brw_miptree_layout_texture_array(struct intel_context *intel,
				 struct intel_mipmap_tree *mt)
{
   GLuint level;
   GLuint qpitch = 0;
   int h0, h1, q;

   h0 = ALIGN(mt->height0, mt->align_h);
   h1 = ALIGN(minify(mt->height0), mt->align_h);
   if (mt->array_spacing_lod0)
      qpitch = h0;
   else
      qpitch = (h0 + h1 + (intel->gen >= 7 ? 12 : 11) * mt->align_h);
   if (mt->compressed)
      qpitch /= 4;

   i945_miptree_layout_2d(mt);

   for (level = mt->first_level; level <= mt->last_level; level++) {
      for (q = 0; q < mt->depth0; q++) {
	 intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch);
      }
   }
   mt->total_height = qpitch * mt->depth0;
}
Example #8
0
static void
gen9_miptree_layout_1d(struct intel_mipmap_tree *mt)
{
   unsigned x = 0;
   unsigned width = mt->physical_width0;
   unsigned depth = mt->physical_depth0; /* number of array layers. */

   /* When this layout is used the horizontal alignment is fixed at 64 and the
    * hardware ignores the value given in the surface state
    */
   const unsigned int align_w = 64;

   mt->total_height = mt->physical_height0;
   mt->total_width = 0;

   for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
      unsigned img_width;

      intel_miptree_set_level_info(mt, level, x, 0, depth);

      img_width = ALIGN(width, align_w);

      mt->total_width = MAX2(mt->total_width, x + img_width);

      x += img_width;

      width = minify(width, 1);
   }
}
//==============================================================
void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, uint32_t* outframe)
{
  Tinstance *in;
  in=(Tinstance*)instance;
  ExceptionInfo *exception;
  /* Generamos la excepción */
  exception = AcquireExceptionInfo();
  /* Transformamos el mapa de imagen de entrada para imagemagick */
  Image *im = ConstituteImage(in->size.width, in->size.height, "RGBA", CharPixel, inframe, exception);

  if (in->preview) 
    {
      minify(&im, (int)in->preview, exception);
    }
  /* Generamos la imagen de salida */
  Image *out = MotionBlurImage(im, in->radius, in->deviation, in->angle, exception);
  if (in->preview) 
    {
      magnify(&out, (int)in->preview, exception);
    }
  /* Volvemos a coger el contenido de la imagen para frei0r */
  ExportImagePixels(out, 0, 0, in->size.width, in->size.height, "RGBA", CharPixel,  outframe, exception);

  /* Liberamos memoria */
  exception = DestroyExceptionInfo(exception);
  im = DestroyImage(im);
  out = DestroyImage(out);
}
Example #10
0
static void
brw_miptree_layout_texture_array(struct brw_context *brw,
				 struct intel_mipmap_tree *mt)
{
   unsigned qpitch = 0;
   int h0, h1;

   h0 = ALIGN(mt->physical_height0, mt->align_h);
   h1 = ALIGN(minify(mt->physical_height0, 1), mt->align_h);
   if (mt->array_spacing_lod0)
      qpitch = h0;
   else
      qpitch = (h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->align_h);
   if (mt->compressed)
      qpitch /= 4;

   brw_miptree_layout_2d(mt);

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

   align_cube(mt);
}
Example #11
0
static void
i915_miptree_layout_3d(struct intel_context *intel,
		       struct intel_mipmap_tree * mt,
		       uint32_t tiling)
{
   GLuint width = mt->width0;
   GLuint height = mt->height0;
   GLuint depth = mt->depth0;
   GLuint stack_height = 0;
   GLint level;

   /* Calculate the size of a single slice. */
   mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0);

   /* XXX: hardware expects/requires 9 levels at minimum. */
   for (level = mt->first_level; level <= MAX2(8, mt->last_level); level++) {
      intel_miptree_set_level_info(mt, level, depth, 0, mt->total_height,
				   width, height, depth);

      stack_height += MAX2(2, height);

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

   /* Fixup depth image_offsets: */
   depth = mt->depth0;
   for (level = mt->first_level; level <= mt->last_level; level++) {
      GLuint i;
      for (i = 0; i < depth; i++) {
	 intel_miptree_set_image_offset(mt, level, i,
					0, i * stack_height);
      }

      depth = minify(depth);
   }

   /* Multiply slice size by texture depth for total size.  It's
    * remarkable how wasteful of memory the i915 texture layouts
    * are.  They are largely fixed in the i945.
    */
   mt->total_height = stack_height * mt->depth0;
}
Example #12
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 #13
0
static void
brw_miptree_layout_texture_array(struct brw_context *brw,
				 struct intel_mipmap_tree *mt)
{
   int h0, h1;
   unsigned height = mt->physical_height0;
   bool layout_1d = use_linear_1d_layout(brw, mt);

   h0 = ALIGN(mt->physical_height0, mt->align_h);
   h1 = ALIGN(minify(mt->physical_height0, 1), mt->align_h);
   if (mt->array_layout == ALL_SLICES_AT_EACH_LOD)
      mt->qpitch = h0;
   else
      mt->qpitch = (h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->align_h);

   int physical_qpitch = mt->compressed ? mt->qpitch / 4 : mt->qpitch;

   if (layout_1d)
      gen9_miptree_layout_1d(mt);
   else
      brw_miptree_layout_2d(mt);

   for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
      unsigned img_height;
      img_height = ALIGN(height, mt->align_h);
      if (mt->compressed)
         img_height /= mt->align_h;

      for (int q = 0; q < mt->level[level].depth; q++) {
         if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) {
            intel_miptree_set_image_offset(mt, level, q, 0, q * img_height);
         } else {
            intel_miptree_set_image_offset(mt, level, q, 0, q * physical_qpitch);
         }
      }
      height = minify(height, 1);
   }
   if (mt->array_layout == ALL_LOD_IN_EACH_SLICE)
      mt->total_height = physical_qpitch * mt->physical_depth0;

   align_cube(mt);
}
Example #14
0
unsigned
brw_miptree_get_horizontal_slice_pitch(const struct brw_context *brw,
                                       const struct intel_mipmap_tree *mt,
                                       unsigned level)
{
   if ((brw->gen < 9 && mt->target == GL_TEXTURE_3D) ||
       (brw->gen == 4 && mt->target == GL_TEXTURE_CUBE_MAP)) {
      return ALIGN_NPOT(minify(mt->physical_width0, level), mt->align_w);
   } else {
      return 0;
   }
}
Example #15
0
/**
 * Sets up a DRIImage structure to point to a slice out of a miptree.
 */
static void
intel_setup_image_from_mipmap_tree(struct brw_context *brw, __DRIimage *image,
                                   struct intel_mipmap_tree *mt, GLuint level,
                                   GLuint zoffset)
{
   intel_miptree_make_shareable(brw, mt);

   intel_miptree_check_level_layer(mt, level, zoffset);

   image->width = minify(mt->physical_width0, level - mt->first_level);
   image->height = minify(mt->physical_height0, level - mt->first_level);
   image->pitch = mt->pitch;

   image->offset = intel_miptree_get_tile_offsets(mt, level, zoffset,
                                                  &image->tile_x,
                                                  &image->tile_y);

   drm_intel_bo_unreference(image->bo);
   image->bo = mt->bo;
   drm_intel_bo_reference(mt->bo);
}
Example #16
0
/* Conventional allocation path for non-display textures:
 */
static boolean
softpipe_texture_layout(struct pipe_screen *screen,
                        struct softpipe_texture * spt)
{
   struct pipe_winsys *ws = screen->winsys;
   struct pipe_texture *pt = &spt->base;
   unsigned level;
   unsigned width = pt->width[0];
   unsigned height = pt->height[0];
   unsigned depth = pt->depth[0];

   unsigned buffer_size = 0;

   for (level = 0; level <= pt->last_level; level++) {
      pt->width[level] = width;
      pt->height[level] = height;
      pt->depth[level] = depth;
      pt->nblocksx[level] = pf_get_nblocksx(&pt->block, width);  
      pt->nblocksy[level] = pf_get_nblocksy(&pt->block, height);  
      spt->stride[level] = pt->nblocksx[level]*pt->block.size;

      spt->level_offset[level] = buffer_size;

      buffer_size += (pt->nblocksy[level] *
                      ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
                      spt->stride[level]);

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

   spt->buffer = ws->buffer_create(ws, 32,
                                   PIPE_BUFFER_USAGE_PIXEL,
                                   buffer_size);

   return spt->buffer != NULL;
}
void
brw_blorp_mip_info::set(struct intel_mipmap_tree *mt,
                        unsigned int level, unsigned int layer)
{
   /* Layer is a physical layer, so if this is a 2D multisample array texture
    * using INTEL_MSAA_LAYOUT_UMS or INTEL_MSAA_LAYOUT_CMS, then it had better
    * be a multiple of num_samples.
    */
   if (mt->msaa_layout == INTEL_MSAA_LAYOUT_UMS ||
       mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) {
      assert(layer % mt->num_samples == 0);
   }

   intel_miptree_check_level_layer(mt, level, layer);

   this->mt = mt;
   this->level = level;
   this->layer = layer;
   this->width = minify(mt->physical_width0, level - mt->first_level);
   this->height = minify(mt->physical_height0, level - mt->first_level);

   intel_miptree_get_image_offset(mt, level, layer, &x_offset, &y_offset);
}
Example #18
0
static void
brw_miptree_layout_texture_array(struct brw_context *brw,
				 struct intel_mipmap_tree *mt)
{
   unsigned height = mt->physical_height0;
   bool layout_1d = gen9_use_linear_1d_layout(brw, mt);
   int physical_qpitch;

   if (layout_1d)
      gen9_miptree_layout_1d(mt);
   else
      brw_miptree_layout_2d(mt);

   if (layout_1d) {
      physical_qpitch = 1;
      /* When using the horizontal layout the qpitch specifies the distance in
       * pixels between array slices. The total_width is forced to be a
       * multiple of the horizontal alignment in brw_miptree_layout_1d (in
       * this case it's always 64). The vertical alignment is ignored.
       */
      mt->qpitch = mt->total_width;
   } else {
      mt->qpitch = brw_miptree_get_vertical_slice_pitch(brw, mt, 0);
      /* Unlike previous generations the qpitch is a multiple of the
       * compressed block size on Gen9 so physical_qpitch matches mt->qpitch.
       */
      physical_qpitch = (mt->compressed && brw->gen < 9 ? mt->qpitch / 4 :
                         mt->qpitch);
   }

   for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
      unsigned img_height;
      img_height = ALIGN_NPOT(height, mt->align_h);
      if (mt->compressed)
         img_height /= mt->align_h;

      for (unsigned q = 0; q < mt->level[level].depth; q++) {
         if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) {
            intel_miptree_set_image_offset(mt, level, q, 0, q * img_height);
         } else {
            intel_miptree_set_image_offset(mt, level, q, 0, q * physical_qpitch);
         }
      }
      height = minify(height, 1);
   }
   if (mt->array_layout == ALL_LOD_IN_EACH_SLICE)
      mt->total_height = physical_qpitch * mt->physical_depth0;

   align_cube(mt);
}
Example #19
0
void ofxUISuperCanvas::setMinified(bool _bIsMinified)
{
    if(bIsMinified != _bIsMinified)
    {
        bIsMinified = _bIsMinified;
        if(bIsMinified)
        {
            minify();
        }
        else
        {
            maximize();
        }
    }
}
Example #20
0
float4 __CGsampler1DARRAY_state::sample(float4 strq, float lod)
{
    lod += clampedLodBias;

    if (lod < minLod) {
        lod = minLod;
    } else if (lod > maxLod) {
        lod = maxLod;
    } else {
        // lod not clamped.
    }

    if (lod <= magnifyTransition) {
        return magnify(0, strq);
    } else {
        return minify(0, strq, lod);
    }
}
Example #21
0
/**
 * Implements fast depth clears on gen6+.
 *
 * Fast clears basically work by setting a flag in each of the subspans
 * represented in the HiZ buffer that says "When you need the depth values for
 * this subspan, it's the hardware's current clear value."  Then later rendering
 * can just use the static clear value instead of referencing memory.
 *
 * The tricky part of the implementation is that you have to have the clear
 * value that was used on the depth buffer in place for all further rendering,
 * at least until a resolve to the real depth buffer happens.
 */
static bool
brw_fast_clear_depth(struct gl_context *ctx)
{
   struct brw_context *brw = brw_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   struct intel_renderbuffer *depth_irb =
      intel_get_renderbuffer(fb, BUFFER_DEPTH);
   struct intel_mipmap_tree *mt = depth_irb->mt;
   struct gl_renderbuffer_attachment *depth_att = &fb->Attachment[BUFFER_DEPTH];

   if (brw->gen < 6)
      return false;

   if (!intel_renderbuffer_has_hiz(depth_irb))
      return false;

   /* We only handle full buffer clears -- otherwise you'd have to track whether
    * a previous clear had happened at a different clear value and resolve it
    * first.
    */
   if ((ctx->Scissor.EnableFlags & 1) && !noop_scissor(ctx, fb)) {
      perf_debug("Failed to fast clear %dx%d depth because of scissors.  "
                 "Possible 5%% performance win if avoided.\n",
                 mt->logical_width0, mt->logical_height0);
      return false;
   }

   uint32_t depth_clear_value;
   switch (mt->format) {
   case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
   case MESA_FORMAT_Z24_UNORM_S8_UINT:
      /* From the Sandy Bridge PRM, volume 2 part 1, page 314:
       *
       *     "[DevSNB+]: Several cases exist where Depth Buffer Clear cannot be
       *      enabled (the legacy method of clearing must be performed):
       *
       *      - If the depth buffer format is D32_FLOAT_S8X24_UINT or
       *        D24_UNORM_S8_UINT.
       */
      return false;

   case MESA_FORMAT_Z_FLOAT32:
      depth_clear_value = float_as_int(ctx->Depth.Clear);
      break;

   case MESA_FORMAT_Z_UNORM16:
      /* From the Sandy Bridge PRM, volume 2 part 1, page 314:
       *
       *     "[DevSNB+]: Several cases exist where Depth Buffer Clear cannot be
       *      enabled (the legacy method of clearing must be performed):
       *
       *      - DevSNB{W/A}]: When depth buffer format is D16_UNORM and the
       *        width of the map (LOD0) is not multiple of 16, fast clear
       *        optimization must be disabled.
       */
      if (brw->gen == 6 &&
          (minify(mt->physical_width0,
                  depth_irb->mt_level - mt->first_level) % 16) != 0)
	 return false;
      /* FALLTHROUGH */

   default:
      if (brw->gen >= 8)
         depth_clear_value = float_as_int(ctx->Depth.Clear);
      else
         depth_clear_value = fb->_DepthMax * ctx->Depth.Clear;
      break;
   }

   /* If we're clearing to a new clear value, then we need to resolve any clear
    * flags out of the HiZ buffer into the real depth buffer.
    */
   if (mt->depth_clear_value != depth_clear_value) {
      intel_miptree_all_slices_resolve_depth(brw, mt);
      mt->depth_clear_value = depth_clear_value;
   }

   /* From the Sandy Bridge PRM, volume 2 part 1, page 313:
    *
    *     "If other rendering operations have preceded this clear, a
    *      PIPE_CONTROL with write cache flush enabled and Z-inhibit disabled
    *      must be issued before the rectangle primitive used for the depth
    *      buffer clear operation.
    */
   brw_emit_mi_flush(brw);

   if (fb->MaxNumLayers > 0) {
      for (unsigned layer = 0; layer < depth_irb->layer_count; layer++) {
         intel_hiz_exec(brw, mt, depth_irb->mt_level,
                        depth_irb->mt_layer + layer,
                        GEN6_HIZ_OP_DEPTH_CLEAR);
      }
   } else {
      intel_hiz_exec(brw, mt, depth_irb->mt_level, depth_irb->mt_layer,
                     GEN6_HIZ_OP_DEPTH_CLEAR);
   }

   if (brw->gen == 6) {
      /* From the Sandy Bridge PRM, volume 2 part 1, page 314:
       *
       *     "DevSNB, DevSNB-B{W/A}]: Depth buffer clear pass must be followed
       *      by a PIPE_CONTROL command with DEPTH_STALL bit set and Then
       *      followed by Depth FLUSH'
      */
      brw_emit_mi_flush(brw);
   }

   /* Now, the HiZ buffer contains data that needs to be resolved to the depth
    * buffer.
    */
   intel_renderbuffer_att_set_needs_depth_resolve(depth_att);

   return true;
}
Example #22
0
/**
 * Called via ctx->Driver.GenerateMipmap()
 * Note: We don't yet support 3D textures, 1D/2D array textures or texture
 * borders.
 */
void
_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target,
                          struct gl_texture_object *texObj)
{
   struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
   struct vertex verts[4];
   const GLuint baseLevel = texObj->BaseLevel;
   const GLuint maxLevel = texObj->MaxLevel;
   const GLint maxLevelSave = texObj->MaxLevel;
   const GLboolean genMipmapSave = texObj->GenerateMipmap;
   const GLuint currentTexUnitSave = ctx->Texture.CurrentUnit;
   const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
                                      ctx->Extensions.ARB_fragment_shader;
   GLenum faceTarget;
   GLuint dstLevel;
   GLuint samplerSave;
   GLint swizzle[4];
   GLboolean swizzleSaved = GL_FALSE;

   if (fallback_required(ctx, target, texObj)) {
      _mesa_generate_mipmap(ctx, target, texObj);
      return;
   }

   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) {
      faceTarget = target;
      target = GL_TEXTURE_CUBE_MAP;
   } else {
      faceTarget = target;
   }

   _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS);

   /* Choose between glsl version and fixed function version of
    * GenerateMipmap function.
    */
   if (use_glsl_version) {
      _mesa_meta_setup_vertex_objects(&mipmap->VAO, &mipmap->VBO, true,
                                      2, 4, 0);
      _mesa_meta_setup_blit_shader(ctx, target, false, &mipmap->shaders);
   } else {
      _mesa_meta_setup_ff_tnl_for_blit(&mipmap->VAO, &mipmap->VBO, 3);
      _mesa_set_enable(ctx, target, GL_TRUE);
   }

   samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ?
      ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0;

   if (currentTexUnitSave != 0)
      glBindTexture(target, texObj->Name);

   if (!mipmap->Sampler) {
      glGenSamplers(1, &mipmap->Sampler);
      glBindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler);

      glSamplerParameteri(mipmap->Sampler,
                              GL_TEXTURE_MIN_FILTER,
                              GL_LINEAR_MIPMAP_LINEAR);
      glSamplerParameteri(mipmap->Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glSamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
      glSamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
      glSamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

      /* We don't want to encode or decode sRGB values; treat them as linear.
       * This is not technically correct for GLES3 but we don't get any API
       * error at the moment.
       */
      if (ctx->Extensions.EXT_texture_sRGB_decode) {
         glSamplerParameteri(mipmap->Sampler, GL_TEXTURE_SRGB_DECODE_EXT,
               GL_SKIP_DECODE_EXT);
      }
   } else {
      glBindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler);
   }

   assert(mipmap->FBO != 0);
   glBindFramebuffer(GL_FRAMEBUFFER, mipmap->FBO);

   glTexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE);

//   if (texObj->_Swizzle != SWIZZLE_NOOP) {
//      static const GLint swizzleNoop[4] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
//      memcpy(swizzle, texObj->Swizzle, sizeof(swizzle));
//      swizzleSaved = GL_TRUE;
//      glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzleNoop);
//   }

   /* Silence valgrind warnings about reading uninitialized stack. */
   memset(verts, 0, sizeof(verts));

   /* setup vertex positions */
   verts[0].x = -1.0F;
   verts[0].y = -1.0F;
   verts[1].x =  1.0F;
   verts[1].y = -1.0F;
   verts[2].x =  1.0F;
   verts[2].y =  1.0F;
   verts[3].x = -1.0F;
   verts[3].y =  1.0F;

   /* texture is already locked, unlock now */
   _mesa_unlock_texture(ctx, texObj);

   for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) {
      const struct gl_texture_image *srcImage;
      struct gl_texture_image *dstImage;
      const GLuint srcLevel = dstLevel - 1;
      GLuint layer;
      GLsizei srcWidth, srcHeight, srcDepth;
      GLsizei dstWidth, dstHeight, dstDepth;

      srcImage = _mesa_select_tex_image(texObj, faceTarget, srcLevel);
      assert(srcImage->Border == 0);

      /* src size */
      srcWidth = srcImage->Width;
      if (target == GL_TEXTURE_1D_ARRAY) {
         srcHeight = 1;
         srcDepth = srcImage->Height;
      } else {
         srcHeight = srcImage->Height;
         srcDepth = srcImage->Depth;
      }

      /* new dst size */
      dstWidth = minify(srcWidth, 1);
      dstHeight = minify(srcHeight, 1);
//      dstDepth = target == GL_TEXTURE_3D ? minify(srcDepth, 1) : srcDepth;
      dstDepth = srcDepth;

      if (dstWidth == srcWidth &&
          dstHeight == srcHeight &&
          dstDepth == srcDepth) {
         /* all done */
         break;
      }

      /* Allocate storage for the destination mipmap image(s) */

      /* Set MaxLevel large enough to hold the new level when we allocate it */
      glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel);

      if (!prepare_mipmap_level(ctx, texObj, dstLevel,
                                dstWidth, dstHeight, dstDepth,
                                srcImage->InternalFormat,
                                srcImage->TexFormat)) {
         /* All done.  We either ran out of memory or we would go beyond the
          * last valid level of an immutable texture if we continued.
          */
         break;
      }
      dstImage = _mesa_select_tex_image(texObj, faceTarget, dstLevel);

      /* limit minification to src level */
      glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel);

      /* setup viewport */
      _mesa_set_viewport(ctx, 0, 0, 0, dstWidth, dstHeight);
      glDrawBuffer(GL_COLOR_ATTACHMENT0);

      for (layer = 0; layer < dstDepth; ++layer) {
         /* Setup texture coordinates */
         _mesa_meta_setup_texture_coords(faceTarget,
                                         layer,
                                         0, 0, 1, /* width, height never used here */
                                         verts[0].tex,
                                         verts[1].tex,
                                         verts[2].tex,
                                         verts[3].tex);

         /* upload vertex data */
         glBufferData(GL_ARRAY_BUFFER, sizeof(verts),
                          verts, GL_DYNAMIC_DRAW);

         _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dstImage, layer);

         /* sanity check */
         if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
             GL_FRAMEBUFFER_COMPLETE) {
            _mesa_problem(ctx, "Unexpected incomplete framebuffer in "
                          "_mesa_meta_GenerateMipmap()");
            break;
         }

         assert(dstWidth == ctx->DrawBuffer->Width);
         if (target == GL_TEXTURE_1D_ARRAY) {
            assert(dstHeight == 1);
         } else {
            assert(dstHeight == ctx->DrawBuffer->Height);
         }

         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
      }
   }

   _mesa_lock_texture(ctx, texObj); /* relock */

   glBindSampler(ctx->Texture.CurrentUnit, samplerSave);

   _mesa_meta_end(ctx);

   glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave);
   if (genMipmapSave)
      glTexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave);
//   if (swizzleSaved)
//      glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
}
Example #23
0
void
brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt)
{
   switch (mt->target) {
   case GL_TEXTURE_CUBE_MAP_ARRAY:
      brw_miptree_layout_texture_array(intel, mt);
      break;

   case GL_TEXTURE_CUBE_MAP:
      if (intel->gen >= 5) {
	 /* 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.
	  */
	 brw_miptree_layout_texture_array(intel, mt);
	 break;
      }
      assert(mt->physical_depth0 == 6);
      /* FALLTHROUGH */

   case GL_TEXTURE_3D: {
      GLuint width  = mt->physical_width0;
      GLuint height = mt->physical_height0;
      GLuint depth = mt->physical_depth0;
      GLuint pack_x_pitch, pack_x_nr;
      GLuint pack_y_pitch;
      GLuint level;

      mt->total_height = 0;

      if (mt->compressed) {
          mt->total_width = ALIGN(width, mt->align_w);
          pack_y_pitch = (height + 3) / 4;
      } else {
	 mt->total_width = mt->physical_width0;
	 pack_y_pitch = ALIGN(mt->physical_height0, mt->align_h);
      }

      pack_x_pitch = width;
      pack_x_nr = 1;

      for (level = mt->first_level ; level <= mt->last_level ; level++) {
	 GLint x = 0;
	 GLint y = 0;
	 GLint q, j;

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

	 for (q = 0; q < depth; /* empty */) {
	    for (j = 0; j < pack_x_nr && q < depth; j++, q++) {
	       intel_miptree_set_image_offset(mt, level, q, x, y);
	       x += pack_x_pitch;
	    }
            if (x > mt->total_width)
               mt->total_width = x;

	    x = 0;
	    y += pack_y_pitch;
	 }


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

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

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

	    if (pack_y_pitch > 2) {
	       pack_y_pitch >>= 1;
	       pack_y_pitch = ALIGN(pack_y_pitch, mt->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.
       */
      if (mt->target == GL_TEXTURE_CUBE_MAP)
	 mt->total_height += 2;
      break;
   }
Example #24
0
	 y += pack_y_pitch;
      }

      mt->total_height += y;

      if (pack_x_pitch > 4) {
	 pack_x_pitch >>= 1;
	 pack_x_nr <<= 1;
	 assert(pack_x_pitch * pack_x_nr <= mt->total_width);
      }

      if (pack_y_pitch > 2) {
	 pack_y_pitch >>= 1;
      }

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

void
i945_miptree_layout(struct intel_mipmap_tree * mt)
{
   switch (mt->target) {
   case GL_TEXTURE_CUBE_MAP:
      if (mt->compressed)
	 i945_miptree_layout_cube(mt);
      else
	 i915_miptree_layout_cube(mt);
      break;
Example #25
0
static void
brw_miptree_layout_2d(struct intel_mipmap_tree *mt)
{
   unsigned x = 0;
   unsigned y = 0;
   unsigned width = mt->physical_width0;
   unsigned height = mt->physical_height0;
   unsigned depth = mt->physical_depth0; /* number of array layers. */

   mt->total_width = mt->physical_width0;

   if (mt->compressed) {
       mt->total_width = ALIGN(mt->physical_width0, mt->align_w);
   }

   /* May need to adjust width to accomodate the placement of
    * the 2nd mipmap.  This occurs when the alignment
    * constraints of mipmap placement push the right edge of the
    * 2nd mipmap out past the width of its parent.
    */
   if (mt->first_level != mt->last_level) {
       unsigned mip1_width;

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

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

   mt->total_height = 0;

   for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
      unsigned img_height;

      intel_miptree_set_level_info(mt, level, x, y, width,
				   height, depth);

      img_height = ALIGN(height, mt->align_h);
      if (mt->compressed)
	 img_height /= mt->align_h;

      /* Because the images are packed better, the final offset
       * might not be the maximal one:
       */
      mt->total_height = MAX2(mt->total_height, y + img_height);

      /* Layout_below: step right after second mipmap.
       */
      if (level == mt->first_level + 1) {
	 x += ALIGN(width, mt->align_w);
      } else {
	 y += img_height;
      }

      width  = minify(width, 1);
      height = minify(height, 1);
   }
}
Example #26
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;
   }
Example #27
0
GLboolean
i915_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt)
{
   GLint level;

   switch (mt->target) {
   case GL_TEXTURE_CUBE_MAP:{
         const GLuint dim = mt->width0;
         GLuint face;
         GLuint lvlWidth = mt->width0, lvlHeight = mt->height0;

         assert(lvlWidth == lvlHeight); /* cubemap images are square */

         /* double pitch for cube layouts */
         mt->pitch = intel_miptree_pitch_align (intel, mt, dim * 2);
         mt->total_height = dim * 4;

         for (level = mt->first_level; level <= mt->last_level; level++) {
            intel_miptree_set_level_info(mt, level, 6,
                                         0, 0,
                                         /*OLD: mt->pitch, mt->total_height,*/
                                         lvlWidth, lvlHeight,
                                         1);
            lvlWidth /= 2;
            lvlHeight /= 2;
         }

         for (face = 0; face < 6; face++) {
            GLuint x = initial_offsets[face][0] * dim;
            GLuint y = initial_offsets[face][1] * dim;
            GLuint d = dim;

            for (level = mt->first_level; level <= mt->last_level; level++) {
               intel_miptree_set_image_offset(mt, level, face, x, y);

               if (d == 0)
                  _mesa_printf("cube mipmap %d/%d (%d..%d) is 0x0\n",
                               face, level, mt->first_level, mt->last_level);

               d >>= 1;
               x += step_offsets[face][0] * d;
               y += step_offsets[face][1] * d;
            }
         }
         break;
      }
   case GL_TEXTURE_3D:{
         GLuint width = mt->width0;
         GLuint height = mt->height0;
         GLuint depth = mt->depth0;
         GLuint stack_height = 0;

         /* Calculate the size of a single slice. 
          */
         mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);

         /* XXX: hardware expects/requires 9 levels at minimum.
          */
         for (level = mt->first_level; level <= MAX2(8, mt->last_level);
              level++) {
            intel_miptree_set_level_info(mt, level, depth, 0, mt->total_height,
                                         width, height, depth);


            stack_height += MAX2(2, height);

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

         /* Fixup depth image_offsets: 
          */
         depth = mt->depth0;
         for (level = mt->first_level; level <= mt->last_level; level++) {
            GLuint i;
            for (i = 0; i < depth; i++) 
               intel_miptree_set_image_offset(mt, level, i,
                                              0, i * stack_height);

            depth = minify(depth);
         }


         /* Multiply slice size by texture depth for total size.  It's
          * remarkable how wasteful of memory the i915 texture layouts
          * are.  They are largely fixed in the i945.
          */
         mt->total_height = stack_height * mt->depth0;
         break;
      }

   default:{
         GLuint width = mt->width0;
         GLuint height = mt->height0;
	 GLuint img_height;

         mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
         mt->total_height = 0;

         for (level = mt->first_level; level <= mt->last_level; level++) {
            intel_miptree_set_level_info(mt, level, 1,
                                         0, mt->total_height,
                                         width, height, 1);

            if (mt->compressed)
               img_height = MAX2(1, height / 4);
            else
               img_height = (MAX2(2, height) + 1) & ~1;

	    mt->total_height += img_height;

            width = minify(width);
            height = minify(height);
         }
         break;
      }
   }
   DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
       mt->pitch,
       mt->total_height, mt->cpp, mt->pitch * mt->total_height * mt->cpp);

   return GL_TRUE;
}
Example #28
0
static void
brw_miptree_layout_2d(struct intel_mipmap_tree *mt)
{
   unsigned x = 0;
   unsigned y = 0;
   unsigned width = mt->physical_width0;
   unsigned height = mt->physical_height0;
   unsigned depth = mt->physical_depth0; /* number of array layers. */
   unsigned int bw, bh;

   _mesa_get_format_block_size(mt->format, &bw, &bh);

   mt->total_width = mt->physical_width0;

   if (mt->compressed)
       mt->total_width = ALIGN_NPOT(mt->total_width, bw);

   /* May need to adjust width to accommodate the placement of
    * the 2nd mipmap.  This occurs when the alignment
    * constraints of mipmap placement push the right edge of the
    * 2nd mipmap out past the width of its parent.
    */
   if (mt->first_level != mt->last_level) {
       unsigned mip1_width;

       if (mt->compressed) {
          mip1_width = ALIGN_NPOT(minify(mt->physical_width0, 1), mt->align_w) +
             ALIGN_NPOT(minify(mt->physical_width0, 2), bw);
       } else {
          mip1_width = ALIGN_NPOT(minify(mt->physical_width0, 1), mt->align_w) +
             minify(mt->physical_width0, 2);
       }

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

   mt->total_width /= bw;
   mt->total_height = 0;

   for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
      unsigned img_height;

      intel_miptree_set_level_info(mt, level, x, y, depth);

      img_height = ALIGN_NPOT(height, mt->align_h);
      if (mt->compressed)
	 img_height /= bh;

      if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) {
         /* Compact arrays with separated miplevels */
         img_height *= depth;
      }

      /* Because the images are packed better, the final offset
       * might not be the maximal one:
       */
      mt->total_height = MAX2(mt->total_height, y + img_height);

      /* Layout_below: step right after second mipmap.
       */
      if (level == mt->first_level + 1) {
	 x += ALIGN_NPOT(width, mt->align_w) / bw;
      } else {
	 y += img_height;
      }

      width  = minify(width, 1);
      height = minify(height, 1);

      if (mt->target == GL_TEXTURE_3D)
         depth = minify(depth, 1);
   }
}
/**
 * The GenerateMipmap() driver hook.
 */
void
brw_generate_mipmap(struct gl_context *ctx, GLenum target,
                    struct gl_texture_object *tex_obj)
{
   struct brw_context *brw = brw_context(ctx);
   struct gen_device_info *devinfo = &brw->screen->devinfo;
   struct intel_texture_object *intel_obj = intel_texture_object(tex_obj);
   const unsigned base_level = tex_obj->BaseLevel;
   unsigned last_level, first_layer, last_layer;

   /* Blorp doesn't handle combined depth/stencil surfaces on Gen4-5 yet. */
   if (devinfo->gen <= 5 &&
       (tex_obj->Image[0][base_level]->_BaseFormat == GL_DEPTH_COMPONENT ||
        tex_obj->Image[0][base_level]->_BaseFormat == GL_DEPTH_STENCIL)) {
      _mesa_meta_GenerateMipmap(ctx, target, tex_obj);
      return;
   }

   /* find expected last mipmap level to generate */
   last_level = _mesa_compute_num_levels(ctx, tex_obj, target) - 1;

   if (last_level == 0)
      return;

   /* The texture isn't in a "complete" state yet so set the expected
    * last_level here; we're not going through normal texture validation.
    */
   intel_obj->_MaxLevel = last_level;

   if (!tex_obj->Immutable) {
      _mesa_prepare_mipmap_levels(ctx, tex_obj, base_level, last_level);

      /* At this point, memory for all the texture levels has been
       * allocated.  However, the base level image may be in one resource
       * while the subsequent/smaller levels may be in another resource.
       * Finalizing the texture will copy the base images from the former
       * resource to the latter.
       *
       * After this, we'll have all mipmap levels in one resource.
       */
      intel_finalize_mipmap_tree(brw, tex_obj);
   }

   struct intel_mipmap_tree *mt = intel_obj->mt;
   if (!mt) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "mipmap generation");
      return;
   }

   const mesa_format format = intel_obj->_Format;

   /* Fall back to the CPU for non-renderable cases.
    *
    * TODO: 3D textures require blending data from multiple slices,
    * which means we need custom shaders.  For now, fall back.
    */
   if (!brw->mesa_format_supports_render[format] || target == GL_TEXTURE_3D) {
      _mesa_generate_mipmap(ctx, target, tex_obj);
      return;
   }

   const struct isl_extent4d *base_size = &mt->surf.logical_level0_px;

   if (mt->target == GL_TEXTURE_CUBE_MAP) {
      first_layer = _mesa_tex_target_to_face(target);
      last_layer = first_layer;
   } else {
      first_layer = 0;
      last_layer = base_size->array_len - 1;
   }

   /* The GL_EXT_texture_sRGB_decode extension's issues section says:
    *
    *    "10) How is mipmap generation of sRGB textures affected by the
    *     TEXTURE_SRGB_DECODE_EXT parameter?
    *
    *     RESOLVED:  When the TEXTURE_SRGB_DECODE parameter is DECODE_EXT
    *     for an sRGB texture, mipmap generation should decode sRGB texels
    *     to a linear RGB color space, perform downsampling, then encode
    *     back to an sRGB color space.  (Issue 24 in the EXT_texture_sRGB
    *     specification provides a rationale for why.)  When the parameter
    *     is SKIP_DECODE_EXT instead, mipmap generation skips the encode
    *     and decode steps during mipmap generation.  By skipping the
    *     encode and decode steps, sRGB mipmap generation should match
    *     the mipmap generation for a non-sRGB texture."
    */
   bool do_srgb = tex_obj->Sampler.sRGBDecode == GL_DECODE_EXT;

   for (unsigned dst_level = base_level + 1;
        dst_level <= last_level;
        dst_level++) {

      const unsigned src_level = dst_level - 1;

      for (unsigned layer = first_layer; layer <= last_layer; layer++) {
         brw_blorp_blit_miptrees(brw, mt, src_level, layer, format,
                                 SWIZZLE_XYZW, mt, dst_level, layer, format,
                                 0, 0,
                                 minify(base_size->width, src_level),
                                 minify(base_size->height, src_level),
                                 0, 0,
                                 minify(base_size->width, dst_level),
                                 minify(base_size->height, dst_level),
                                 GL_LINEAR, false, false,
                                 do_srgb, do_srgb);
      }
   }
}
Example #30
0
GLboolean
i945_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt)
{
   GLint level;

   switch (mt->target) {
   case GL_TEXTURE_CUBE_MAP:{
         const GLuint dim = mt->width0;
         GLuint face;
         GLuint lvlWidth = mt->width0, lvlHeight = mt->height0;

         assert(lvlWidth == lvlHeight); /* cubemap images are square */

         /* Depending on the size of the largest images, pitch can be
          * determined either by the old-style packing of cubemap faces,
          * or the final row of 4x4, 2x2 and 1x1 faces below this. 
          */
         if (dim > 32)
            mt->pitch = intel_miptree_pitch_align (intel, mt, dim);
         else
            mt->pitch = 14 * 8;

         mt->total_height = dim * 4 + 4;

         /* Set all the levels to effectively occupy the whole rectangular region. 
          */
         for (level = mt->first_level; level <= mt->last_level; level++) {
            intel_miptree_set_level_info(mt, level, 6,
                                         0, 0,
                                         lvlWidth, lvlHeight, 1);
	    lvlWidth /= 2;
	    lvlHeight /= 2;
	 }


         for (face = 0; face < 6; face++) {
            GLuint x = initial_offsets[face][0] * dim;
            GLuint y = initial_offsets[face][1] * dim;
            GLuint d = dim;

            if (dim == 4 && face >= 4) {
               y = mt->total_height - 4;
               x = (face - 4) * 8;
            }
            else if (dim < 4 && (face > 0 || mt->first_level > 0)) {
               y = mt->total_height - 4;
               x = face * 8;
            }

            for (level = mt->first_level; level <= mt->last_level; level++) {
               intel_miptree_set_image_offset(mt, level, face, x, y);

               d >>= 1;

               switch (d) {
               case 4:
                  switch (face) {
                  case FACE_POS_X:
                  case FACE_NEG_X:
                     x += step_offsets[face][0] * d;
                     y += step_offsets[face][1] * d;
                     break;
                  case FACE_POS_Y:
                  case FACE_NEG_Y:
                     y += 12;
                     x -= 8;
                     break;
                  case FACE_POS_Z:
                  case FACE_NEG_Z:
                     y = mt->total_height - 4;
                     x = (face - 4) * 8;
                     break;
                  }

               case 2:
                  y = mt->total_height - 4;
                  x = 16 + face * 8;
                  break;

               case 1:
                  x += 48;
                  break;

               default:
                  x += step_offsets[face][0] * d;
                  y += step_offsets[face][1] * d;
                  break;
               }
            }
         }
         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;

         mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
         mt->total_height = 0;

         pack_y_pitch = MAX2(mt->height0, 2);
         pack_x_pitch = mt->pitch;
         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;

            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;
            }

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