summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/drivers/dri/i915/i830_vtbl.c9
-rw-r--r--src/mesa/drivers/dri/i915/i915_vtbl.c9
-rw-r--r--src/mesa/drivers/dri/i965/Makefile.sources1
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.c66
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.h37
-rw-r--r--src/mesa/drivers/dri/i965/brw_defines.h9
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw.c105
-rw-r--r--src/mesa/drivers/dri/i965/brw_misc_state.c22
-rw-r--r--src/mesa/drivers/dri/i965/brw_state_upload.c1
-rw-r--r--src/mesa/drivers/dri/i965/brw_tex_layout.c43
-rw-r--r--src/mesa/drivers/dri/i965/brw_vtbl.c37
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_surface_state.c10
-rw-r--r--src/mesa/drivers/dri/i965/gen6_clip_state.c20
-rw-r--r--src/mesa/drivers/dri/i965/gen6_depthstencil.c11
-rw-r--r--src/mesa/drivers/dri/i965/gen6_hiz.c312
-rw-r--r--src/mesa/drivers/dri/i965/gen6_hiz.h16
-rw-r--r--src/mesa/drivers/dri/i965/gen6_sf_state.c18
-rw-r--r--src/mesa/drivers/dri/i965/gen6_wm_state.c20
-rw-r--r--src/mesa/drivers/dri/i965/gen7_misc_state.c11
-rw-r--r--src/mesa/drivers/dri/i965/gen7_wm_surface_state.c2
l---------src/mesa/drivers/dri/i965/intel_resolve_map.c1
-rw-r--r--src/mesa/drivers/dri/intel/intel_blit.c21
-rw-r--r--src/mesa/drivers/dri/intel/intel_buffer_objects.c8
-rw-r--r--src/mesa/drivers/dri/intel/intel_buffers.c9
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.c81
-rw-r--r--src/mesa/drivers/dri/intel/intel_context.h13
-rw-r--r--src/mesa/drivers/dri/intel/intel_fbo.c510
-rw-r--r--src/mesa/drivers/dri/intel/intel_fbo.h92
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.c496
-rw-r--r--src/mesa/drivers/dri/intel/intel_mipmap_tree.h211
-rw-r--r--src/mesa/drivers/dri/intel/intel_pixel_copy.c5
-rw-r--r--src/mesa/drivers/dri/intel/intel_resolve_map.c111
-rw-r--r--src/mesa/drivers/dri/intel/intel_resolve_map.h83
-rw-r--r--src/mesa/drivers/dri/intel/intel_screen.c11
-rw-r--r--src/mesa/drivers/dri/intel/intel_span.c149
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex.c46
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_copy.c14
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_image.c132
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_layout.c128
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_layout.h10
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_obj.h30
-rw-r--r--src/mesa/drivers/dri/intel/intel_tex_validate.c2
42 files changed, 2130 insertions, 792 deletions
diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c
index 86c805148cd..d29f9799a86 100644
--- a/src/mesa/drivers/dri/i915/i830_vtbl.c
+++ b/src/mesa/drivers/dri/i915/i830_vtbl.c
@@ -885,13 +885,6 @@ i830_is_hiz_depth_format(struct intel_context *intel, gl_format format)
return false;
}
-static void
-i830_hiz_resolve_noop(struct intel_context *intel,
- struct intel_region *region)
-{
- /* empty */
-}
-
void
i830InitVtbl(struct i830_context *i830)
{
@@ -910,6 +903,4 @@ i830InitVtbl(struct i830_context *i830)
i830->intel.vtbl.invalidate_state = i830_invalidate_state;
i830->intel.vtbl.render_target_supported = i830_render_target_supported;
i830->intel.vtbl.is_hiz_depth_format = i830_is_hiz_depth_format;
- i830->intel.vtbl.hiz_resolve_depthbuffer = i830_hiz_resolve_noop;
- i830->intel.vtbl.hiz_resolve_hizbuffer = i830_hiz_resolve_noop;
}
diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c
index fa02dfa3654..072a692767a 100644
--- a/src/mesa/drivers/dri/i915/i915_vtbl.c
+++ b/src/mesa/drivers/dri/i915/i915_vtbl.c
@@ -853,13 +853,6 @@ i915_is_hiz_depth_format(struct intel_context *intel,
}
static void
-i915_hiz_resolve_noop(struct intel_context *intel,
- struct intel_region *region)
-{
- /* empty */
-}
-
-static void
i915_invalidate_state(struct intel_context *intel, GLuint new_state)
{
struct gl_context *ctx = &intel->ctx;
@@ -887,6 +880,4 @@ i915InitVtbl(struct i915_context *i915)
i915->intel.vtbl.invalidate_state = i915_invalidate_state;
i915->intel.vtbl.render_target_supported = i915_render_target_supported;
i915->intel.vtbl.is_hiz_depth_format = i915_is_hiz_depth_format;
- i915->intel.vtbl.hiz_resolve_depthbuffer = i915_hiz_resolve_noop;
- i915->intel.vtbl.hiz_resolve_hizbuffer = i915_hiz_resolve_noop;
}
diff --git a/src/mesa/drivers/dri/i965/Makefile.sources b/src/mesa/drivers/dri/i965/Makefile.sources
index 1b9ca6f2321..cd6a8f48b5a 100644
--- a/src/mesa/drivers/dri/i965/Makefile.sources
+++ b/src/mesa/drivers/dri/i965/Makefile.sources
@@ -15,6 +15,7 @@ i965_C_SOURCES := \
intel_fbo.c \
intel_mipmap_tree.c \
intel_regions.c \
+ intel_resolve_map.c \
intel_screen.c \
intel_span.c \
intel_pixel.c \
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index 9b506a6529f..531ce5bd0d8 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -33,11 +33,23 @@
#include "main/imports.h"
#include "main/macros.h"
#include "main/simple_list.h"
+
+#include "vbo/vbo_context.h"
+
#include "brw_context.h"
#include "brw_defines.h"
#include "brw_draw.h"
#include "brw_state.h"
+
+#include "gen6_hiz.h"
+
+#include "intel_fbo.h"
+#include "intel_mipmap_tree.h"
+#include "intel_regions.h"
#include "intel_span.h"
+#include "intel_tex.h"
+#include "intel_tex_obj.h"
+
#include "tnl/t_pipeline.h"
#include "glsl/ralloc.h"
@@ -45,12 +57,66 @@
* Mesa's Driver Functions
***************************************/
+/**
+ * \brief Prepare for entry into glBegin/glEnd block.
+ *
+ * Resolve buffers before entering a glBegin/glEnd block. This is
+ * necessary to prevent recursive calls to FLUSH_VERTICES.
+ *
+ * This resolves the depth buffer of each enabled depth texture and the HiZ
+ * buffer of the attached depth renderbuffer.
+ *
+ * Details
+ * -------
+ * When vertices are queued during a glBegin/glEnd block, those vertices must
+ * be drawn before any rendering state changes. To ensure this, Mesa calls
+ * FLUSH_VERTICES as a prehook to such state changes. Therefore,
+ * FLUSH_VERTICES itself cannot change rendering state without falling into a
+ * recursive trap.
+ *
+ * This precludes meta-ops, namely buffer resolves, from occurring while any
+ * vertices are queued. To prevent that situation, we resolve some buffers on
+ * entering a glBegin/glEnd
+ *
+ * \see brwCleanupExecEnd()
+ */
+static void brwPrepareExecBegin(struct gl_context *ctx)
+{
+ struct brw_context *brw = brw_context(ctx);
+ struct intel_context *intel = &brw->intel;
+ struct intel_renderbuffer *draw_irb;
+ struct intel_texture_object *tex_obj;
+
+ if (!intel->has_hiz) {
+ /* The context uses no feature that requires buffer resolves. */
+ return;
+ }
+
+ /* Resolve each enabled texture. */
+ for (int i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (!ctx->Texture.Unit[i]._ReallyEnabled)
+ continue;
+ tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current);
+ if (!tex_obj || !tex_obj->mt)
+ continue;
+ intel_miptree_all_slices_resolve_depth(intel, tex_obj->mt);
+ }
+
+ /* Resolve the attached depth buffer. */
+ draw_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH);
+ if (draw_irb) {
+ intel_renderbuffer_resolve_hiz(intel, draw_irb);
+ }
+}
+
static void brwInitDriverFunctions( struct dd_function_table *functions )
{
intelInitDriverFunctions( functions );
brwInitFragProgFuncs( functions );
brw_init_queryobj_functions(functions);
+
+ functions->PrepareExecBegin = brwPrepareExecBegin;
}
bool
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index e5d2d140b1e..ec05fb75869 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -144,6 +144,7 @@ enum brw_state_id {
BRW_STATE_VS_CONSTBUF,
BRW_STATE_PROGRAM_CACHE,
BRW_STATE_STATE_BASE_ADDRESS,
+ BRW_STATE_HIZ,
};
#define BRW_NEW_URB_FENCE (1 << BRW_STATE_URB_FENCE)
@@ -172,6 +173,7 @@ enum brw_state_id {
#define BRW_NEW_VS_CONSTBUF (1 << BRW_STATE_VS_CONSTBUF)
#define BRW_NEW_PROGRAM_CACHE (1 << BRW_STATE_PROGRAM_CACHE)
#define BRW_NEW_STATE_BASE_ADDRESS (1 << BRW_STATE_STATE_BASE_ADDRESS)
+#define BRW_NEW_HIZ (1 << BRW_STATE_HIZ)
struct brw_state_flags {
/** State update flags signalled by mesa internals */
@@ -899,6 +901,41 @@ struct brw_context
enum state_struct_type type;
} *state_batch_list;
int state_batch_count;
+
+ /**
+ * \brief State needed to execute HiZ meta-ops
+ *
+ * All fields except \c op are initialized by gen6_hiz_init().
+ */
+ struct brw_hiz_state {
+ /**
+ * \brief Indicates which HiZ operation is in progress.
+ *
+ * See the following sections of the Sandy Bridge PRM, Volume 1, Part2:
+ * - 7.5.3.1 Depth Buffer Clear
+ * - 7.5.3.2 Depth Buffer Resolve
+ * - 7.5.3.3 Hierarchical Depth Buffer Resolve
+ */
+ enum brw_hiz_op {
+ BRW_HIZ_OP_NONE = 0,
+ BRW_HIZ_OP_DEPTH_CLEAR,
+ BRW_HIZ_OP_DEPTH_RESOLVE,
+ BRW_HIZ_OP_HIZ_RESOLVE,
+ } op;
+
+ /** \brief Shader state */
+ struct {
+ GLuint program;
+ GLuint position_vbo;
+ GLint position_location;
+ } shader;
+
+ /** \brief VAO for the rectangle primitive's vertices. */
+ GLuint vao;
+
+ GLuint fbo;
+ struct gl_renderbuffer *depth_rb;
+ } hiz;
};
diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h
index 746c89f87cc..bb79bfbafdf 100644
--- a/src/mesa/drivers/dri/i965/brw_defines.h
+++ b/src/mesa/drivers/dri/i965/brw_defines.h
@@ -458,10 +458,11 @@
#define BRW_SURFACE_MIN_LOD_MASK INTEL_MASK(31, 28)
/* Surface state DW5 */
-#define BRW_SURFACE_X_OFFSET_SHIFT 25
-#define BRW_SURFACE_X_OFFSET_MASK INTEL_MASK(31, 25)
-#define BRW_SURFACE_Y_OFFSET_SHIFT 20
-#define BRW_SURFACE_Y_OFFSET_MASK INTEL_MASK(23, 20)
+#define BRW_SURFACE_X_OFFSET_SHIFT 25
+#define BRW_SURFACE_X_OFFSET_MASK INTEL_MASK(31, 25)
+#define BRW_SURFACE_VERTICAL_ALIGN_ENABLE (1 << 24)
+#define BRW_SURFACE_Y_OFFSET_SHIFT 20
+#define BRW_SURFACE_Y_OFFSET_MASK INTEL_MASK(23, 20)
#define BRW_TEXCOORDMODE_WRAP 0
#define BRW_TEXCOORDMODE_MIRROR 1
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index 1571fb74d6c..bf3c95cbebc 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -44,6 +44,9 @@
#include "brw_state.h"
#include "intel_batchbuffer.h"
+#include "intel_fbo.h"
+#include "intel_mipmap_tree.h"
+#include "intel_regions.h"
#define FILE_DEBUG_FLAG DEBUG_PRIMS
@@ -117,10 +120,17 @@ static void brw_set_prim(struct brw_context *brw,
static void gen6_set_prim(struct brw_context *brw,
const struct _mesa_prim *prim)
{
- uint32_t hw_prim = prim_to_hw_prim[prim->mode];
+ uint32_t hw_prim;
DBG("PRIM: %s\n", _mesa_lookup_enum_by_nr(prim->mode));
+ if (brw->hiz.op) {
+ assert(prim->mode == GL_TRIANGLES);
+ hw_prim = _3DPRIM_RECTLIST;
+ } else {
+ hw_prim = prim_to_hw_prim[prim->mode];
+ }
+
if (hw_prim != brw->primitive) {
brw->primitive = hw_prim;
brw->state.dirty.brw |= BRW_NEW_PRIMITIVE;
@@ -280,6 +290,93 @@ static void brw_merge_inputs( struct brw_context *brw,
brw->state.dirty.brw |= BRW_NEW_INPUT_DIMENSIONS;
}
+/*
+ * \brief Resolve buffers before drawing.
+ *
+ * Resolve the depth buffer's HiZ buffer and resolve the depth buffer of each
+ * enabled depth texture.
+ *
+ * (In the future, this will also perform MSAA resolves).
+ */
+static void
+brw_predraw_resolve_buffers(struct brw_context *brw)
+{
+ struct gl_context *ctx = &brw->intel.ctx;
+ struct intel_context *intel = &brw->intel;
+ struct intel_renderbuffer *depth_irb;
+ struct intel_texture_object *tex_obj;
+ bool did_resolve = false;
+
+ /* Avoid recursive HiZ op. */
+ if (brw->hiz.op) {
+ return;
+ }
+
+ /* Resolve the depth buffer's HiZ buffer. */
+ depth_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH);
+ if (depth_irb && depth_irb->mt) {
+ did_resolve |= intel_renderbuffer_resolve_hiz(intel, depth_irb);
+ }
+
+ /* Resolve depth buffer of each enabled depth texture. */
+ for (int i = 0; i < BRW_MAX_TEX_UNIT; i++) {
+ if (!ctx->Texture.Unit[i]._ReallyEnabled)
+ continue;
+ tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current);
+ if (!tex_obj || !tex_obj->mt)
+ continue;
+ did_resolve |= intel_miptree_all_slices_resolve_depth(intel, tex_obj->mt);
+ }
+
+ if (did_resolve) {
+ /* Call vbo_bind_array() to synchronize the vbo module's vertex
+ * attributes to the gl_context's.
+ *
+ * Details
+ * -------
+ * The vbo module tracks vertex attributes separately from the
+ * gl_context. Specifically, the vbo module maintins vertex attributes
+ * in vbo_exec_context::array::inputs, which is synchronized with
+ * gl_context::Array::ArrayObj::VertexAttrib by vbo_bind_array().
+ * vbo_draw_arrays() calls vbo_bind_array() to perform the
+ * synchronization before calling the real draw call,
+ * vbo_context::draw_arrays.
+ *
+ * At this point (after performing a resolve meta-op but before calling
+ * vbo_bind_array), the gl_context's vertex attributes have been
+ * restored to their original state (that is, their state before the
+ * meta-op began), but the vbo module's vertex attribute are those used
+ * in the last meta-op. Therefore we must manually synchronize the two with
+ * vbo_bind_array() before continuing with the original draw command.
+ */
+ _mesa_update_state(ctx);
+ vbo_bind_arrays(ctx);
+ _mesa_update_state(ctx);
+ }
+}
+
+/**
+ * \brief Call this after drawing to mark which buffers need resolving
+ *
+ * If the depth buffer was written to and if it has an accompanying HiZ
+ * buffer, then mark that it needs a depth resolve.
+ *
+ * (In the future, this will also mark needed MSAA resolves).
+ */
+static void brw_postdraw_set_buffers_need_resolve(struct brw_context *brw)
+{
+ struct gl_context *ctx = &brw->intel.ctx;
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct intel_renderbuffer *depth_irb =
+ intel_get_renderbuffer(fb, BUFFER_DEPTH);
+
+ if (depth_irb &&
+ ctx->Depth.Mask &&
+ !brw->hiz.op) {
+ intel_renderbuffer_set_needs_depth_resolve(depth_irb);
+ }
+}
+
/* May fail if out of video memory for texture or vbo upload, or on
* fallback conditions.
*/
@@ -309,6 +406,11 @@ static bool brw_try_draw_prims( struct gl_context *ctx,
*/
brw_validate_textures( brw );
+ /* Resolves must occur after updating state and finalizing textures but
+ * before setting up any hardware state for this draw call.
+ */
+ brw_predraw_resolve_buffers(brw);
+
/* Bind all inputs, derive varying and size information:
*/
brw_merge_inputs( brw, arrays );
@@ -403,6 +505,7 @@ retry:
out:
brw_state_cache_check_size(brw);
+ brw_postdraw_set_buffers_need_resolve(brw);
return retval;
}
diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c
index 514c990ed25..17da46099ed 100644
--- a/src/mesa/drivers/dri/i965/brw_misc_state.c
+++ b/src/mesa/drivers/dri/i965/brw_misc_state.c
@@ -33,6 +33,7 @@
#include "intel_batchbuffer.h"
#include "intel_fbo.h"
+#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "brw_context.h"
@@ -204,9 +205,15 @@ static void emit_depthbuffer(struct brw_context *brw)
/* _NEW_BUFFERS */
struct intel_renderbuffer *depth_irb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
struct intel_renderbuffer *stencil_irb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
- struct intel_region *hiz_region = depth_irb ? depth_irb->hiz_region : NULL;
+ struct intel_region *hiz_region = NULL;
unsigned int len;
+ if (depth_irb &&
+ depth_irb->mt &&
+ depth_irb->mt->hiz_mt) {
+ hiz_region = depth_irb->mt->hiz_mt->region;
+ }
+
/* 3DSTATE_DEPTH_BUFFER, 3DSTATE_STENCIL_BUFFER are both
* non-pipelined state that will need the PIPE_CONTROL workaround.
*/
@@ -272,6 +279,8 @@ static void emit_depthbuffer(struct brw_context *brw)
* [DevGT]: This field must be set to the same value (enabled or
* disabled) as Hierarchical Depth Buffer Enable
*/
+ struct intel_region *region = stencil_irb->mt->region;
+
assert(intel->has_separate_stencil);
assert(stencil_irb->Base.Format == MESA_FORMAT_S8);
@@ -283,8 +292,8 @@ static void emit_depthbuffer(struct brw_context *brw)
(BRW_TILEWALK_YMAJOR << 26) |
(BRW_SURFACE_2D << 29));
OUT_BATCH(0);
- OUT_BATCH(((stencil_irb->region->width - 1) << 6) |
- (2 * stencil_irb->region->height - 1) << 19);
+ OUT_BATCH(((region->width - 1) << 6) |
+ (2 * region->height - 1) << 19);
OUT_BATCH(0);
OUT_BATCH(0);
@@ -294,7 +303,7 @@ static void emit_depthbuffer(struct brw_context *brw)
ADVANCE_BATCH();
} else {
- struct intel_region *region = depth_irb->region;
+ struct intel_region *region = depth_irb->mt->region;
unsigned int format;
uint32_t tile_x, tile_y, offset;
@@ -379,10 +388,11 @@ static void emit_depthbuffer(struct brw_context *brw)
/* Emit stencil buffer. */
if (stencil_irb) {
+ struct intel_region *region = stencil_irb->mt->region;
BEGIN_BATCH(3);
OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2));
- OUT_BATCH(stencil_irb->region->pitch * stencil_irb->region->cpp - 1);
- OUT_RELOC(stencil_irb->region->bo,
+ OUT_BATCH(region->pitch * region->cpp - 1);
+ OUT_RELOC(region->bo,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
0);
ADVANCE_BATCH();
diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c
index 730a0e8a12b..bd32815d08c 100644
--- a/src/mesa/drivers/dri/i965/brw_state_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_state_upload.c
@@ -368,6 +368,7 @@ static struct dirty_bit_map brw_bits[] = {
DEFINE_BIT(BRW_NEW_GS_BINDING_TABLE),
DEFINE_BIT(BRW_NEW_PS_BINDING_TABLE),
DEFINE_BIT(BRW_NEW_STATE_BASE_ADDRESS),
+ DEFINE_BIT(BRW_NEW_HIZ),
{0, 0, 0}
};
diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c
index d77bf4d7cd9..eaea49bf55f 100644
--- a/src/mesa/drivers/dri/i965/brw_tex_layout.c
+++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c
@@ -41,39 +41,31 @@
static void
brw_miptree_layout_texture_array(struct intel_context *intel,
- struct intel_mipmap_tree *mt,
- int slices)
+ struct intel_mipmap_tree *mt)
{
- GLuint align_w;
- GLuint align_h;
GLuint level;
GLuint qpitch = 0;
int h0, h1, q;
- intel_get_texture_alignment_unit(mt->format, &align_w, &align_h);
-
- h0 = ALIGN(mt->height0, align_h);
- h1 = ALIGN(minify(mt->height0), align_h);
- qpitch = (h0 + h1 + (intel->gen >= 7 ? 12 : 11) * align_h);
+ h0 = ALIGN(mt->height0, mt->align_h);
+ h1 = ALIGN(minify(mt->height0), mt->align_h);
+ qpitch = (h0 + h1 + (intel->gen >= 7 ? 12 : 11) * mt->align_h);
if (mt->compressed)
qpitch /= 4;
- i945_miptree_layout_2d(mt, slices);
+ i945_miptree_layout_2d(mt);
for (level = mt->first_level; level <= mt->last_level; level++) {
- for (q = 0; q < slices; q++) {
+ for (q = 0; q < mt->depth0; q++) {
intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch);
}
}
- mt->total_height = qpitch * slices;
+ mt->total_height = qpitch * mt->depth0;
}
void
brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt)
{
- /* XXX: these vary depending on image format: */
- /* GLint align_w = 4; */
-
switch (mt->target) {
case GL_TEXTURE_CUBE_MAP:
if (intel->gen >= 5) {
@@ -82,7 +74,7 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt)
* 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, 6);
+ brw_miptree_layout_texture_array(intel, mt);
break;
}
/* FALLTHROUGH */
@@ -94,18 +86,15 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt)
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->format, &align_w, &align_h);
if (mt->compressed) {
- mt->total_width = ALIGN(width, align_w);
+ mt->total_width = ALIGN(width, mt->align_w);
pack_y_pitch = (height + 3) / 4;
} else {
mt->total_width = mt->width0;
- pack_y_pitch = ALIGN(mt->height0, align_h);
+ pack_y_pitch = ALIGN(mt->height0, mt->align_h);
}
pack_x_pitch = width;
@@ -117,7 +106,7 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt)
GLint y = 0;
GLint q, j;
- intel_miptree_set_level_info(mt, level, nr_images,
+ intel_miptree_set_level_info(mt, level,
0, mt->total_height,
width, height, depth);
@@ -140,8 +129,8 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt)
if (mt->compressed) {
pack_y_pitch = (height + 3) / 4;
- if (pack_x_pitch > ALIGN(width, align_w)) {
- pack_x_pitch = ALIGN(width, align_w);
+ if (pack_x_pitch > ALIGN(width, mt->align_w)) {
+ pack_x_pitch = ALIGN(width, mt->align_w);
pack_x_nr <<= 1;
}
} else {
@@ -153,7 +142,7 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt)
if (pack_y_pitch > 2) {
pack_y_pitch >>= 1;
- pack_y_pitch = ALIGN(pack_y_pitch, align_h);
+ pack_y_pitch = ALIGN(pack_y_pitch, mt->align_h);
}
}
@@ -170,11 +159,11 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt)
case GL_TEXTURE_2D_ARRAY:
case GL_TEXTURE_1D_ARRAY:
- brw_miptree_layout_texture_array(intel, mt, mt->depth0);
+ brw_miptree_layout_texture_array(intel, mt);
break;
default:
- i945_miptree_layout_2d(mt, 1);
+ i945_miptree_layout_2d(mt);
break;
}
DBG("%s: %dx%dx%d\n", __FUNCTION__,
diff --git a/src/mesa/drivers/dri/i965/brw_vtbl.c b/src/mesa/drivers/dri/i965/brw_vtbl.c
index 7c40f278b8a..dd2e05a3669 100644
--- a/src/mesa/drivers/dri/i965/brw_vtbl.c
+++ b/src/mesa/drivers/dri/i965/brw_vtbl.c
@@ -95,7 +95,7 @@ brw_update_draw_buffer(struct intel_context *intel)
{
struct gl_context *ctx = &intel->ctx;
struct gl_framebuffer *fb = ctx->DrawBuffer;
- struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
+ struct intel_renderbuffer *irbStencil = NULL;
bool fb_has_hiz = intel_framebuffer_has_hiz(fb);
if (!fb) {
@@ -103,27 +103,7 @@ brw_update_draw_buffer(struct intel_context *intel)
return;
}
- /*
- * If intel_context is using separate stencil, but the depth attachment
- * (gl_framebuffer.Attachment[BUFFER_DEPTH]) has a packed depth/stencil
- * format, then we must install the real depth buffer at fb->_DepthBuffer
- * and set fb->_DepthBuffer->Wrapped before calling _mesa_update_framebuffer.
- * Otherwise, _mesa_update_framebuffer will create and install a swras
- * depth wrapper instead.
- *
- * Ditto for stencil.
- */
- irbDepth = intel_get_renderbuffer(fb, BUFFER_DEPTH);
- if (irbDepth && irbDepth->Base.Format == MESA_FORMAT_X8_Z24) {
- _mesa_reference_renderbuffer(&fb->_DepthBuffer, &irbDepth->Base);
- irbDepth->Base.Wrapped = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
- }
-
irbStencil = intel_get_renderbuffer(fb, BUFFER_STENCIL);
- if (irbStencil && irbStencil->Base.Format == MESA_FORMAT_S8) {
- _mesa_reference_renderbuffer(&fb->_StencilBuffer, &irbStencil->Base);
- irbStencil->Base.Wrapped = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
- }
/* Do this here, not core Mesa, since this function is called from
* many places within the driver.
@@ -146,7 +126,7 @@ brw_update_draw_buffer(struct intel_context *intel)
/* Check some stencil invariants. These should probably be in
* emit_depthbuffer().
*/
- if (irbStencil && irbStencil->region) {
+ if (irbStencil && irbStencil->mt) {
if (!intel->has_separate_stencil)
assert(irbStencil->Base.Format == MESA_FORMAT_S8_Z24);
if (fb_has_hiz || intel->must_use_separate_stencil)
@@ -238,12 +218,6 @@ static bool brw_is_hiz_depth_format(struct intel_context *intel,
return intel->has_hiz && (format == MESA_FORMAT_X8_Z24);
}
-static void brw_hiz_resolve_noop(struct intel_context *intel,
- struct intel_region *depth_region)
-{
- /* empty */
-}
-
void brwInitVtbl( struct brw_context *brw )
{
brw->intel.vtbl.check_vertex_size = 0;
@@ -262,11 +236,8 @@ void brwInitVtbl( struct brw_context *brw )
brw->intel.vtbl.is_hiz_depth_format = brw_is_hiz_depth_format;
if (brw->intel.has_hiz) {
- brw->intel.vtbl.hiz_resolve_hizbuffer = gen6_hiz_resolve_hizbuffer;
- brw->intel.vtbl.hiz_resolve_depthbuffer = gen6_hiz_resolve_depthbuffer;
- } else {
- brw->intel.vtbl.hiz_resolve_hizbuffer = brw_hiz_resolve_noop;
- brw->intel.vtbl.hiz_resolve_depthbuffer = brw_hiz_resolve_noop;
+ brw->intel.vtbl.resolve_depth_slice = gen6_resolve_depth_slice;
+ brw->intel.vtbl.resolve_hiz_slice = gen6_resolve_hiz_slice;
}
if (brw->intel.gen >= 7) {
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 0cc62017cbe..984a7bc2239 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -262,6 +262,7 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit )
struct brw_context *brw = brw_context(ctx);
struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
struct intel_texture_object *intelObj = intel_texture_object(tObj);
+ struct intel_mipmap_tree *mt = intelObj->mt;
struct gl_texture_image *firstImage = tObj->Image[0][tObj->BaseLevel];
struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
const GLuint surf_index = SURF_INDEX_TEXTURE(unit);
@@ -294,7 +295,8 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit )
BRW_SURFACE_PITCH_SHIFT);
surf[4] = 0;
- surf[5] = 0;
+
+ surf[5] = (mt->align_h == 4) ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0;
/* Emit relocation to surface contents */
drm_intel_bo_emit_reloc(brw->intel.batch.bo,
@@ -447,7 +449,8 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
struct intel_context *intel = &brw->intel;
struct gl_context *ctx = &intel->ctx;
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
- struct intel_region *region = irb->region;
+ struct intel_mipmap_tree *mt = irb->mt;
+ struct intel_region *region = irb->mt->region;
uint32_t *surf;
uint32_t tile_x, tile_y;
uint32_t format = 0;
@@ -509,7 +512,8 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
assert(tile_x % 4 == 0);
assert(tile_y % 2 == 0);
surf[5] = ((tile_x / 4) << BRW_SURFACE_X_OFFSET_SHIFT |
- (tile_y / 2) << BRW_SURFACE_Y_OFFSET_SHIFT);
+ (tile_y / 2) << BRW_SURFACE_Y_OFFSET_SHIFT |
+ (mt->align_h == 4 ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0));
if (intel->gen < 6) {
/* _NEW_COLOR */
diff --git a/src/mesa/drivers/dri/i965/gen6_clip_state.c b/src/mesa/drivers/dri/i965/gen6_clip_state.c
index b3bb8aee3ec..d2a5f755726 100644
--- a/src/mesa/drivers/dri/i965/gen6_clip_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_clip_state.c
@@ -67,6 +67,23 @@ upload_clip_state(struct brw_context *brw)
GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE;
}
+ if (brw->hiz.op) {
+ /* HiZ operations emit a rectangle primitive, which requires clipping to
+ * be disabled. From page 10 of the Sandy Bridge PRM Volume 2 Part 1
+ * Section 1.3 3D Primitives Overview:
+ * RECTLIST:
+ * Either the CLIP unit should be DISABLED, or the CLIP unit's Clip
+ * Mode should be set to a value other than CLIPMODE_NORMAL.
+ */
+ BEGIN_BATCH(4);
+ OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2));
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ OUT_BATCH(0);
+ ADVANCE_BATCH();
+ return;
+ }
+
if (!ctx->Transform.DepthClamp)
depth_clamp = GEN6_CLIP_Z_TEST;
@@ -107,7 +124,8 @@ const struct brw_tracked_state gen6_clip_state = {
.dirty = {
.mesa = _NEW_TRANSFORM | _NEW_LIGHT,
.brw = (BRW_NEW_CONTEXT |
- BRW_NEW_FRAGMENT_PROGRAM),
+ BRW_NEW_FRAGMENT_PROGRAM |
+ BRW_NEW_HIZ),
.cache = 0
},
.emit = upload_clip_state,
diff --git a/src/mesa/drivers/dri/i965/gen6_depthstencil.c b/src/mesa/drivers/dri/i965/gen6_depthstencil.c
index 72e86879b2b..eec1bf69015 100644
--- a/src/mesa/drivers/dri/i965/gen6_depthstencil.c
+++ b/src/mesa/drivers/dri/i965/gen6_depthstencil.c
@@ -77,8 +77,12 @@ gen6_upload_depth_stencil_state(struct brw_context *brw)
}
/* _NEW_DEPTH */
- if (ctx->Depth.Test) {
- ds->ds2.depth_test_enable = 1;
+ if (ctx->Depth.Test || brw->hiz.op) {
+ assert(brw->hiz.op != BRW_HIZ_OP_DEPTH_RESOLVE || ctx->Depth.Test);
+ assert(brw->hiz.op != BRW_HIZ_OP_HIZ_RESOLVE || !ctx->Depth.Test);
+ assert(brw->hiz.op != BRW_HIZ_OP_DEPTH_CLEAR || !ctx->Depth.Test);
+
+ ds->ds2.depth_test_enable = ctx->Depth.Test;
ds->ds2.depth_test_func = intel_translate_compare_func(ctx->Depth.Func);
ds->ds2.depth_write_enable = ctx->Depth.Mask;
}
@@ -89,7 +93,8 @@ gen6_upload_depth_stencil_state(struct brw_context *brw)
const struct brw_tracked_state gen6_depth_stencil_state = {
.dirty = {
.mesa = _NEW_DEPTH | _NEW_STENCIL,
- .brw = BRW_NEW_BATCH,
+ .brw = (BRW_NEW_BATCH |
+ BRW_NEW_HIZ),
.cache = 0,
},
.emit = gen6_upload_depth_stencil_state,
diff --git a/src/mesa/drivers/dri/i965/gen6_hiz.c b/src/mesa/drivers/dri/i965/gen6_hiz.c
index fc6344b0aa9..e28251182c9 100644
--- a/src/mesa/drivers/dri/i965/gen6_hiz.c
+++ b/src/mesa/drivers/dri/i965/gen6_hiz.c
@@ -25,16 +25,316 @@
#include <assert.h>
+#include "mesa/drivers/common/meta.h"
+
+#include "mesa/main/arrayobj.h"
+#include "mesa/main/bufferobj.h"
+#include "mesa/main/depth.h"
+#include "mesa/main/enable.h"
+#include "mesa/main/fbobject.h"
+#include "mesa/main/framebuffer.h"
+#include "mesa/main/get.h"
+#include "mesa/main/renderbuffer.h"
+#include "mesa/main/shaderapi.h"
+#include "mesa/main/varray.h"
+
+#include "intel_fbo.h"
+#include "intel_mipmap_tree.h"
+#include "intel_regions.h"
+#include "intel_tex.h"
+
+#include "brw_context.h"
+#include "brw_defines.h"
+
+static const uint32_t gen6_hiz_meta_save =
+
+ /* Disable alpha, depth, and stencil test.
+ *
+ * See the following sections of the Sandy Bridge PRM, Volume 1, Part2:
+ * - 7.5.3.1 Depth Buffer Clear
+ * - 7.5.3.2 Depth Buffer Resolve
+ * - 7.5.3.3 Hierarchical Depth Buffer Resolve
+ */
+ MESA_META_ALPHA_TEST |
+ MESA_META_DEPTH_TEST |
+ MESA_META_STENCIL_TEST |
+
+ /* Disable viewport mapping.
+ *
+ * From page 11 of the Sandy Bridge PRM, Volume 2, Part 1, Section 1.3
+ * 3D Primitives Overview:
+ * RECTLIST:
+ * Viewport Mapping must be DISABLED (as is typical with the use of
+ * screen- space coordinates).
+ *
+ * We must also manually disable 3DSTATE_SF.Viewport_Transform_Enable.
+ */
+ MESA_META_VIEWPORT |
+
+ /* Disable clipping.
+ *
+ * From page 11 of the Sandy Bridge PRM, Volume 2, Part 1, Section 1.3
+ * 3D Primitives Overview:
+ * Either the CLIP unit should be DISABLED, or the CLIP unit’s Clip
+ * Mode should be set to a value other than CLIPMODE_NORMAL.
+ */
+ MESA_META_CLIP |
+
+ /* Render a solid rectangle (set 3DSTATE_SF.FrontFace_Fill_Mode).
+ *
+ * From page 249 of the Sandy Bridge PRM, Volume 2, Part 1, Section
+ * 6.4.1.1 3DSTATE_SF, FrontFace_Fill_Mode:
+ * SOLID: Any triangle or rectangle object found to be front-facing
+ * is rendered as a solid object. This setting is required when
+ * (rendering rectangle (RECTLIST) objects.
+ * Also see field BackFace_Fill_Mode.
+ *
+ * Note: MESA_META_RASTERIZAION also disables culling, but that is
+ * irrelevant. See 3DSTATE_SF.Cull_Mode.
+ */
+ MESA_META_RASTERIZATION |
+
+ /* Each HiZ operation uses a vertex shader and VAO. */
+ MESA_META_SHADER |
+ MESA_META_VERTEX |
+
+ /* Disable scissoring.
+ *
+ * Scissoring is disabled for resolves because a resolve operation
+ * should resolve the entire buffer. Scissoring is disabled for depth
+ * clears because, if we are performing a partial depth clear, then we
+ * specify the clear region with the RECTLIST vertices.
+ */
+ MESA_META_SCISSOR |
+
+ MESA_META_SELECT_FEEDBACK;
+
+/**
+ * Initialize static data needed for HiZ operations.
+ */
+static void
+gen6_hiz_init(struct brw_context *brw)
+{
+ struct gl_context *ctx = &brw->intel.ctx;
+ struct brw_hiz_state *hiz = &brw->hiz;
+
+ if (hiz->fbo != 0)
+ return;
+
+ /* Create depthbuffer.
+ *
+ * Until glRenderbufferStorage is called, the renderbuffer hash table
+ * maps the renderbuffer name to a dummy renderbuffer. We need the
+ * renderbuffer to be registered in the hash table so that framebuffer
+ * validation succeeds, so we hackishly allocate storage then immediately
+ * discard it.
+ */
+ GLuint depth_rb_name;
+ _mesa_GenRenderbuffersEXT(1, &depth_rb_name);
+ _mesa_BindRenderbufferEXT(GL_RENDERBUFFER, depth_rb_name);
+ _mesa_RenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 32, 32);
+ _mesa_reference_renderbuffer(&hiz->depth_rb,
+ _mesa_lookup_renderbuffer(ctx, depth_rb_name));
+ intel_miptree_release(&((struct intel_renderbuffer*) hiz->depth_rb)->mt);
+
+ /* Setup FBO. */
+ _mesa_GenFramebuffersEXT(1, &hiz->fbo);
+ _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, hiz->fbo);
+ _mesa_FramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER,
+ GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER,
+ hiz->depth_rb->Name);
+
+ /* Compile vertex shader. */
+ const char *vs_source =
+ "attribute vec4 position;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = position;\n"
+ "}\n";
+ GLuint vs = _mesa_CreateShaderObjectARB(GL_VERTEX_SHADER);
+ _mesa_ShaderSourceARB(vs, 1, &vs_source, NULL);
+ _mesa_CompileShaderARB(vs);
+
+ /* Compile fragment shader. */
+ const char *fs_source = "void main() {}";
+ GLuint fs = _mesa_CreateShaderObjectARB(GL_FRAGMENT_SHADER);
+ _mesa_ShaderSourceARB(fs, 1, &fs_source, NULL);
+ _mesa_CompileShaderARB(fs);
+
+ /* Link and use program. */
+ hiz->shader.program = _mesa_CreateProgramObjectARB();
+ _mesa_AttachShader(hiz->shader.program, vs);
+ _mesa_AttachShader(hiz->shader.program, fs);
+ _mesa_LinkProgramARB(hiz->shader.program);
+ _mesa_UseProgramObjectARB(hiz->shader.program);
+
+ /* Create and bind VAO. */
+ _mesa_GenVertexArrays(1, &hiz->vao);
+ _mesa_BindVertexArray(hiz->vao);
+
+ /* Setup VBO for 'position'. */
+ hiz->shader.position_location =
+ _mesa_GetAttribLocationARB(hiz->shader.program, "position");
+ _mesa_GenBuffersARB(1, &hiz->shader.position_vbo);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, hiz->shader.position_vbo);
+ _mesa_VertexAttribPointerARB(hiz->shader.position_location,
+ 2, /*components*/
+ GL_FLOAT,
+ GL_FALSE, /*normalized?*/
+ 0, /*stride*/
+ NULL);
+ _mesa_EnableVertexAttribArrayARB(hiz->shader.position_location);
+
+ /* Cleanup. */
+ _mesa_DeleteShader(vs);
+ _mesa_DeleteShader(fs);
+}
+
+/**
+ * Wrap \c brw->hiz.depth_rb around a miptree.
+ *
+ * \see gen6_hiz_teardown_depth_buffer()
+ */
+static void
+gen6_hiz_setup_depth_buffer(struct brw_context *brw,
+ struct intel_mipmap_tree *mt,
+ unsigned int level,
+ unsigned int layer)
+{
+ struct gl_renderbuffer *rb = brw->hiz.depth_rb;
+ struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+
+ rb->Format = mt->format;
+ rb->_BaseFormat = _mesa_get_format_base_format(rb->Format);
+ rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format);
+ rb->InternalFormat = rb->_BaseFormat;
+ rb->Width = mt->level[level].width;
+ rb->Height = mt->level[level].height;
+
+ irb->mt_level = level;
+ irb->mt_layer = layer;
+
+ intel_miptree_reference(&irb->mt, mt);
+ intel_renderbuffer_set_draw_offset(irb);
+}
+
+/**
+ * Release the region from \c brw->hiz.depth_rb.
+ *
+ * \see gen6_hiz_setup_depth_buffer()
+ */
+static void
+gen6_hiz_teardown_depth_buffer(struct gl_renderbuffer *rb)
+{
+ struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+ intel_miptree_release(&irb->mt);
+}
+
+static void
+gen6_resolve_slice(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ unsigned int level,
+ unsigned int layer,
+ enum brw_hiz_op op)
+{
+ struct gl_context *ctx = &intel->ctx;
+ struct brw_context *brw = brw_context(ctx);
+ struct brw_hiz_state *hiz = &brw->hiz;
+
+ /* Do not recurse. */
+ assert(!brw->hiz.op);
+
+ assert(mt->hiz_mt != NULL);
+ assert(level >= mt->first_level);
+ assert(level <= mt->last_level);
+ assert(layer < mt->level[level].depth);
+
+ /* Save state. */
+ GLint save_drawbuffer;
+ GLint save_renderbuffer;
+ _mesa_meta_begin(ctx, gen6_hiz_meta_save);
+ _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &save_drawbuffer);
+ _mesa_GetIntegerv(GL_RENDERBUFFER_BINDING, &save_renderbuffer);
+
+ /* Initialize context data for HiZ operations. */
+ gen6_hiz_init(brw);
+
+ /* Set depth state. */
+ if (!ctx->Depth.Mask) {
+ /* This sets 3DSTATE_WM.Depth_Buffer_Write_Enable. */
+ _mesa_DepthMask(GL_TRUE);
+ }
+ if (op == BRW_HIZ_OP_DEPTH_RESOLVE) {
+ _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
+ _mesa_DepthFunc(GL_NEVER);
+ }
+
+ /* Setup FBO. */
+ gen6_hiz_setup_depth_buffer(brw, mt, level, layer);
+ _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, hiz->fbo);
+
+
+ /* A rectangle primitive (3DPRIM_RECTLIST) consists of only three vertices.
+ * The vertices reside in screen space with DirectX coordinates (this is,
+ * (0, 0) is the upper left corner).
+ *
+ * v2 ------ implied
+ * | |
+ * | |
+ * v0 ----- v1
+ */
+ const int width = hiz->depth_rb->Width;
+ const int height = hiz->depth_rb->Height;
+ const GLfloat positions[] = {
+ 0, height,
+ width, height,
+ 0, 0,
+ };
+
+ /* Setup program and vertex attributes. */
+ _mesa_UseProgramObjectARB(hiz->shader.program);
+ _mesa_BindVertexArray(hiz->vao);
+ _mesa_BindBufferARB(GL_ARRAY_BUFFER, hiz->shader.position_vbo);
+ _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(positions), positions,
+ GL_DYNAMIC_DRAW_ARB);
+
+ /* Execute the HiZ operation. */
+ brw->hiz.op = op;
+ brw->state.dirty.brw |= BRW_NEW_HIZ;
+ _mesa_DrawArrays(GL_TRIANGLES, 0, 3);
+ brw->state.dirty.brw |= BRW_NEW_HIZ;
+ brw->hiz.op = BRW_HIZ_OP_NONE;
+
+ /* Restore state.
+ *
+ * The order in which state is restored is significant. The draw buffer
+ * used for the HiZ op has no stencil buffer, and glStencilFunc() clamps
+ * the stencil reference value to the range allowed by the draw buffer's
+ * number of stencil bits. So, the draw buffer binding must be restored
+ * before the stencil state, or else the stencil ref will be clamped to 0.
+ */
+ gen6_hiz_teardown_depth_buffer(hiz->depth_rb);
+ _mesa_BindRenderbufferEXT(GL_RENDERBUFFER, save_renderbuffer);
+ _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, save_drawbuffer);
+ _mesa_meta_end(ctx);
+}
+
void
-gen6_hiz_resolve_depthbuffer(struct intel_context *intel,
- struct intel_region *depth_region)
+gen6_resolve_hiz_slice(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer)
{
- assert("!stub");
+ gen6_resolve_slice(intel, mt, level, layer, BRW_HIZ_OP_HIZ_RESOLVE);
}
+
void
-gen6_hiz_resolve_hizbuffer(struct intel_context *intel,
- struct intel_region *depth_region)
+gen6_resolve_depth_slice(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer)
{
- assert("!stub");
+ gen6_resolve_slice(intel, mt, level, layer, BRW_HIZ_OP_DEPTH_RESOLVE);
}
diff --git a/src/mesa/drivers/dri/i965/gen6_hiz.h b/src/mesa/drivers/dri/i965/gen6_hiz.h
index 4611182b980..49290123ff0 100644
--- a/src/mesa/drivers/dri/i965/gen6_hiz.h
+++ b/src/mesa/drivers/dri/i965/gen6_hiz.h
@@ -23,13 +23,19 @@
#pragma once
+#include <stdint.h>
+
struct intel_context;
-struct intel_region;
+struct intel_mipmap_tree;
void
-gen6_hiz_resolve_depthbuffer(struct intel_context *intel,
- struct intel_region *depth_region);
+gen6_resolve_hiz_slice(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer);
void
-gen6_hiz_resolve_hizbuffer(struct intel_context *intel,
- struct intel_region *depth_region);
+gen6_resolve_depth_slice(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer);
diff --git a/src/mesa/drivers/dri/i965/gen6_sf_state.c b/src/mesa/drivers/dri/i965/gen6_sf_state.c
index 67119d8d182..4c4ff308054 100644
--- a/src/mesa/drivers/dri/i965/gen6_sf_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_sf_state.c
@@ -147,8 +147,19 @@ upload_sf_state(struct brw_context *brw)
num_outputs << GEN6_SF_NUM_OUTPUTS_SHIFT |
urb_entry_read_length << GEN6_SF_URB_ENTRY_READ_LENGTH_SHIFT |
urb_entry_read_offset << GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT;
- dw2 = GEN6_SF_VIEWPORT_TRANSFORM_ENABLE |
- GEN6_SF_STATISTICS_ENABLE;
+
+ dw2 = GEN6_SF_STATISTICS_ENABLE;
+
+ /* Enable viewport transform only if no HiZ operation is progress
+ *
+ * From page 11 of the SandyBridge PRM, Volume 2, Part 1, Section 1.3, "3D
+ * Primitives Overview":
+ * RECTLIST: Viewport Mapping must be DISABLED (as is typical with the
+ * use of screen- space coordinates).
+ */
+ if (!brw->hiz.op)
+ dw2 |= GEN6_SF_VIEWPORT_TRANSFORM_ENABLE;
+
dw3 = 0;
dw4 = 0;
dw16 = 0;
@@ -334,7 +345,8 @@ const struct brw_tracked_state gen6_sf_state = {
_NEW_POINT |
_NEW_TRANSFORM),
.brw = (BRW_NEW_CONTEXT |
- BRW_NEW_FRAGMENT_PROGRAM),
+ BRW_NEW_FRAGMENT_PROGRAM |
+ BRW_NEW_HIZ),
.cache = CACHE_NEW_VS_PROG
},
.emit = upload_sf_state,
diff --git a/src/mesa/drivers/dri/i965/gen6_wm_state.c b/src/mesa/drivers/dri/i965/gen6_wm_state.c
index 271a9aeca78..070220a5077 100644
--- a/src/mesa/drivers/dri/i965/gen6_wm_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_wm_state.c
@@ -147,6 +147,23 @@ upload_wm_state(struct brw_context *brw)
dw4 |= (brw->wm.prog_data->first_curbe_grf_16 <<
GEN6_WM_DISPATCH_START_GRF_SHIFT_2);
+ switch (brw->hiz.op) {
+ case BRW_HIZ_OP_NONE:
+ break;
+ case BRW_HIZ_OP_DEPTH_CLEAR:
+ dw4 |= GEN6_WM_DEPTH_CLEAR;
+ break;
+ case BRW_HIZ_OP_DEPTH_RESOLVE:
+ dw4 |= GEN6_WM_DEPTH_RESOLVE;
+ break;
+ case BRW_HIZ_OP_HIZ_RESOLVE:
+ dw4 |= GEN6_WM_HIERARCHICAL_DEPTH_RESOLVE;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
dw5 |= (brw->max_wm_threads - 1) << GEN6_WM_MAX_THREADS_SHIFT;
/* CACHE_NEW_WM_PROG */
@@ -215,7 +232,8 @@ const struct brw_tracked_state gen6_wm_state = {
_NEW_POLYGON),
.brw = (BRW_NEW_FRAGMENT_PROGRAM |
BRW_NEW_URB_FENCE |
- BRW_NEW_BATCH),
+ BRW_NEW_BATCH |
+ BRW_NEW_HIZ),
.cache = (CACHE_NEW_SAMPLER |
CACHE_NEW_WM_PROG)
},
diff --git a/src/mesa/drivers/dri/i965/gen7_misc_state.c b/src/mesa/drivers/dri/i965/gen7_misc_state.c
index 6a3c086ac96..25e1b1d0fe1 100644
--- a/src/mesa/drivers/dri/i965/gen7_misc_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_misc_state.c
@@ -22,6 +22,7 @@
*/
#include "intel_batchbuffer.h"
+#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_fbo.h"
#include "brw_context.h"
@@ -38,7 +39,7 @@ gen7_depth_format(struct brw_context *brw)
struct intel_region *region = NULL;
if (drb)
- region = drb->region;
+ region = drb->mt->region;
else
return BRW_DEPTHFORMAT_D32_FLOAT;
@@ -78,7 +79,7 @@ static void emit_depthbuffer(struct brw_context *brw)
if (srb == NULL) {
dw1 |= (BRW_SURFACE_NULL << 29);
} else {
- struct intel_region *region = srb->region;
+ struct intel_region *region = srb->mt->region;
/* _NEW_STENCIL: enable stencil buffer writes */
dw1 |= ((ctx->Stencil.WriteMask != 0) << 27);
@@ -98,7 +99,7 @@ static void emit_depthbuffer(struct brw_context *brw)
OUT_BATCH(0);
ADVANCE_BATCH();
} else {
- struct intel_region *region = drb->region;
+ struct intel_region *region = drb->mt->region;
uint32_t tile_x, tile_y, offset;
offset = intel_renderbuffer_tile_offsets(drb, &tile_x, &tile_y);
@@ -140,8 +141,8 @@ static void emit_depthbuffer(struct brw_context *brw)
} else {
BEGIN_BATCH(3);
OUT_BATCH(GEN7_3DSTATE_STENCIL_BUFFER << 16 | (3 - 2));
- OUT_BATCH(srb->region->pitch * srb->region->cpp - 1);
- OUT_RELOC(srb->region->bo,
+ OUT_BATCH(srb->mt->region->pitch * srb->mt->region->cpp - 1);
+ OUT_RELOC(srb->mt->region->bo,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
0);
ADVANCE_BATCH();
diff --git a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
index f74198b2468..e1c3910af95 100644
--- a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
@@ -192,7 +192,7 @@ gen7_update_renderbuffer_surface(struct brw_context *brw,
struct intel_context *intel = &brw->intel;
struct gl_context *ctx = &intel->ctx;
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
- struct intel_region *region = irb->region;
+ struct intel_region *region = irb->mt->region;
struct gen7_surface_state *surf;
uint32_t tile_x, tile_y;
diff --git a/src/mesa/drivers/dri/i965/intel_resolve_map.c b/src/mesa/drivers/dri/i965/intel_resolve_map.c
new file mode 120000
index 00000000000..77e50fbaea4
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/intel_resolve_map.c
@@ -0,0 +1 @@
+../intel/intel_resolve_map.c \ No newline at end of file
diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c
index 8d7693d7b88..b1a839ac706 100644
--- a/src/mesa/drivers/dri/intel/intel_blit.c
+++ b/src/mesa/drivers/dri/intel/intel_blit.c
@@ -267,13 +267,18 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
int x1, y1, x2, y2;
uint32_t clear_val;
uint32_t BR13, CMD;
+ struct intel_region *region;
int pitch, cpp;
drm_intel_bo *aper_array[2];
mask &= ~(1 << buf);
irb = intel_get_renderbuffer(fb, buf);
- if (irb == NULL || irb->region == NULL || irb->region->bo == NULL) {
+ if (irb && irb->mt) {
+ region = irb->mt->region;
+ assert(region);
+ assert(region->bo);
+ } else {
fail_mask |= 1 << buf;
continue;
}
@@ -284,12 +289,12 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
x2 = cx + cw + irb->draw_x;
y2 = cy + ch + irb->draw_y;
- pitch = irb->region->pitch;
- cpp = irb->region->cpp;
+ pitch = region->pitch;
+ cpp = region->cpp;
DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
__FUNCTION__,
- irb->region->bo, (pitch * cpp),
+ region->bo, (pitch * cpp),
x1, y1, x2 - x1, y2 - y1);
BR13 = 0xf0 << 16;
@@ -305,10 +310,10 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
}
}
- assert(irb->region->tiling != I915_TILING_Y);
+ assert(region->tiling != I915_TILING_Y);
#ifndef I915
- if (irb->region->tiling != I915_TILING_NONE) {
+ if (region->tiling != I915_TILING_NONE) {
CMD |= XY_DST_TILED;
pitch /= 4;
}
@@ -357,7 +362,7 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
/* do space check before going any further */
aper_array[0] = intel->batch.bo;
- aper_array[1] = irb->region->bo;
+ aper_array[1] = region->bo;
if (drm_intel_bufmgr_check_aperture_space(aper_array,
ARRAY_SIZE(aper_array)) != 0) {
@@ -369,7 +374,7 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
OUT_BATCH(BR13);
OUT_BATCH((y1 << 16) | x1);
OUT_BATCH((y2 << 16) | x2);
- OUT_RELOC_FENCED(irb->region->bo,
+ OUT_RELOC_FENCED(region->bo,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
0);
OUT_BATCH(clear_val);
diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
index 75d95b1fe70..4a1a8165be5 100644
--- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c
+++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
@@ -766,10 +766,10 @@ intel_render_object_purgeable(struct gl_context * ctx,
(void) option;
intel = intel_renderbuffer(obj);
- if (intel->region == NULL)
+ if (intel->mt == NULL)
return GL_RELEASED_APPLE;
- return intel_buffer_purgeable(intel->region->bo);
+ return intel_buffer_purgeable(intel->mt->region->bo);
}
static GLenum
@@ -823,10 +823,10 @@ intel_render_object_unpurgeable(struct gl_context * ctx,
(void) option;
intel = intel_renderbuffer(obj);
- if (intel->region == NULL)
+ if (intel->mt == NULL)
return GL_UNDEFINED_APPLE;
- return intel_buffer_unpurgeable(intel->region->bo);
+ return intel_buffer_unpurgeable(intel->mt->region->bo);
}
#endif
diff --git a/src/mesa/drivers/dri/intel/intel_buffers.c b/src/mesa/drivers/dri/intel/intel_buffers.c
index 08f5c4decd3..4632751935a 100644
--- a/src/mesa/drivers/dri/intel/intel_buffers.c
+++ b/src/mesa/drivers/dri/intel/intel_buffers.c
@@ -28,6 +28,7 @@
#include "intel_context.h"
#include "intel_buffers.h"
#include "intel_fbo.h"
+#include "intel_mipmap_tree.h"
#include "main/framebuffer.h"
#include "main/renderbuffer.h"
@@ -40,8 +41,8 @@ intel_drawbuf_region(struct intel_context *intel)
{
struct intel_renderbuffer *irbColor =
intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0]);
- if (irbColor)
- return irbColor->region;
+ if (irbColor && irbColor->mt)
+ return irbColor->mt->region;
else
return NULL;
}
@@ -54,8 +55,8 @@ intel_readbuf_region(struct intel_context *intel)
{
struct intel_renderbuffer *irb
= intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
- if (irb)
- return irb->region;
+ if (irb && irb->mt)
+ return irb->mt->region;
else
return NULL;
}
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index d89b38875b8..9af21c8dace 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -53,6 +53,7 @@
#include "intel_fbo.h"
#include "intel_bufmgr.h"
#include "intel_screen.h"
+#include "intel_mipmap_tree.h"
#include "utils.h"
#include "../glsl/ralloc.h"
@@ -1153,7 +1154,9 @@ intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel,
if (!rb)
return;
- if (rb->region && rb->region->name == buffer->name)
+ if (rb->mt &&
+ rb->mt->region &&
+ rb->mt->region->name == buffer->name)
return;
if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
@@ -1167,23 +1170,34 @@ intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel,
if (buffer->attachment == __DRI_BUFFER_STENCIL) {
struct intel_renderbuffer *depth_rb =
intel_get_renderbuffer(fb, BUFFER_DEPTH);
- identify_depth_and_stencil = depth_rb && depth_rb->region;
+ identify_depth_and_stencil = depth_rb && depth_rb->mt;
}
if (identify_depth_and_stencil) {
if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
fprintf(stderr, "(reusing depth buffer as stencil)\n");
}
- intel_region_reference(&rb->region, depth_rb->region);
+ intel_miptree_reference(&rb->mt, depth_rb->mt);
} else {
- intel_region_release(&rb->region);
- rb->region = intel_region_alloc_for_handle(intel->intelScreen,
+ intel_miptree_release(&rb->mt);
+ struct intel_region *region =
+ intel_region_alloc_for_handle(intel->intelScreen,
buffer->cpp,
drawable->w,
drawable->h,
buffer->pitch / buffer->cpp,
buffer->name,
buffer_name);
+ if (!region)
+ return;
+
+ rb->mt = intel_miptree_create_for_region(intel,
+ GL_TEXTURE_2D,
+ rb->Base.Format,
+ region);
+ intel_region_release(&region);
+ if (!rb->mt)
+ return;
}
if (buffer->attachment == __DRI_BUFFER_DEPTH_STENCIL) {
@@ -1196,7 +1210,7 @@ intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel,
/* The rb passed in is the BUFFER_DEPTH attachment, and we need
* to associate this region to BUFFER_STENCIL as well.
*/
- intel_region_reference(&stencil_rb->region, rb->region);
+ intel_miptree_reference(&stencil_rb->mt, rb->mt);
}
}
@@ -1338,11 +1352,13 @@ intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel,
/* If the renderbuffer's and DRIbuffer's regions match, then continue. */
if ((buffer->attachment != __DRI_BUFFER_HIZ &&
- rb->region &&
- rb->region->name == buffer->name) ||
+ rb->mt &&
+ rb->mt->region &&
+ rb->mt->region->name == buffer->name) ||
(buffer->attachment == __DRI_BUFFER_HIZ &&
- rb->hiz_region &&
- rb->hiz_region->name == buffer->name)) {
+ rb->mt &&
+ rb->mt->hiz_mt &&
+ rb->mt->hiz_mt->region->name == buffer->name)) {
return;
}
@@ -1371,6 +1387,15 @@ intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel,
buffer_height = drawable->h;
}
+ /* Release the buffer storage now in case we have to return early
+ * due to failure to allocate new storage.
+ */
+ if (buffer->attachment == __DRI_BUFFER_HIZ) {
+ intel_miptree_release(&rb->mt->hiz_mt);
+ } else {
+ intel_miptree_release(&rb->mt);
+ }
+
struct intel_region *region =
intel_region_alloc_for_handle(intel->intelScreen,
buffer->cpp,
@@ -1379,14 +1404,22 @@ intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel,
buffer->pitch / buffer->cpp,
buffer->name,
buffer_name);
+ if (!region)
+ return;
+ struct intel_mipmap_tree *mt =
+ intel_miptree_create_for_region(intel,
+ GL_TEXTURE_2D,
+ rb->Base.Format,
+ region);
+ intel_region_release(&region);
+
+ /* Associate buffer with new storage. */
if (buffer->attachment == __DRI_BUFFER_HIZ) {
- intel_region_reference(&rb->hiz_region, region);
+ rb->mt->hiz_mt = mt;
} else {
- intel_region_reference(&rb->region, region);
+ rb->mt = mt;
}
-
- intel_region_release(&region);
}
/**
@@ -1463,7 +1496,7 @@ intel_verify_dri2_has_hiz(struct intel_context *intel,
assert(stencil_rb->Base.Format == MESA_FORMAT_S8);
assert(depth_rb && depth_rb->Base.Format == MESA_FORMAT_X8_Z24);
- if (stencil_rb->region->tiling == I915_TILING_NONE) {
+ if (stencil_rb->mt->region->tiling == I915_TILING_NONE) {
/*
* The stencil buffer is actually W tiled. The region's tiling is
* I915_TILING_NONE, however, because the GTT is incapable of W
@@ -1544,11 +1577,21 @@ intel_verify_dri2_has_hiz(struct intel_context *intel,
/ depth_stencil_buffer->cpp,
depth_stencil_buffer->name,
"dri2 depth / stencil buffer");
- intel_region_reference(&intel_get_renderbuffer(fb, BUFFER_DEPTH)->region,
- region);
- intel_region_reference(&intel_get_renderbuffer(fb, BUFFER_STENCIL)->region,
- region);
+ if (!region)
+ return;
+
+ struct intel_mipmap_tree *mt =
+ intel_miptree_create_for_region(intel,
+ GL_TEXTURE_2D,
+ depth_stencil_rb->Base.Format,
+ region);
intel_region_release(&region);
+ if (!mt)
+ return;
+
+ intel_miptree_reference(&intel_get_renderbuffer(fb, BUFFER_DEPTH)->mt, mt);
+ intel_miptree_reference(&intel_get_renderbuffer(fb, BUFFER_STENCIL)->mt, mt);
+ intel_miptree_release(&mt);
}
}
diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h
index f2be5973851..efaf721ae82 100644
--- a/src/mesa/drivers/dri/intel/intel_context.h
+++ b/src/mesa/drivers/dri/intel/intel_context.h
@@ -166,10 +166,15 @@ struct intel_context
* - 7.5.3.3 Hierarchical Depth Buffer Resolve
* \{
*/
- void (*hiz_resolve_depthbuffer)(struct intel_context *intel,
- struct intel_region *depth_region);
- void (*hiz_resolve_hizbuffer)(struct intel_context *intel,
- struct intel_region *depth_region);
+ void (*resolve_hiz_slice)(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer);
+
+ void (*resolve_depth_slice)(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer);
/** \} */
/**
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c
index a724f1d97b3..dc3e5dda14f 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.c
+++ b/src/mesa/drivers/dri/intel/intel_fbo.c
@@ -36,6 +36,8 @@
#include "main/renderbuffer.h"
#include "main/context.h"
#include "main/teximage.h"
+#include "main/image.h"
+
#include "swrast/swrast.h"
#include "drivers/common/meta.h"
@@ -55,6 +57,25 @@
#define FILE_DEBUG_FLAG DEBUG_FBO
+bool
+intel_framebuffer_has_hiz(struct gl_framebuffer *fb)
+{
+ struct intel_renderbuffer *rb = NULL;
+ if (fb)
+ rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
+ return rb && rb->mt && rb->mt->hiz_mt;
+}
+
+struct intel_region*
+intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
+{
+ struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex);
+ if (irb && irb->mt)
+ return irb->mt->region;
+ else
+ return NULL;
+}
+
/**
* Create a new framebuffer object.
*/
@@ -76,8 +97,7 @@ intel_delete_renderbuffer(struct gl_renderbuffer *rb)
ASSERT(irb);
- intel_region_release(&irb->region);
- intel_region_release(&irb->hiz_region);
+ intel_miptree_release(&irb->mt);
_mesa_reference_renderbuffer(&irb->wrapped_depth, NULL);
_mesa_reference_renderbuffer(&irb->wrapped_stencil, NULL);
@@ -103,7 +123,12 @@ intel_map_renderbuffer_gtt(struct gl_context *ctx,
GLubyte *map;
int stride, flip_stride;
- assert(irb->region);
+ assert(irb->mt);
+
+ intel_renderbuffer_resolve_depth(intel, irb);
+ if (mode & GL_MAP_WRITE_BIT) {
+ intel_renderbuffer_set_needs_hiz_resolve(irb);
+ }
irb->map_mode = mode;
irb->map_x = x;
@@ -111,10 +136,10 @@ intel_map_renderbuffer_gtt(struct gl_context *ctx,
irb->map_w = w;
irb->map_h = h;
- stride = irb->region->pitch * irb->region->cpp;
+ stride = irb->mt->region->pitch * irb->mt->region->cpp;
if (rb->Name == 0) {
- y = irb->region->height - 1 - y;
+ y = irb->mt->region->height - 1 - y;
flip_stride = -stride;
} else {
x += irb->draw_x;
@@ -122,14 +147,14 @@ intel_map_renderbuffer_gtt(struct gl_context *ctx,
flip_stride = stride;
}
- if (drm_intel_bo_references(intel->batch.bo, irb->region->bo)) {
+ if (drm_intel_bo_references(intel->batch.bo, irb->mt->region->bo)) {
intel_batchbuffer_flush(intel);
}
- drm_intel_gem_bo_map_gtt(irb->region->bo);
+ drm_intel_gem_bo_map_gtt(irb->mt->region->bo);
- map = irb->region->bo->virtual;
- map += x * irb->region->cpp;
+ map = irb->mt->region->bo->virtual;
+ map += x * irb->mt->region->cpp;
map += (int)y * stride;
*out_map = map;
@@ -167,10 +192,10 @@ intel_map_renderbuffer_blit(struct gl_context *ctx,
int src_x, src_y;
int dst_stride;
- assert(irb->region);
+ assert(irb->mt->region);
assert(intel->gen >= 6);
assert(!(mode & GL_MAP_WRITE_BIT));
- assert(irb->region->tiling == I915_TILING_X);
+ assert(irb->mt->region->tiling == I915_TILING_X);
irb->map_mode = mode;
irb->map_x = x;
@@ -178,14 +203,14 @@ intel_map_renderbuffer_blit(struct gl_context *ctx,
irb->map_w = w;
irb->map_h = h;
- dst_stride = ALIGN(w * irb->region->cpp, 4);
+ dst_stride = ALIGN(w * irb->mt->region->cpp, 4);
if (rb->Name) {
src_x = x + irb->draw_x;
src_y = y + irb->draw_y;
} else {
src_x = x;
- src_y = irb->region->height - y - h;
+ src_y = irb->mt->region->height - y - h;
}
irb->map_bo = drm_intel_bo_alloc(intel->bufmgr, "MapRenderbuffer() temp",
@@ -196,10 +221,10 @@ intel_map_renderbuffer_blit(struct gl_context *ctx,
*/
if (irb->map_bo &&
intelEmitCopyBlit(intel,
- irb->region->cpp,
- irb->region->pitch, irb->region->bo,
- 0, irb->region->tiling,
- dst_stride / irb->region->cpp, irb->map_bo,
+ irb->mt->region->cpp,
+ irb->mt->region->pitch, irb->mt->region->bo,
+ 0, irb->mt->region->tiling,
+ dst_stride / irb->mt->region->cpp, irb->map_bo,
0, I915_TILING_NONE,
src_x, src_y,
0, 0,
@@ -258,7 +283,7 @@ intel_map_renderbuffer_s8(struct gl_context *ctx,
uint8_t *untiled_s8_map;
assert(rb->Format == MESA_FORMAT_S8);
- assert(irb->region);
+ assert(irb->mt);
irb->map_mode = mode;
irb->map_x = x;
@@ -272,12 +297,12 @@ intel_map_renderbuffer_s8(struct gl_context *ctx,
irb->map_buffer = malloc(w * h);
untiled_s8_map = irb->map_buffer;
- tiled_s8_map = intel_region_map(intel, irb->region, mode);
+ tiled_s8_map = intel_region_map(intel, irb->mt->region, mode);
for (uint32_t pix_y = 0; pix_y < h; pix_y++) {
for (uint32_t pix_x = 0; pix_x < w; pix_x++) {
uint32_t flipped_y = y_flip * (int32_t)(y + pix_y) + y_bias;
- ptrdiff_t offset = intel_offset_S8(irb->region->pitch,
+ ptrdiff_t offset = intel_offset_S8(irb->mt->region->pitch,
x + pix_x,
flipped_y);
untiled_s8_map[pix_y * w + pix_x] = tiled_s8_map[offset];
@@ -321,11 +346,12 @@ intel_map_renderbuffer_separate_s8z24(struct gl_context *ctx,
struct intel_context *intel = intel_context(ctx);
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
- GLbitfield adjusted_mode;
-
uint8_t *s8z24_map;
int32_t s8z24_stride;
+ struct intel_renderbuffer *s8_irb;
+ uint8_t *s8_map;
+
assert(rb->Name != 0);
assert(rb->Format == MESA_FORMAT_S8_Z24);
assert(irb->wrapped_depth != NULL);
@@ -337,42 +363,29 @@ intel_map_renderbuffer_separate_s8z24(struct gl_context *ctx,
irb->map_w = w;
irb->map_h = h;
- if (mode & GL_MAP_READ_BIT) {
- /* Since the caller may read the stencil bits, we must copy the stencil
- * buffer's contents into the depth buffer. This necessitates that the
- * depth buffer be mapped in write mode.
- */
- adjusted_mode = mode | GL_MAP_WRITE_BIT;
- } else {
- adjusted_mode = mode;
- }
-
+ /* Map with write mode for the gather below. */
intel_map_renderbuffer_gtt(ctx, irb->wrapped_depth,
- x, y, w, h, adjusted_mode,
+ x, y, w, h, mode | GL_MAP_WRITE_BIT,
&s8z24_map, &s8z24_stride);
- if (mode & GL_MAP_READ_BIT) {
- struct intel_renderbuffer *s8_irb;
- uint8_t *s8_map;
-
- s8_irb = intel_renderbuffer(irb->wrapped_stencil);
- s8_map = intel_region_map(intel, s8_irb->region, GL_MAP_READ_BIT);
-
- for (uint32_t pix_y = 0; pix_y < h; ++pix_y) {
- for (uint32_t pix_x = 0; pix_x < w; ++pix_x) {
- ptrdiff_t s8_offset = intel_offset_S8(s8_irb->region->pitch,
- x + pix_x,
- y + pix_y);
- ptrdiff_t s8z24_offset = pix_y * s8z24_stride
- + pix_x * 4
- + 3;
- s8z24_map[s8z24_offset] = s8_map[s8_offset];
- }
+ s8_irb = intel_renderbuffer(irb->wrapped_stencil);
+ s8_map = intel_region_map(intel, s8_irb->mt->region, GL_MAP_READ_BIT);
+
+ /* Gather the stencil buffer into the depth buffer. */
+ for (uint32_t pix_y = 0; pix_y < h; ++pix_y) {
+ for (uint32_t pix_x = 0; pix_x < w; ++pix_x) {
+ ptrdiff_t s8_offset = intel_offset_S8(s8_irb->mt->region->pitch,
+ x + pix_x,
+ y + pix_y);
+ ptrdiff_t s8z24_offset = pix_y * s8z24_stride
+ + pix_x * 4
+ + 3;
+ s8z24_map[s8z24_offset] = s8_map[s8_offset];
}
-
- intel_region_unmap(intel, s8_irb->region);
}
+ intel_region_unmap(intel, s8_irb->mt->region);
+
*out_map = s8z24_map;
*out_stride = s8z24_stride;
}
@@ -392,7 +405,7 @@ intel_map_renderbuffer(struct gl_context *ctx,
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
/* We sometimes get called with this by our intel_span.c usage. */
- if (!irb->region && !irb->wrapped_depth) {
+ if (!irb->mt && !irb->wrapped_depth) {
*out_map = NULL;
*out_stride = 0;
return;
@@ -406,7 +419,7 @@ intel_map_renderbuffer(struct gl_context *ctx,
out_map, out_stride);
} else if (intel->gen >= 6 &&
!(mode & GL_MAP_WRITE_BIT) &&
- irb->region->tiling == I915_TILING_X) {
+ irb->mt->region->tiling == I915_TILING_X) {
intel_map_renderbuffer_blit(ctx, rb, x, y, w, h, mode,
out_map, out_stride);
} else {
@@ -438,7 +451,7 @@ intel_unmap_renderbuffer_s8(struct gl_context *ctx,
* the real buffer.
*/
uint8_t *untiled_s8_map = irb->map_buffer;
- uint8_t *tiled_s8_map = irb->region->bo->virtual;
+ uint8_t *tiled_s8_map = irb->mt->region->bo->virtual;
/* Flip the Y axis for the default framebuffer. */
int y_flip = (rb->Name == 0) ? -1 : 1;
@@ -447,7 +460,7 @@ intel_unmap_renderbuffer_s8(struct gl_context *ctx,
for (uint32_t pix_y = 0; pix_y < irb->map_h; pix_y++) {
for (uint32_t pix_x = 0; pix_x < irb->map_w; pix_x++) {
uint32_t flipped_y = y_flip * (int32_t)(pix_y + irb->map_y) + y_bias;
- ptrdiff_t offset = intel_offset_S8(irb->region->pitch,
+ ptrdiff_t offset = intel_offset_S8(irb->mt->region->pitch,
pix_x + irb->map_x,
flipped_y);
tiled_s8_map[offset] =
@@ -456,7 +469,7 @@ intel_unmap_renderbuffer_s8(struct gl_context *ctx,
}
}
- intel_region_unmap(intel, irb->region);
+ intel_region_unmap(intel, irb->mt->region);
free(irb->map_buffer);
irb->map_buffer = NULL;
}
@@ -494,16 +507,16 @@ intel_unmap_renderbuffer_separate_s8z24(struct gl_context *ctx,
uint8_t *s8_map;
s8_irb = intel_renderbuffer(irb->wrapped_stencil);
- s8_map = intel_region_map(intel, s8_irb->region, GL_MAP_WRITE_BIT);
+ s8_map = intel_region_map(intel, s8_irb->mt->region, GL_MAP_WRITE_BIT);
- int32_t s8z24_stride = 4 * s8z24_irb->region->pitch;
- uint8_t *s8z24_map = s8z24_irb->region->bo->virtual
+ int32_t s8z24_stride = 4 * s8z24_irb->mt->region->pitch;
+ uint8_t *s8z24_map = s8z24_irb->mt->region->bo->virtual
+ map_y * s8z24_stride
+ map_x * 4;
for (uint32_t pix_y = 0; pix_y < map_h; ++pix_y) {
for (uint32_t pix_x = 0; pix_x < map_w; ++pix_x) {
- ptrdiff_t s8_offset = intel_offset_S8(s8_irb->region->pitch,
+ ptrdiff_t s8_offset = intel_offset_S8(s8_irb->mt->region->pitch,
map_x + pix_x,
map_y + pix_y);
ptrdiff_t s8z24_offset = pix_y * s8z24_stride
@@ -513,10 +526,10 @@ intel_unmap_renderbuffer_separate_s8z24(struct gl_context *ctx,
}
}
- intel_region_unmap(intel, s8_irb->region);
+ intel_region_unmap(intel, s8_irb->mt->region);
}
- drm_intel_gem_bo_unmap_gtt(s8z24_irb->region->bo);
+ drm_intel_gem_bo_unmap_gtt(s8z24_irb->mt->region->bo);
}
/**
@@ -542,11 +555,11 @@ intel_unmap_renderbuffer(struct gl_context *ctx,
irb->map_bo = 0;
} else {
/* Paired with intel_map_renderbuffer_gtt(). */
- if (irb->region) {
- /* The region may be null when intel_map_renderbuffer() is
+ if (irb->mt) {
+ /* The miptree may be null when intel_map_renderbuffer() is
* called from intel_span.c.
*/
- drm_intel_gem_bo_unmap_gtt(irb->region->bo);
+ drm_intel_gem_bo_unmap_gtt(irb->mt->region->bo);
}
}
}
@@ -613,13 +626,7 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer
intel_flush(ctx);
- /* free old region */
- if (irb->region) {
- intel_region_release(&irb->region);
- }
- if (irb->hiz_region) {
- intel_region_release(&irb->hiz_region);
- }
+ intel_miptree_release(&irb->mt);
DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(internalFormat),
@@ -651,17 +658,18 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer
*
* If we neglect to double the pitch, then render corruption occurs.
*/
- irb->region = intel_region_alloc(intel->intelScreen,
- I915_TILING_NONE,
- cpp * 2,
- ALIGN(width, 64),
- ALIGN((height + 1) / 2, 64),
- true);
- if (!irb->region)
- return false;
+ irb->mt = intel_miptree_create_for_renderbuffer(
+ intel,
+ rb->Format,
+ I915_TILING_NONE,
+ cpp * 2,
+ ALIGN(width, 64),
+ ALIGN((height + 1) / 2, 64));
+ if (!irb->mt)
+ return false;
} else if (irb->Base.Format == MESA_FORMAT_S8_Z24
- && intel->must_use_separate_stencil) {
+ && intel->has_separate_stencil) {
bool ok = true;
struct gl_renderbuffer *depth_rb;
@@ -695,20 +703,16 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer
_mesa_reference_renderbuffer(&irb->wrapped_stencil, stencil_rb);
} else {
- irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp,
- width, height, true);
- if (!irb->region)
+ irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format,
+ tiling, cpp,
+ width, height);
+ if (!irb->mt)
return false;
if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
- irb->hiz_region = intel_region_alloc(intel->intelScreen,
- I915_TILING_Y,
- irb->region->cpp,
- irb->region->width,
- irb->region->height,
- true);
- if (!irb->hiz_region) {
- intel_region_release(&irb->region);
+ bool ok = intel_miptree_alloc_hiz(intel, irb->mt);
+ if (!ok) {
+ intel_miptree_release(&irb->mt);
return false;
}
}
@@ -747,7 +751,13 @@ intel_image_target_renderbuffer_storage(struct gl_context *ctx,
}
irb = intel_renderbuffer(rb);
- intel_region_reference(&irb->region, image->region);
+ intel_miptree_release(&irb->mt);
+ irb->mt = intel_miptree_create_for_region(intel,
+ GL_TEXTURE_2D,
+ image->format,
+ image->region);
+ if (!irb->mt)
+ return;
rb->InternalFormat = image->internal_format;
rb->Width = image->region->width;
@@ -938,117 +948,141 @@ intel_framebuffer_renderbuffer(struct gl_context * ctx,
intel_draw_buffer(ctx);
}
-static bool
-intel_update_tex_wrapper_regions(struct intel_context *intel,
- struct intel_renderbuffer *irb,
- struct intel_texture_image *intel_image);
+static struct intel_renderbuffer*
+intel_renderbuffer_wrap_miptree(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer,
+ gl_format format,
+ GLenum internal_format);
+/**
+ * \par Special case for separate stencil
+ *
+ * When wrapping a depthstencil texture that uses separate stencil, this
+ * function is recursively called twice: once to create \c
+ * irb->wrapped_depth and again to create \c irb->wrapped_stencil. On the
+ * call to create \c irb->wrapped_depth, the \c format and \c
+ * internal_format parameters do not match \c mt->format. In that case, \c
+ * mt->format is MESA_FORMAT_S8_Z24 and \c format is \c
+ * MESA_FORMAT_X8_Z24.
+ *
+ * @return true on success
+ */
static bool
-intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb,
- struct gl_texture_image *texImage)
+intel_renderbuffer_update_wrapper(struct intel_context *intel,
+ struct intel_renderbuffer *irb,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer,
+ gl_format format,
+ GLenum internal_format)
{
- struct intel_context *intel = intel_context(ctx);
- struct intel_texture_image *intel_image = intel_texture_image(texImage);
- int width, height, depth;
+ struct gl_renderbuffer *rb = &irb->Base;
- if (!intel_span_supports_format(texImage->TexFormat)) {
+ rb->Format = format;
+ if (!intel_span_supports_format(rb->Format)) {
DBG("Render to texture BAD FORMAT %s\n",
- _mesa_get_format_name(texImage->TexFormat));
+ _mesa_get_format_name(rb->Format));
return false;
} else {
- DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat));
+ DBG("Render to texture %s\n", _mesa_get_format_name(rb->Format));
}
- intel_miptree_get_dimensions_for_image(texImage, &width, &height, &depth);
-
- irb->Base.Format = texImage->TexFormat;
- irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat);
- irb->Base.InternalFormat = texImage->InternalFormat;
- irb->Base._BaseFormat = _mesa_base_tex_format(ctx, irb->Base.InternalFormat);
- irb->Base.Width = width;
- irb->Base.Height = height;
+ rb->InternalFormat = internal_format;
+ rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format);
+ rb->_BaseFormat = _mesa_get_format_base_format(rb->Format);
+ rb->Width = mt->level[level].width;
+ rb->Height = mt->level[level].height;
irb->Base.Delete = intel_delete_renderbuffer;
irb->Base.AllocStorage = intel_nop_alloc_storage;
- if (intel_image->stencil_rb) {
- /* The tex image has packed depth/stencil format, but is using separate
- * stencil. */
-
- bool ok;
- struct intel_renderbuffer *depth_irb =
- intel_renderbuffer(intel_image->depth_rb);
-
- /* Update the hiz region if necessary. */
- ok = intel_update_tex_wrapper_regions(intel, depth_irb, intel_image);
- if (!ok) {
- return false;
+ intel_miptree_check_level_layer(mt, level, layer);
+ irb->mt_level = level;
+ irb->mt_layer = layer;
+
+ if (mt->stencil_mt && _mesa_is_depthstencil_format(rb->InternalFormat)) {
+ assert((irb->wrapped_depth == NULL) == (irb->wrapped_stencil == NULL));
+
+ struct intel_renderbuffer *depth_irb;
+ struct intel_renderbuffer *stencil_irb;
+
+ if (!irb->wrapped_depth) {
+ depth_irb = intel_renderbuffer_wrap_miptree(intel,
+ mt, level, layer,
+ MESA_FORMAT_X8_Z24,
+ GL_DEPTH_COMPONENT24);
+ stencil_irb = intel_renderbuffer_wrap_miptree(intel,
+ mt->stencil_mt,
+ level, layer,
+ MESA_FORMAT_S8,
+ GL_STENCIL_INDEX8);
+ _mesa_reference_renderbuffer(&irb->wrapped_depth, &depth_irb->Base);
+ _mesa_reference_renderbuffer(&irb->wrapped_stencil, &stencil_irb->Base);
+
+ if (!irb->wrapped_depth || !irb->wrapped_stencil)
+ return false;
+ } else {
+ bool ok = true;
+
+ depth_irb = intel_renderbuffer(irb->wrapped_depth);
+ stencil_irb = intel_renderbuffer(irb->wrapped_stencil);
+
+ ok &= intel_renderbuffer_update_wrapper(intel,
+ depth_irb,
+ mt,
+ level, layer,
+ MESA_FORMAT_X8_Z24,
+ GL_DEPTH_COMPONENT24);
+ ok &= intel_renderbuffer_update_wrapper(intel,
+ stencil_irb,
+ mt->stencil_mt,
+ level, layer,
+ MESA_FORMAT_S8,
+ GL_STENCIL_INDEX8);
+ if (!ok)
+ return false;
}
-
- /* The tex image shares its embedded depth and stencil renderbuffers with
- * the renderbuffer wrapper. */
- _mesa_reference_renderbuffer(&irb->wrapped_depth,
- intel_image->depth_rb);
- _mesa_reference_renderbuffer(&irb->wrapped_stencil,
- intel_image->stencil_rb);
-
- return true;
} else {
- return intel_update_tex_wrapper_regions(intel, irb, intel_image);
- }
-}
-
-/**
- * FIXME: The handling of the hiz region is broken for mipmapped depth textures
- * FIXME: because intel_finalize_mipmap_tree is unaware of it.
- */
-static bool
-intel_update_tex_wrapper_regions(struct intel_context *intel,
- struct intel_renderbuffer *irb,
- struct intel_texture_image *intel_image)
-{
- struct gl_renderbuffer *rb = &irb->Base;
-
- /* Point the renderbuffer's region to the texture's region. */
- if (irb->region != intel_image->mt->region) {
- intel_region_reference(&irb->region, intel_image->mt->region);
- }
-
- /* Allocate the texture's hiz region if necessary. */
- if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)
- && !intel_image->mt->hiz_region) {
- intel_image->mt->hiz_region =
- intel_region_alloc(intel->intelScreen,
- I915_TILING_Y,
- _mesa_get_format_bytes(rb->Format),
- rb->Width,
- rb->Height,
- true);
- if (!intel_image->mt->hiz_region)
- return false;
- }
-
- /* Point the renderbuffer's hiz region to the texture's hiz region. */
- if (irb->hiz_region != intel_image->mt->hiz_region) {
- intel_region_reference(&irb->hiz_region, intel_image->mt->hiz_region);
+ 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);
+ if (!mt->hiz_mt)
+ return false;
+ }
}
return true;
}
-
/**
- * When glFramebufferTexture[123]D is called this function sets up the
- * gl_renderbuffer wrapper around the texture image.
- * This will have the region info needed for hardware rendering.
+ * \brief Wrap a renderbuffer around a single slice of a miptree.
+ *
+ * Called by glFramebufferTexture*(). This just allocates a
+ * ``struct intel_renderbuffer`` then calls
+ * intel_renderbuffer_update_wrapper() to do the real work.
+ *
+ * \see intel_renderbuffer_update_wrapper()
*/
-static struct intel_renderbuffer *
-intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
+static struct intel_renderbuffer*
+intel_renderbuffer_wrap_miptree(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer,
+ gl_format format,
+ GLenum internal_format)
+
{
const GLuint name = ~0; /* not significant, but distinct for debugging */
+ struct gl_context *ctx = &intel->ctx;
struct intel_renderbuffer *irb;
- /* make an intel_renderbuffer to wrap the texture image */
+ intel_miptree_check_level_layer(mt, level, layer);
+
irb = CALLOC_STRUCT(intel_renderbuffer);
if (!irb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
@@ -1058,7 +1092,9 @@ intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
_mesa_init_renderbuffer(&irb->Base, name);
irb->Base.ClassID = INTEL_RB_CLASS;
- if (!intel_update_wrapper(ctx, irb, texImage)) {
+ if (!intel_renderbuffer_update_wrapper(intel, irb,
+ mt, level, layer,
+ format, internal_format)) {
free(irb);
return NULL;
}
@@ -1067,17 +1103,15 @@ intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
}
void
-intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb,
- struct intel_texture_image *intel_image,
- int zoffset)
+intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb)
{
unsigned int dst_x, dst_y;
/* compute offset of the particular 2D image within the texture region */
- intel_miptree_get_image_offset(intel_image->mt,
- intel_image->base.Base.Level,
- intel_image->base.Base.Face,
- zoffset,
+ intel_miptree_get_image_offset(irb->mt,
+ irb->mt_level,
+ 0, /* face, which we ignore */
+ irb->mt_layer,
&dst_x, &dst_y);
irb->draw_x = dst_x;
@@ -1099,20 +1133,21 @@ intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
uint32_t *tile_x,
uint32_t *tile_y)
{
- int cpp = irb->region->cpp;
- uint32_t pitch = irb->region->pitch * cpp;
+ struct intel_region *region = irb->mt->region;
+ int cpp = region->cpp;
+ uint32_t pitch = region->pitch * cpp;
- if (irb->region->tiling == I915_TILING_NONE) {
+ if (region->tiling == I915_TILING_NONE) {
*tile_x = 0;
*tile_y = 0;
return irb->draw_x * cpp + irb->draw_y * pitch;
- } else if (irb->region->tiling == I915_TILING_X) {
+ } else if (region->tiling == I915_TILING_X) {
*tile_x = irb->draw_x % (512 / cpp);
*tile_y = irb->draw_y % 8;
return ((irb->draw_y / 8) * (8 * pitch) +
(irb->draw_x - *tile_x) / (512 / cpp) * 4096);
} else {
- assert(irb->region->tiling == I915_TILING_Y);
+ assert(region->tiling == I915_TILING_Y);
*tile_x = irb->draw_x % (128 / cpp);
*tile_y = irb->draw_y % 32;
return ((irb->draw_y / 32) * (32 * pitch) +
@@ -1147,12 +1182,22 @@ intel_render_texture(struct gl_context * ctx,
struct gl_framebuffer *fb,
struct gl_renderbuffer_attachment *att)
{
+ struct intel_context *intel = intel_context(ctx);
struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
struct intel_texture_image *intel_image = intel_texture_image(image);
+ struct intel_mipmap_tree *mt = intel_image->mt;
(void) fb;
+ int layer;
+ if (att->CubeMapFace > 0) {
+ assert(att->Zoffset == 0);
+ layer = att->CubeMapFace;
+ } else {
+ layer = att->Zoffset;
+ }
+
if (!intel_image->mt) {
/* Fallback on drawing to a texture that doesn't have a miptree
* (has a border, width/height 0, etc.)
@@ -1162,7 +1207,13 @@ intel_render_texture(struct gl_context * ctx,
return;
}
else if (!irb) {
- irb = intel_wrap_texture(ctx, image);
+ irb = intel_renderbuffer_wrap_miptree(intel,
+ mt,
+ att->TextureLevel,
+ layer,
+ image->TexFormat,
+ image->InternalFormat);
+
if (irb) {
/* bind the wrapper to the attachment point */
_mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
@@ -1174,7 +1225,10 @@ intel_render_texture(struct gl_context * ctx,
}
}
- if (!intel_update_wrapper(ctx, irb, image)) {
+ if (!intel_renderbuffer_update_wrapper(intel, irb,
+ mt, att->TextureLevel, layer,
+ image->TexFormat,
+ image->InternalFormat)) {
_mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
_swrast_render_texture(ctx, fb, att);
return;
@@ -1185,7 +1239,6 @@ intel_render_texture(struct gl_context * ctx,
att->Texture->Name, image->Width, image->Height,
irb->Base.RefCount);
- intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
intel_image->used_as_render_target = true;
#ifndef I915
@@ -1211,9 +1264,9 @@ intel_render_texture(struct gl_context * ctx,
true);
intel_miptree_copy_teximage(intel, intel_image, new_mt);
- intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
+ intel_renderbuffer_set_draw_offset(irb);
- intel_region_reference(&irb->region, intel_image->mt->region);
+ intel_miptree_reference(&irb->mt, intel_image->mt);
intel_miptree_release(&new_mt);
}
#endif
@@ -1395,6 +1448,69 @@ intel_blit_framebuffer(struct gl_context *ctx,
mask, filter);
}
+void
+intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb)
+{
+ if (irb->mt) {
+ intel_miptree_slice_set_needs_hiz_resolve(irb->mt,
+ irb->mt_level,
+ irb->mt_layer);
+ } else if (irb->wrapped_depth) {
+ intel_renderbuffer_set_needs_hiz_resolve(
+ intel_renderbuffer(irb->wrapped_depth));
+ } else {
+ return;
+ }
+}
+
+void
+intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb)
+{
+ if (irb->mt) {
+ intel_miptree_slice_set_needs_depth_resolve(irb->mt,
+ irb->mt_level,
+ irb->mt_layer);
+ } else if (irb->wrapped_depth) {
+ intel_renderbuffer_set_needs_depth_resolve(
+ intel_renderbuffer(irb->wrapped_depth));
+ } else {
+ return;
+ }
+}
+
+bool
+intel_renderbuffer_resolve_hiz(struct intel_context *intel,
+ struct intel_renderbuffer *irb)
+{
+ if (irb->mt)
+ return intel_miptree_slice_resolve_hiz(intel,
+ irb->mt,
+ irb->mt_level,
+ irb->mt_layer);
+ if (irb->wrapped_depth)
+ return intel_renderbuffer_resolve_hiz(intel,
+ intel_renderbuffer(irb->wrapped_depth));
+
+ return false;
+}
+
+bool
+intel_renderbuffer_resolve_depth(struct intel_context *intel,
+ struct intel_renderbuffer *irb)
+{
+ if (irb->mt)
+ return intel_miptree_slice_resolve_depth(intel,
+ irb->mt,
+ irb->mt_level,
+ irb->mt_layer);
+
+ if (irb->wrapped_depth)
+ return intel_renderbuffer_resolve_depth(intel,
+ intel_renderbuffer(irb->wrapped_depth));
+
+ return false;
+}
+
/**
* Do one-time context initializations related to GL_EXT_framebuffer_object.
* Hook in device driver functions.
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.h b/src/mesa/drivers/dri/intel/intel_fbo.h
index 4cc57fe60be..bb943099fd3 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.h
+++ b/src/mesa/drivers/dri/intel/intel_fbo.h
@@ -35,6 +35,7 @@
#include "intel_screen.h"
struct intel_context;
+struct intel_mipmap_tree;
struct intel_texture_image;
/**
@@ -43,14 +44,29 @@ struct intel_texture_image;
struct intel_renderbuffer
{
struct gl_renderbuffer Base;
- struct intel_region *region;
+ struct intel_mipmap_tree *mt; /**< The renderbuffer storage. */
drm_intel_bo *map_bo;
+
void *map_buffer;
GLuint map_x, map_y, map_w, map_h;
GLbitfield map_mode;
- /** Only used by depth renderbuffers for which HiZ is enabled. */
- struct intel_region *hiz_region;
+ /**
+ * \name Miptree view
+ * \{
+ *
+ * Multiple renderbuffers may simultaneously wrap a single texture and each
+ * provide a different view into that texture. The fields below indicate
+ * which miptree slice is wrapped by this renderbuffer. The fields' values
+ * are consistent with the 'level' and 'layer' parameters of
+ * glFramebufferTextureLayer().
+ *
+ * For renderbuffers not created with glFramebufferTexture*(), mt_level and
+ * mt_layer are 0.
+ */
+ unsigned int mt_level;
+ unsigned int mt_layer;
+ /** \} */
/**
* \name Packed depth/stencil unwrappers
@@ -134,28 +150,8 @@ intel_get_renderbuffer(struct gl_framebuffer *fb, gl_buffer_index attIndex)
return irb;
}
-/**
- * If the framebuffer has a depth buffer attached, then return its HiZ region.
- * The HiZ region may be null.
- */
-static INLINE struct intel_region*
-intel_framebuffer_get_hiz_region(struct gl_framebuffer *fb)
-{
- struct intel_renderbuffer *rb = NULL;
- if (fb)
- rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
-
- if (rb)
- return rb->hiz_region;
- else
- return NULL;
-}
-
-static INLINE bool
-intel_framebuffer_has_hiz(struct gl_framebuffer *fb)
-{
- return intel_framebuffer_get_hiz_region(fb) != NULL;
-}
+bool
+intel_framebuffer_has_hiz(struct gl_framebuffer *fb);
extern struct intel_renderbuffer *
intel_create_renderbuffer(gl_format format);
@@ -179,23 +175,45 @@ extern void
intel_flip_renderbuffers(struct gl_framebuffer *fb);
void
-intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb,
- struct intel_texture_image *intel_image,
- int zoffset);
+intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb);
uint32_t
intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
uint32_t *tile_x,
uint32_t *tile_y);
-static INLINE struct intel_region *
-intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
-{
- struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex);
- if (irb)
- return irb->region;
- else
- return NULL;
-}
+struct intel_region*
+intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex);
+
+void
+intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb);
+
+void
+intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb);
+
+
+/**
+ * \brief Perform a HiZ resolve on the renderbuffer.
+ *
+ * It is safe to call this function on a renderbuffer without HiZ. In that
+ * case, the function is a no-op.
+ *
+ * \return false if no resolve was needed
+ */
+bool
+intel_renderbuffer_resolve_hiz(struct intel_context *intel,
+ struct intel_renderbuffer *irb);
+
+/**
+ * \brief Perform a depth resolve on the renderbuffer.
+ *
+ * It is safe to call this function on a renderbuffer without HiZ. In that
+ * case, the function is a no-op.
+ *
+ * \return false if no resolve was needed
+ */
+bool
+intel_renderbuffer_resolve_depth(struct intel_context *intel,
+ struct intel_renderbuffer *irb);
#endif /* INTEL_FBO_H */
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index 19f151f4fa3..f8ef2625df3 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -25,19 +25,23 @@
*
**************************************************************************/
+#include "intel_batchbuffer.h"
#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
+#include "intel_resolve_map.h"
+#include "intel_span.h"
#include "intel_tex_layout.h"
#include "intel_tex.h"
#include "intel_blit.h"
+
#include "main/enums.h"
#include "main/formats.h"
+#include "main/image.h"
#include "main/teximage.h"
#define FILE_DEBUG_FLAG DEBUG_MIPTREE
-
static GLenum
target_to_target(GLenum target)
{
@@ -54,7 +58,6 @@ target_to_target(GLenum target)
}
}
-
static struct intel_mipmap_tree *
intel_miptree_create_internal(struct intel_context *intel,
GLenum target,
@@ -82,11 +85,30 @@ intel_miptree_create_internal(struct intel_context *intel,
mt->last_level = last_level;
mt->width0 = width0;
mt->height0 = height0;
- mt->depth0 = depth0;
mt->cpp = compress_byte ? compress_byte : _mesa_get_format_bytes(mt->format);
mt->compressed = compress_byte ? 1 : 0;
mt->refcount = 1;
+ intel_get_texture_alignment_unit(intel, format,
+ &mt->align_w, &mt->align_h);
+
+ if (target == GL_TEXTURE_CUBE_MAP) {
+ assert(depth0 == 1);
+ mt->depth0 = 6;
+ } else {
+ mt->depth0 = depth0;
+ }
+
+ if (format == MESA_FORMAT_S8) {
+ /* The stencil buffer has quirky pitch requirements. From Vol 2a,
+ * 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
+ * The pitch must be set to 2x the value computed based on width, as
+ * the stencil buffer is stored with two rows interleaved.
+ */
+ assert(intel->has_separate_stencil);
+ mt->cpp = 2;
+ }
+
#ifdef I915
(void) intel;
if (intel->is_945)
@@ -97,6 +119,23 @@ intel_miptree_create_internal(struct intel_context *intel,
brw_miptree_layout(intel, mt);
#endif
+ if (intel->has_separate_stencil &&
+ _mesa_is_depthstencil_format(_mesa_get_format_base_format(format))) {
+ mt->stencil_mt = intel_miptree_create(intel,
+ mt->target,
+ MESA_FORMAT_S8,
+ mt->first_level,
+ mt->last_level,
+ mt->width0,
+ mt->height0,
+ mt->depth0,
+ true);
+ if (!mt->stencil_mt) {
+ intel_miptree_release(&mt);
+ return NULL;
+ }
+ }
+
return mt;
}
@@ -121,6 +160,8 @@ intel_miptree_create(struct intel_context *intel,
(base_format == GL_DEPTH_COMPONENT ||
base_format == GL_DEPTH_STENCIL_EXT))
tiling = I915_TILING_Y;
+ else if (format == MESA_FORMAT_S8)
+ tiling = I915_TILING_NONE;
else if (width0 >= 64)
tiling = I915_TILING_X;
}
@@ -171,6 +212,27 @@ intel_miptree_create_for_region(struct intel_context *intel,
return mt;
}
+struct intel_mipmap_tree*
+intel_miptree_create_for_renderbuffer(struct intel_context *intel,
+ gl_format format,
+ uint32_t tiling,
+ uint32_t cpp,
+ uint32_t width,
+ uint32_t height)
+{
+ struct intel_region *region;
+ struct intel_mipmap_tree *mt;
+
+ region = intel_region_alloc(intel->intelScreen,
+ tiling, cpp, width, height, true);
+ if (!region)
+ return NULL;
+
+ mt = intel_miptree_create_for_region(intel, GL_TEXTURE_2D, format, region);
+ intel_region_release(&region);
+ return mt;
+}
+
void
intel_miptree_reference(struct intel_mipmap_tree **dst,
struct intel_mipmap_tree *src)
@@ -202,11 +264,12 @@ intel_miptree_release(struct intel_mipmap_tree **mt)
DBG("%s deleting %p\n", __FUNCTION__, *mt);
intel_region_release(&((*mt)->region));
- intel_region_release(&((*mt)->hiz_region));
+ intel_miptree_release(&(*mt)->stencil_mt);
+ intel_miptree_release(&(*mt)->hiz_mt);
+ intel_resolve_map_clear(&(*mt)->hiz_map);
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
- free((*mt)->level[i].x_offset);
- free((*mt)->level[i].y_offset);
+ free((*mt)->level[i].slice);
}
free(*mt);
@@ -267,7 +330,6 @@ intel_miptree_match_image(struct intel_mipmap_tree *mt,
void
intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
GLuint level,
- GLuint nr_images,
GLuint x, GLuint y,
GLuint w, GLuint h, GLuint d)
{
@@ -276,18 +338,15 @@ intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
mt->level[level].depth = d;
mt->level[level].level_x = x;
mt->level[level].level_y = y;
- mt->level[level].nr_images = nr_images;
DBG("%s level %d size: %d,%d,%d offset %d,%d\n", __FUNCTION__,
level, w, h, d, x, y);
- assert(nr_images);
- assert(!mt->level[level].x_offset);
+ assert(mt->level[level].slice == NULL);
- mt->level[level].x_offset = malloc(nr_images * sizeof(GLuint));
- mt->level[level].x_offset[0] = mt->level[level].level_x;
- mt->level[level].y_offset = malloc(nr_images * sizeof(GLuint));
- mt->level[level].y_offset[0] = mt->level[level].level_y;
+ mt->level[level].slice = malloc(d * sizeof(*mt->level[0].slice));
+ mt->level[level].slice[0].x_offset = mt->level[level].level_x;
+ mt->level[level].slice[0].y_offset = mt->level[level].level_y;
}
@@ -299,38 +358,110 @@ intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
if (img == 0 && level == 0)
assert(x == 0 && y == 0);
- assert(img < mt->level[level].nr_images);
+ assert(img < mt->level[level].depth);
- mt->level[level].x_offset[img] = mt->level[level].level_x + x;
- mt->level[level].y_offset[img] = mt->level[level].level_y + y;
+ mt->level[level].slice[img].x_offset = mt->level[level].level_x + x;
+ mt->level[level].slice[img].y_offset = mt->level[level].level_y + y;
DBG("%s level %d img %d pos %d,%d\n",
__FUNCTION__, level, img,
- mt->level[level].x_offset[img], mt->level[level].y_offset[img]);
+ mt->level[level].slice[img].x_offset,
+ mt->level[level].slice[img].y_offset);
}
+/**
+ * For cube map textures, either the \c face parameter can be used, of course,
+ * or the cube face can be interpreted as a depth layer and the \c layer
+ * parameter used.
+ */
void
intel_miptree_get_image_offset(struct intel_mipmap_tree *mt,
- GLuint level, GLuint face, GLuint depth,
+ GLuint level, GLuint face, GLuint layer,
GLuint *x, GLuint *y)
{
- switch (mt->target) {
- case GL_TEXTURE_CUBE_MAP_ARB:
- *x = mt->level[level].x_offset[face];
- *y = mt->level[level].y_offset[face];
- break;
- case GL_TEXTURE_3D:
- case GL_TEXTURE_2D_ARRAY_EXT:
- case GL_TEXTURE_1D_ARRAY_EXT:
- assert(depth < mt->level[level].nr_images);
- *x = mt->level[level].x_offset[depth];
- *y = mt->level[level].y_offset[depth];
- break;
- default:
- *x = mt->level[level].x_offset[0];
- *y = mt->level[level].y_offset[0];
- break;
+ int slice;
+
+ if (face > 0) {
+ assert(mt->target == GL_TEXTURE_CUBE_MAP);
+ assert(face < 6);
+ assert(layer == 0);
+ slice = face;
+ } else {
+ /* This branch may be taken even if the texture target is a cube map. In
+ * that case, the caller chose to interpret each cube face as a layer.
+ */
+ assert(face == 0);
+ slice = layer;
+ }
+
+ *x = mt->level[level].slice[slice].x_offset;
+ *y = mt->level[level].slice[slice].y_offset;
+}
+
+static void
+intel_miptree_copy_slice(struct intel_context *intel,
+ struct intel_mipmap_tree *dst_mt,
+ struct intel_mipmap_tree *src_mt,
+ int level,
+ int face,
+ int depth)
+
+{
+ gl_format format = src_mt->format;
+ uint32_t width = src_mt->level[level].width;
+ uint32_t height = src_mt->level[level].height;
+
+ assert(depth < src_mt->level[level].depth);
+
+ if (dst_mt->compressed) {
+ height = ALIGN(height, dst_mt->align_h) / dst_mt->align_h;
+ width = ALIGN(width, dst_mt->align_w);
+ }
+
+ uint32_t dst_x, dst_y, src_x, src_y;
+ intel_miptree_get_image_offset(dst_mt, level, face, depth,
+ &dst_x, &dst_y);
+ intel_miptree_get_image_offset(src_mt, level, face, depth,
+ &src_x, &src_y);
+
+ DBG("validate blit mt %p %d,%d/%d -> mt %p %d,%d/%d (%dx%d)\n",
+ src_mt, src_x, src_y, src_mt->region->pitch * src_mt->region->cpp,
+ dst_mt, dst_x, dst_y, dst_mt->region->pitch * dst_mt->region->cpp,
+ width, height);
+
+ if (!intelEmitCopyBlit(intel,
+ dst_mt->region->cpp,
+ src_mt->region->pitch, src_mt->region->bo,
+ 0, src_mt->region->tiling,
+ dst_mt->region->pitch, dst_mt->region->bo,
+ 0, dst_mt->region->tiling,
+ src_x, src_y,
+ dst_x, dst_y,
+ width, height,
+ GL_COPY)) {
+
+ fallback_debug("miptree validate blit for %s failed\n",
+ _mesa_get_format_name(format));
+ void *dst = intel_region_map(intel, dst_mt->region, GL_MAP_WRITE_BIT);
+ void *src = intel_region_map(intel, src_mt->region, GL_MAP_READ_BIT);
+
+ _mesa_copy_rect(dst,
+ dst_mt->cpp,
+ dst_mt->region->pitch,
+ dst_x, dst_y,
+ width, height,
+ src, src_mt->region->pitch,
+ src_x, src_y);
+
+ intel_region_unmap(intel, dst_mt->region);
+ intel_region_unmap(intel, src_mt->region);
+ }
+
+ if (src_mt->stencil_mt) {
+ intel_miptree_copy_slice(intel,
+ dst_mt->stencil_mt, src_mt->stencil_mt,
+ level, face, depth);
}
}
@@ -346,65 +477,256 @@ intel_miptree_copy_teximage(struct intel_context *intel,
struct intel_mipmap_tree *src_mt = intelImage->mt;
int level = intelImage->base.Base.Level;
int face = intelImage->base.Base.Face;
- GLuint width = src_mt->level[level].width;
- GLuint height = src_mt->level[level].height;
- GLuint depth = src_mt->level[level].depth;
- int slice;
- void *src, *dst;
+ GLuint depth = intelImage->base.Base.Depth;
- if (dst_mt->compressed) {
- unsigned int align_w, align_h;
+ for (int slice = 0; slice < depth; slice++) {
+ intel_miptree_copy_slice(intel, dst_mt, src_mt, level, face, slice);
+ }
- intel_get_texture_alignment_unit(intelImage->base.Base.TexFormat,
- &align_w, &align_h);
- height = ALIGN(height, align_h) / align_h;
- width = ALIGN(width, align_w);
+ intel_miptree_reference(&intelImage->mt, dst_mt);
+}
+
+/**
+ * \param scatter Scatter if true. Gather if false.
+ *
+ * \see intel_miptree_s8z24_scatter()
+ * \see intel_miptree_s8z24_gather()
+ */
+static void
+intel_miptree_s8z24_scattergather(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer,
+ bool scatter)
+{
+ /* Check function inputs. */
+ assert(level >= mt->first_level);
+ assert(level <= mt->last_level);
+ assert(layer < mt->level[level].depth);
+
+ /* Label everything and its bit layout, just to make the code easier to
+ * read.
+ */
+ struct intel_mipmap_tree *s8_mt = mt->stencil_mt;
+ struct intel_mipmap_level *s8_level = &s8_mt->level[level];
+ struct intel_mipmap_slice *s8_slice = &s8_mt->level[level].slice[layer];
+
+ struct intel_mipmap_tree *s8z24_mt = mt;
+ struct intel_mipmap_level *s8z24_level = &s8z24_mt->level[level];
+ struct intel_mipmap_slice *s8z24_slice = &s8z24_mt->level[level].slice[layer];
+
+ /* Check that both miptree levels have the same dimensions. */
+ assert(s8_level->width == s8z24_level->width);
+ assert(s8_level->height == s8z24_level->height);
+ assert(s8_level->depth == s8z24_level->depth);
+
+ /* Map the buffers. */
+ if (drm_intel_bo_references(intel->batch.bo, s8_mt->region->bo) ||
+ drm_intel_bo_references(intel->batch.bo, s8z24_mt->region->bo)) {
+ intel_batchbuffer_flush(intel);
}
+ drm_intel_gem_bo_map_gtt(s8_mt->region->bo);
+ drm_intel_gem_bo_map_gtt(s8z24_mt->region->bo);
- for (slice = 0; slice < depth; slice++) {
- unsigned int dst_x, dst_y, src_x, src_y;
+ /* Define the invariant values outside the for loop, because I don't trust
+ * GCC to do it for us.
+ */
+ uint8_t *s8_map = s8_mt->region->bo->virtual
+ + s8_slice->x_offset
+ + s8_slice->y_offset;
+
+ uint8_t *s8z24_map = s8z24_mt->region->bo->virtual
+ + s8z24_slice->x_offset
+ + s8z24_slice->y_offset;
+
+ ptrdiff_t s8z24_stride = s8z24_mt->region->pitch * s8z24_mt->region->cpp;
+
+ uint32_t w = s8_level->width;
+ uint32_t h = s8_level->height;
+
+ for (uint32_t y = 0; y < h; ++y) {
+ for (uint32_t x = 0; x < w; ++x) {
+ ptrdiff_t s8_offset = intel_offset_S8(s8_mt->region->pitch, x, y);
+ ptrdiff_t s8z24_offset = y * s8z24_stride
+ + x * 4
+ + 3;
+ if (scatter) {
+ s8_map[s8_offset] = s8z24_map[s8z24_offset];
+ } else {
+ s8z24_map[s8z24_offset] = s8_map[s8_offset];
+ }
+ }
+ }
- intel_miptree_get_image_offset(dst_mt, level, face, slice,
- &dst_x, &dst_y);
+ drm_intel_gem_bo_unmap_gtt(s8_mt->region->bo);
+ drm_intel_gem_bo_unmap_gtt(s8z24_mt->region->bo);
+}
- /* Copy potentially with the blitter:
- */
- intel_miptree_get_image_offset(src_mt, level, face, slice,
- &src_x, &src_y);
-
- DBG("validate blit mt %p %d,%d/%d -> mt %p %d,%d/%d (%dx%d)\n",
- src_mt, src_x, src_y, src_mt->region->pitch * src_mt->region->cpp,
- dst_mt, dst_x, dst_y, dst_mt->region->pitch * dst_mt->region->cpp,
- width, height);
-
- if (!intelEmitCopyBlit(intel,
- dst_mt->region->cpp,
- src_mt->region->pitch, src_mt->region->bo,
- 0, src_mt->region->tiling,
- dst_mt->region->pitch, dst_mt->region->bo,
- 0, dst_mt->region->tiling,
- src_x, src_y,
- dst_x, dst_y,
- width, height,
- GL_COPY)) {
-
- fallback_debug("miptree validate blit for %s failed\n",
- _mesa_get_format_name(intelImage->base.Base.TexFormat));
- dst = intel_region_map(intel, dst_mt->region, GL_MAP_WRITE_BIT);
- src = intel_region_map(intel, src_mt->region, GL_MAP_READ_BIT);
-
- _mesa_copy_rect(dst,
- dst_mt->cpp,
- dst_mt->region->pitch,
- dst_x, dst_y,
- width, height,
- src, src_mt->region->pitch,
- src_x, src_y);
-
- intel_region_unmap(intel, dst_mt->region);
- intel_region_unmap(intel, src_mt->region);
+void
+intel_miptree_s8z24_scatter(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer)
+{
+ intel_miptree_s8z24_scattergather(intel, mt, level, layer, true);
+}
+
+void
+intel_miptree_s8z24_gather(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer)
+{
+ intel_miptree_s8z24_scattergather(intel, mt, level, layer, false);
+}
+
+bool
+intel_miptree_alloc_hiz(struct intel_context *intel,
+ struct intel_mipmap_tree *mt)
+{
+ assert(mt->hiz_mt == NULL);
+ mt->hiz_mt = intel_miptree_create(intel,
+ mt->target,
+ MESA_FORMAT_X8_Z24,
+ mt->first_level,
+ mt->last_level,
+ mt->width0,
+ mt->height0,
+ mt->depth0,
+ true);
+
+ if (!mt->hiz_mt)
+ return false;
+
+ /* Mark that all slices need a HiZ resolve. */
+ struct intel_resolve_map *head = &mt->hiz_map;
+ for (int level = mt->first_level; level <= mt->last_level; ++level) {
+ for (int layer = 0; layer < mt->level[level].depth; ++layer) {
+ head->next = malloc(sizeof(*head->next));
+ head->next->prev = head;
+ head->next->next = NULL;
+ head = head->next;
+
+ head->level = level;
+ head->layer = layer;
+ head->need = INTEL_NEED_HIZ_RESOLVE;
}
}
- intel_miptree_reference(&intelImage->mt, dst_mt);
+ return true;
+}
+
+void
+intel_miptree_slice_set_needs_hiz_resolve(struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer)
+{
+ intel_miptree_check_level_layer(mt, level, layer);
+
+ if (!mt->hiz_mt)
+ return;
+
+ intel_resolve_map_set(&mt->hiz_map,
+ level, layer, INTEL_NEED_HIZ_RESOLVE);
+}
+
+
+void
+intel_miptree_slice_set_needs_depth_resolve(struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer)
+{
+ intel_miptree_check_level_layer(mt, level, layer);
+
+ if (!mt->hiz_mt)
+ return;
+
+ intel_resolve_map_set(&mt->hiz_map,
+ level, layer, INTEL_NEED_DEPTH_RESOLVE);
+}
+
+typedef void (*resolve_func_t)(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer);
+
+static bool
+intel_miptree_slice_resolve(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer,
+ enum intel_need_resolve need,
+ resolve_func_t func)
+{
+ intel_miptree_check_level_layer(mt, level, layer);
+
+ struct intel_resolve_map *item =
+ intel_resolve_map_get(&mt->hiz_map, level, layer);
+
+ if (!item || item->need != need)
+ return false;
+
+ func(intel, mt, level, layer);
+ intel_resolve_map_remove(item);
+ return true;
+}
+
+bool
+intel_miptree_slice_resolve_hiz(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer)
+{
+ return intel_miptree_slice_resolve(intel, mt, level, layer,
+ INTEL_NEED_HIZ_RESOLVE,
+ intel->vtbl.resolve_hiz_slice);
+}
+
+bool
+intel_miptree_slice_resolve_depth(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer)
+{
+ return intel_miptree_slice_resolve(intel, mt, level, layer,
+ INTEL_NEED_DEPTH_RESOLVE,
+ intel->vtbl.resolve_depth_slice);
+}
+
+static bool
+intel_miptree_all_slices_resolve(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ enum intel_need_resolve need,
+ resolve_func_t func)
+{
+ bool did_resolve = false;
+ struct intel_resolve_map *i;
+
+ for (i = mt->hiz_map.next; i; i = i->next) {
+ if (i->need != need)
+ continue;
+ func(intel, mt, i->level, i->layer);
+ intel_resolve_map_remove(i);
+ did_resolve = true;
+ }
+
+ return did_resolve;
+}
+
+bool
+intel_miptree_all_slices_resolve_hiz(struct intel_context *intel,
+ struct intel_mipmap_tree *mt)
+{
+ return intel_miptree_all_slices_resolve(intel, mt,
+ INTEL_NEED_HIZ_RESOLVE,
+ intel->vtbl.resolve_hiz_slice);
+}
+
+bool
+intel_miptree_all_slices_resolve_depth(struct intel_context *intel,
+ struct intel_mipmap_tree *mt)
+{
+ return intel_miptree_all_slices_resolve(intel, mt,
+ INTEL_NEED_DEPTH_RESOLVE,
+ intel->vtbl.resolve_depth_slice);
}
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
index e29b9431939..fda704b9065 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
@@ -28,7 +28,10 @@
#ifndef INTEL_MIPMAP_TREE_H
#define INTEL_MIPMAP_TREE_H
+#include <assert.h>
+
#include "intel_regions.h"
+#include "intel_resolve_map.h"
/* A layer on top of the intel_regions code which adds:
*
@@ -56,6 +59,7 @@
* temporary system buffers.
*/
+struct intel_resolve_map;
struct intel_texture_image;
/**
@@ -69,22 +73,44 @@ struct intel_mipmap_level
GLuint level_y;
GLuint width;
GLuint height;
- /** Depth of the mipmap at this level: 1 for 1D/2D/CUBE, n for 3D. */
+
+ /**
+ * \brief Number of 2D slices in this miplevel.
+ *
+ * The exact semantics of depth varies according to the texture target:
+ * - For GL_TEXTURE_CUBE_MAP, depth is 6.
+ * - For GL_TEXTURE_2D_ARRAY, depth is the number of array slices. It is
+ * identical for all miplevels in the texture.
+ * - For GL_TEXTURE_3D, it is the texture's depth at this miplevel. Its
+ * value, like width and height, varies with miplevel.
+ * - For other texture types, depth is 1.
+ */
GLuint depth;
- /** Number of images at this level: 1 for 1D/2D, 6 for CUBE, depth for 3D */
- GLuint nr_images;
- /** @{
- * offsets from level_[xy] to the image for each cube face or depth
- * level.
+ /**
+ * \brief List of 2D images in this mipmap level.
*
- * Pretty much have to accept that hardware formats
- * are going to be so diverse that there is no unified way to
- * compute the offsets of depth/cube images within a mipmap level,
- * so have to store them as a lookup table.
+ * This may be a list of cube faces, array slices in 2D array texture, or
+ * layers in a 3D texture. The list's length is \c depth.
*/
- GLuint *x_offset, *y_offset;
- /** @} */
+ struct intel_mipmap_slice {
+ /**
+ * \name Offset to slice
+ * \{
+ *
+ * Hardware formats are so diverse that that there is no unified way to
+ * compute the slice offsets, so we store them in this table.
+ *
+ * The (x, y) offset to slice \c s at level \c l relative the miptrees
+ * base address is
+ * \code
+ * x = mt->level[l].slice[s].x_offset
+ * y = mt->level[l].slice[s].y_offset
+ */
+ GLuint x_offset;
+ GLuint y_offset;
+ /** \} */
+ } *slice;
};
struct intel_mipmap_tree
@@ -94,6 +120,13 @@ struct intel_mipmap_tree
GLenum target;
gl_format format;
+ /**
+ * The X offset of each image in the miptree must be aligned to this. See
+ * the "Alignment Unit Size" section of the BSpec.
+ */
+ unsigned int align_w;
+ unsigned int align_h; /**< \see align_w */
+
GLuint first_level;
GLuint last_level;
@@ -115,18 +148,37 @@ struct intel_mipmap_tree
struct intel_region *region;
/**
- * This points to an auxillary hiz region if all of the following hold:
- * 1. The texture has been attached to an FBO as a depthbuffer.
- * 2. The texture format is hiz compatible.
- * 3. The intel context supports hiz.
+ * \brief HiZ miptree
+ *
+ * This is non-null only if HiZ is enabled for this miptree.
+ *
+ * \see intel_miptree_alloc_hiz()
+ */
+ struct intel_mipmap_tree *hiz_mt;
+
+ /**
+ * \brief Map of miptree slices to needed resolves.
*
- * When a texture is attached to multiple FBO's, a separate renderbuffer
- * wrapper is created for each attachment. This necessitates storing the
- * hiz region in the texture itself instead of the renderbuffer wrapper.
+ * This is used only when the miptree has a child HiZ miptree.
*
- * \see intel_fbo.c:intel_wrap_texture()
+ * Let \c mt be a depth miptree with HiZ enabled. Then the resolve map is
+ * \c mt->hiz_map. The resolve map of the child HiZ miptree, \c
+ * mt->hiz_mt->hiz_map, is unused.
*/
- struct intel_region *hiz_region;
+ struct intel_resolve_map hiz_map;
+
+ /**
+ * \brief Stencil miptree for depthstencil textures.
+ *
+ * This miptree is used for depthstencil textures that require separate
+ * stencil. The stencil miptree's data is the golden copy of the
+ * parent miptree's stencil bits. When necessary, we scatter/gather the
+ * stencil bits between the parent miptree and the stencil miptree.
+ *
+ * \see intel_miptree_s8z24_scatter()
+ * \see intel_miptree_s8z24_gather()
+ */
+ struct intel_mipmap_tree *stencil_mt;
/* These are also refcounted:
*/
@@ -151,6 +203,32 @@ intel_miptree_create_for_region(struct intel_context *intel,
gl_format format,
struct intel_region *region);
+/**
+ * Create a miptree appropriate as the storage for a non-texture renderbuffer.
+ * The miptree has the following properties:
+ * - The target is GL_TEXTURE_2D.
+ * - There are no levels other than the base level 0.
+ * - Depth is 1.
+ */
+struct intel_mipmap_tree*
+intel_miptree_create_for_renderbuffer(struct intel_context *intel,
+ gl_format format,
+ uint32_t tiling,
+ uint32_t cpp,
+ uint32_t width,
+ uint32_t height);
+
+/** \brief Assert that the level and layer are valid for the miptree. */
+static inline void
+intel_miptree_check_level_layer(struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer)
+{
+ assert(level >= mt->first_level);
+ assert(level <= mt->last_level);
+ assert(layer < mt->level[level].depth);
+}
+
int intel_miptree_pitch_align (struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t tiling,
@@ -177,7 +255,6 @@ intel_miptree_get_dimensions_for_image(struct gl_texture_image *image,
void intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
GLuint level,
- GLuint nr_images,
GLuint x, GLuint y,
GLuint w, GLuint h, GLuint d);
@@ -190,6 +267,96 @@ intel_miptree_copy_teximage(struct intel_context *intel,
struct intel_texture_image *intelImage,
struct intel_mipmap_tree *dst_mt);
+/**
+ * Copy the stencil data from \c mt->stencil_mt->region to \c mt->region for
+ * the given miptree slice.
+ *
+ * \see intel_mipmap_tree::stencil_mt
+ */
+void
+intel_miptree_s8z24_scatter(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t slice);
+
+/**
+ * Copy the stencil data in \c mt->stencil_mt->region to \c mt->region for the
+ * given miptree slice.
+ *
+ * \see intel_mipmap_tree::stencil_mt
+ */
+void
+intel_miptree_s8z24_gather(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer);
+
+/**
+ * \name Miptree HiZ functions
+ * \{
+ *
+ * It is safe to call the "slice_set_need_resolve" and "slice_resolve"
+ * functions on a miptree without HiZ. In that case, each function is a no-op.
+ */
+
+/**
+ * \brief Allocate the miptree's embedded HiZ miptree.
+ * \see intel_mipmap_tree:hiz_mt
+ * \return false if allocation failed
+ */
+
+bool
+intel_miptree_alloc_hiz(struct intel_context *intel,
+ struct intel_mipmap_tree *mt);
+
+void
+intel_miptree_slice_set_needs_hiz_resolve(struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t depth);
+void
+intel_miptree_slice_set_needs_depth_resolve(struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t depth);
+void
+intel_miptree_all_slices_set_need_hiz_resolve(struct intel_mipmap_tree *mt);
+
+void
+intel_miptree_all_slices_set_need_depth_resolve(struct intel_mipmap_tree *mt);
+
+/**
+ * \return false if no resolve was needed
+ */
+bool
+intel_miptree_slice_resolve_hiz(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ unsigned int level,
+ unsigned int depth);
+
+/**
+ * \return false if no resolve was needed
+ */
+bool
+intel_miptree_slice_resolve_depth(struct intel_context *intel,
+ struct intel_mipmap_tree *mt,
+ unsigned int level,
+ unsigned int depth);
+
+/**
+ * \return false if no resolve was needed
+ */
+bool
+intel_miptree_all_slices_resolve_hiz(struct intel_context *intel,
+ struct intel_mipmap_tree *mt);
+
+/**
+ * \return false if no resolve was needed
+ */
+bool
+intel_miptree_all_slices_resolve_depth(struct intel_context *intel,
+ struct intel_mipmap_tree *mt);
+
+/**\}*/
+
/* i915_mipmap_tree.c:
*/
void i915_miptree_layout(struct intel_mipmap_tree *mt);
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_copy.c b/src/mesa/drivers/dri/intel/intel_pixel_copy.c
index 89d5c51ef15..2682e152abc 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_copy.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_copy.c
@@ -34,6 +34,7 @@
#include "intel_context.h"
#include "intel_buffers.h"
+#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_pixel.h"
#include "intel_fbo.h"
@@ -188,8 +189,8 @@ do_blit_copypixels(struct gl_context * ctx,
dsty += draw_irb->draw_y;
if (!intel_region_copy(intel,
- draw_irb->region, 0, dstx, dsty,
- read_irb->region, 0, srcx, srcy,
+ draw_irb->mt->region, 0, dstx, dsty,
+ read_irb->mt->region, 0, srcx, srcy,
width, height, flip,
ctx->Color.ColorLogicOpEnabled ?
ctx->Color.LogicOp : GL_COPY)) {
diff --git a/src/mesa/drivers/dri/intel/intel_resolve_map.c b/src/mesa/drivers/dri/intel/intel_resolve_map.c
new file mode 100644
index 00000000000..e7d82faee11
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_resolve_map.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "intel_resolve_map.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+/**
+ * \brief Set that the miptree slice at (level, layer) needs a resolve.
+ *
+ * \pre If a map element already exists with the given key, then
+ * the new and existing element value must be identical.
+ */
+void
+intel_resolve_map_set(struct intel_resolve_map *head,
+ uint32_t level,
+ uint32_t layer,
+ enum intel_need_resolve need)
+{
+ struct intel_resolve_map **tail = &head->next;
+ struct intel_resolve_map *prev = head;
+
+ while (*tail) {
+ if ((*tail)->level == level && (*tail)->layer == layer) {
+ assert((*tail)->need == need);
+ return;
+ }
+ prev = *tail;
+ tail = &(*tail)->next;
+ }
+
+ *tail = malloc(sizeof(**tail));
+ (*tail)->prev = prev;
+ (*tail)->next = NULL;
+ (*tail)->level = level;
+ (*tail)->layer = layer;
+ (*tail)->need = need;
+}
+
+/**
+ * \brief Get an element from the map.
+ * \return null if element is not contained in map.
+ */
+struct intel_resolve_map*
+intel_resolve_map_get(struct intel_resolve_map *head,
+ uint32_t level,
+ uint32_t layer)
+{
+ struct intel_resolve_map *item = head->next;
+
+ while (item) {
+ if (item->level == level && item->layer == layer)
+ break;
+ else
+ item = item->next;
+ }
+
+ return item;
+}
+
+/**
+ * \brief Remove and free an element from the map.
+ */
+void
+intel_resolve_map_remove(struct intel_resolve_map *elem)
+{
+ if (elem->prev)
+ elem->prev->next = elem->next;
+ if (elem->next)
+ elem->next->prev = elem->prev;
+ free(elem);
+}
+
+/**
+ * \brief Remove and free all elements of the map.
+ */
+void
+intel_resolve_map_clear(struct intel_resolve_map *head)
+{
+ struct intel_resolve_map *next = head->next;
+ struct intel_resolve_map *trash;
+
+ while (next) {
+ trash = next;
+ next = next->next;
+ free(trash);
+ }
+
+ head->next = NULL;
+}
diff --git a/src/mesa/drivers/dri/intel/intel_resolve_map.h b/src/mesa/drivers/dri/intel/intel_resolve_map.h
new file mode 100644
index 00000000000..1082c10e214
--- /dev/null
+++ b/src/mesa/drivers/dri/intel/intel_resolve_map.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+enum intel_need_resolve {
+ INTEL_NEED_HIZ_RESOLVE,
+ INTEL_NEED_DEPTH_RESOLVE,
+};
+
+/**
+ * \brief Map of miptree slices to needed resolves.
+ *
+ * The map is implemented as a linear doubly-linked list.
+ *
+ * In the intel_resolve_map*() functions, the \c head argument is not
+ * inspected for its data. It only serves as an anchor for the list.
+ *
+ * \par Design Discussion
+ *
+ * There are two possible ways to record which miptree slices need
+ * resolves. 1) Maintain a flag for every miptree slice in the texture,
+ * likely in intel_mipmap_level::slice, or 2) maintain a list of only
+ * those slices that need a resolve.
+ *
+ * Immediately before drawing, a full depth resolve performed on each
+ * enabled depth texture. If design 1 were chosen, then at each draw call
+ * it would be necessary to iterate over each miptree slice of each
+ * enabled depth texture in order to query if each slice needed a resolve.
+ * In the worst case, this would require 2^16 iterations: 16 texture
+ * units, 16 miplevels, and 256 depth layers (assuming maximums for OpenGL
+ * 2.1).
+ *
+ * By choosing design 2, the number of iterations is exactly the minimum
+ * necessary.
+ */
+struct intel_resolve_map {
+ uint32_t level;
+ uint32_t layer;
+ enum intel_need_resolve need;
+
+ struct intel_resolve_map *next;
+ struct intel_resolve_map *prev;
+};
+
+void
+intel_resolve_map_set(struct intel_resolve_map *head,
+ uint32_t level,
+ uint32_t layer,
+ enum intel_need_resolve need);
+
+struct intel_resolve_map*
+intel_resolve_map_get(struct intel_resolve_map *head,
+ uint32_t level,
+ uint32_t layer);
+
+void
+intel_resolve_map_remove(struct intel_resolve_map *elem);
+
+void
+intel_resolve_map_clear(struct intel_resolve_map *head);
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index 5a73030660f..46b822cb319 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -86,6 +86,7 @@ const GLuint __driNConfigOptions = 11;
#include "intel_bufmgr.h"
#include "intel_chipset.h"
#include "intel_fbo.h"
+#include "intel_mipmap_tree.h"
#include "intel_screen.h"
#include "intel_tex.h"
#include "intel_regions.h"
@@ -201,7 +202,7 @@ intel_create_image_from_renderbuffer(__DRIcontext *context,
image->format = rb->Format;
image->data_type = rb->DataType;
image->data = loaderPrivate;
- intel_region_reference(&image->region, irb->region);
+ intel_region_reference(&image->region, irb->mt->region);
return image;
}
@@ -679,13 +680,9 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp)
intelScreen->gen = 2;
}
- /*
- * FIXME: The hiz and separate stencil fields need updating once the
- * FIXME: features are completely implemented for a given chipset.
- */
- intelScreen->hw_has_separate_stencil = intelScreen->gen >= 7;
+ intelScreen->hw_has_separate_stencil = intelScreen->gen >= 6;
intelScreen->hw_must_use_separate_stencil = intelScreen->gen >= 7;
- intelScreen->hw_has_hiz = false;
+ intelScreen->hw_has_hiz = intelScreen->gen == 6; /* Not yet for gen7. */
intelScreen->dri2_has_hiz = INTEL_DRI2_HAS_HIZ_UNKNOWN;
intel_override_hiz(intelScreen);
diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c
index 31f2828c395..042bc30da7d 100644
--- a/src/mesa/drivers/dri/intel/intel_span.c
+++ b/src/mesa/drivers/dri/intel/intel_span.c
@@ -39,6 +39,7 @@
#include "intel_buffers.h"
#include "intel_fbo.h"
+#include "intel_mipmap_tree.h"
#include "intel_screen.h"
#include "intel_span.h"
#include "intel_regions.h"
@@ -58,7 +59,7 @@ intel_set_span_functions(struct intel_context *intel,
int minx = 0, miny = 0; \
int maxx = rb->Width; \
int maxy = rb->Height; \
- int pitch = rb->RowStride * irb->region->cpp; \
+ int pitch = rb->RowStride * irb->mt->region->cpp; \
void *buf = rb->Data; \
GLuint p; \
(void) p;
@@ -114,40 +115,6 @@ intel_set_span_functions(struct intel_context *intel,
#define TAG2(x,y) intel_##x##y##_A8
#include "spantmp2.h"
-/* ------------------------------------------------------------------------- */
-/* s8 stencil span and pixel functions */
-/* ------------------------------------------------------------------------- */
-
-/*
- * HAVE_HW_STENCIL_SPANS determines if stencil buffer read/writes are done with
- * memcpy or for loops. Since the stencil buffer is interleaved, memcpy won't
- * work.
- */
-#define HAVE_HW_STENCIL_SPANS 0
-
-#define LOCAL_STENCIL_VARS \
- (void) ctx; \
- int minx = 0; \
- int miny = 0; \
- int maxx = rb->Width; \
- int maxy = rb->Height; \
- \
- /* \
- * Here we ignore rb->Data and rb->RowStride as set by \
- * intelSpanRenderStart. Since intel_offset_S8 decodes the W tile \
- * manually, the region's *real* base address and stride is \
- * required. \
- */ \
- struct intel_renderbuffer *irb = intel_renderbuffer(rb); \
- uint8_t *buf = irb->region->bo->virtual; \
- unsigned stride = irb->region->pitch; \
- bool flip = rb->Name == 0; \
- int y_scale = flip ? -1 : 1; \
- int y_bias = flip ? (rb->Height - 1) : 0; \
-
-#undef Y_FLIP
-#define Y_FLIP(y) (y_scale * (y) + y_bias)
-
/**
* \brief Get pointer offset into stencil buffer.
*
@@ -210,13 +177,6 @@ intel_offset_S8(uint32_t stride, uint32_t x, uint32_t y)
return u;
}
-#define WRITE_STENCIL(x, y, src) buf[intel_offset_S8(stride, x, y)] = src;
-#define READ_STENCIL(dest, x, y) dest = buf[intel_offset_S8(stride, x, y)]
-#define TAG(x) intel_##x##_S8
-#include "stenciltmp.h"
-
-/* ------------------------------------------------------------------------- */
-
void
intel_renderbuffer_map(struct intel_context *intel, struct gl_renderbuffer *rb)
{
@@ -228,10 +188,13 @@ intel_renderbuffer_map(struct intel_context *intel, struct gl_renderbuffer *rb)
if (!irb)
return;
- if (irb->wrapped_depth)
- intel_renderbuffer_map(intel, irb->wrapped_depth);
- if (irb->wrapped_stencil)
- intel_renderbuffer_map(intel, irb->wrapped_stencil);
+ if (rb->Data) {
+ /* Renderbuffer is already mapped. This usually happens when a single
+ * buffer is attached to the framebuffer's depth and stencil attachment
+ * points.
+ */
+ return;
+ }
ctx->Driver.MapRenderbuffer(ctx, rb, 0, 0, rb->Width, rb->Height,
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
@@ -252,10 +215,13 @@ intel_renderbuffer_unmap(struct intel_context *intel,
if (!irb)
return;
- if (irb->wrapped_depth)
- intel_renderbuffer_unmap(intel, irb->wrapped_depth);
- if (irb->wrapped_stencil)
- intel_renderbuffer_unmap(intel, irb->wrapped_stencil);
+ if (!rb->Data) {
+ /* Renderbuffer is already unmapped. This usually happens when a single
+ * buffer is attached to the framebuffer's depth and stencil attachment
+ * points.
+ */
+ return;
+ }
ctx->Driver.UnmapRenderbuffer(ctx, rb);
@@ -288,28 +254,57 @@ intel_framebuffer_unmap(struct intel_context *intel, struct gl_framebuffer *fb)
}
/**
- * Prepare for software rendering. Map current read/draw framebuffers'
- * renderbuffes and all currently bound texture objects.
+ * Resolve all buffers that will be mapped by intelSpanRenderStart().
*
- * Old note: Moved locking out to get reasonable span performance.
+ * Resolve the depth buffer of each enabled texture and of the read and draw
+ * buffers.
+ *
+ * (Note: In the future this will also perform MSAA resolves.)
*/
-void
-intelSpanRenderStart(struct gl_context * ctx)
+static void
+intel_span_resolve_buffers(struct intel_context *intel)
{
- struct intel_context *intel = intel_context(ctx);
- GLuint i;
-
- intel_flush(&intel->ctx);
- intel_prepare_render(intel);
+ struct gl_context *ctx = &intel->ctx;
+ struct intel_renderbuffer *draw_irb;
+ struct intel_renderbuffer *read_irb;
+ struct intel_texture_object *tex_obj;
+
+ /* Resolve depth buffer of each enabled texture. */
+ for (int i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (!ctx->Texture.Unit[i]._ReallyEnabled)
+ continue;
+ tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current);
+ intel_finalize_mipmap_tree(intel, i);
+ if (!tex_obj || !tex_obj->mt)
+ continue;
+ intel_miptree_all_slices_resolve_depth(intel, tex_obj->mt);
+ }
- for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
- if (ctx->Texture.Unit[i]._ReallyEnabled) {
- struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
+ /* Resolve each attached depth buffer. */
+ draw_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH);
+ read_irb = intel_get_renderbuffer(ctx->ReadBuffer, BUFFER_DEPTH);
+ if (draw_irb)
+ intel_renderbuffer_resolve_depth(intel, draw_irb);
+ if (read_irb != draw_irb && read_irb)
+ intel_renderbuffer_resolve_depth(intel, read_irb);
+}
- intel_finalize_mipmap_tree(intel, i);
- intel_tex_map_images(intel, intel_texture_object(texObj),
- GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
- }
+/**
+ * Map the regions needed by intelSpanRenderStart().
+ */
+static void
+intel_span_map_buffers(struct intel_context *intel)
+{
+ struct gl_context *ctx = &intel->ctx;
+ struct intel_texture_object *tex_obj;
+
+ for (int i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
+ if (!ctx->Texture.Unit[i]._ReallyEnabled)
+ continue;
+ tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current);
+ intel_finalize_mipmap_tree(intel, i);
+ intel_tex_map_images(intel, tex_obj,
+ GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
}
intel_framebuffer_map(intel, ctx->DrawBuffer);
@@ -319,6 +314,24 @@ intelSpanRenderStart(struct gl_context * ctx)
}
/**
+ * Prepare for software rendering. Map current read/draw framebuffers'
+ * renderbuffes and all currently bound texture objects.
+ *
+ * Old note: Moved locking out to get reasonable span performance.
+ */
+void
+intelSpanRenderStart(struct gl_context * ctx)
+{
+ struct intel_context *intel = intel_context(ctx);
+
+ intel_flush(ctx);
+ intel_prepare_render(intel);
+ intel_span_resolve_buffers(intel);
+ intel_flush(ctx);
+ intel_span_map_buffers(intel);
+}
+
+/**
* Called when done software rendering. Unmap the buffers we mapped in
* the above function.
*/
@@ -405,7 +418,7 @@ static span_init_func intel_span_init_funcs[MESA_FORMAT_COUNT] =
[MESA_FORMAT_Z16] = _mesa_set_renderbuffer_accessors,
[MESA_FORMAT_X8_Z24] = _mesa_set_renderbuffer_accessors,
[MESA_FORMAT_S8_Z24] = _mesa_set_renderbuffer_accessors,
- [MESA_FORMAT_S8] = intel_InitStencilPointers_S8,
+ [MESA_FORMAT_S8] = _mesa_set_renderbuffer_accessors,
[MESA_FORMAT_R8] = _mesa_set_renderbuffer_accessors,
[MESA_FORMAT_RG88] = _mesa_set_renderbuffer_accessors,
[MESA_FORMAT_R16] = _mesa_set_renderbuffer_accessors,
diff --git a/src/mesa/drivers/dri/intel/intel_tex.c b/src/mesa/drivers/dri/intel/intel_tex.c
index 05b0748bc3c..9884a57d0fe 100644
--- a/src/mesa/drivers/dri/intel/intel_tex.c
+++ b/src/mesa/drivers/dri/intel/intel_tex.c
@@ -69,11 +69,6 @@ intel_alloc_texture_image_buffer(struct gl_context *ctx,
*/
ctx->Driver.FreeTextureImageBuffer(ctx, image);
- if (intel->must_use_separate_stencil
- && image->TexFormat == MESA_FORMAT_S8_Z24) {
- intel_tex_image_s8z24_create_renderbuffers(intel, intel_image);
- }
-
/* Allocate the swrast_texture_image::ImageOffsets array now */
switch (texobj->Target) {
case GL_TEXTURE_3D:
@@ -107,11 +102,6 @@ intel_alloc_texture_image_buffer(struct gl_context *ctx,
*/
intel_miptree_reference(&intel_texobj->mt, intel_image->mt);
- if (intel->must_use_separate_stencil
- && image->TexFormat == MESA_FORMAT_S8_Z24) {
- intel_tex_image_s8z24_create_renderbuffers(intel, intel_image);
- }
-
DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n",
__FUNCTION__, texobj, image->Level,
width, height, depth, intel_image->mt);
@@ -139,9 +129,6 @@ intel_free_texture_image_buffer(struct gl_context * ctx,
free(intelImage->base.ImageOffsets);
intelImage->base.ImageOffsets = NULL;
}
-
- _mesa_reference_renderbuffer(&intelImage->depth_rb, NULL);
- _mesa_reference_renderbuffer(&intelImage->stencil_rb, NULL);
}
/**
@@ -174,13 +161,19 @@ intel_map_texture_image(struct gl_context *ctx,
assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY ||
h == 1);
- if (intel_image->stencil_rb) {
- /*
- * The texture has packed depth/stencil format, but uses separate
- * stencil. The texture's embedded stencil buffer contains the real
- * stencil data, so copy that into the miptree.
+ if (mt->stencil_mt) {
+ /* The miptree has depthstencil format, but uses separate stencil. The
+ * embedded stencil miptree contains the real stencil data, so gather
+ * that into the depthstencil miptree.
+ *
+ * FIXME: Avoid the gather if the texture is mapped as write-only.
*/
- intel_tex_image_s8z24_gather(intel, intel_image);
+ intel_miptree_s8z24_gather(intel, mt, tex_image->Level, slice);
+ }
+
+ intel_miptree_slice_resolve_depth(intel, mt, tex_image->Level, slice);
+ if (mode & GL_MAP_WRITE_BIT) {
+ intel_miptree_slice_set_needs_hiz_resolve(mt, tex_image->Level, slice);
}
/* For compressed formats, the stride is the number of bytes per
@@ -211,16 +204,19 @@ intel_unmap_texture_image(struct gl_context *ctx,
{
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;
intel_region_unmap(intel, intel_image->mt->region);
- if (intel_image->stencil_rb) {
- /*
- * The texture has packed depth/stencil format, but uses separate
- * stencil. The texture's embedded stencil buffer contains the real
- * stencil data, so copy that into the miptree.
+ if (mt->stencil_mt) {
+ /* The miptree has depthstencil format, but uses separate stencil. The
+ * embedded stencil miptree must contain the real stencil data after
+ * unmapping, so copy it from the depthstencil miptree into the stencil
+ * miptree.
+ *
+ * FIXME: Avoid the scatter if the texture was mapped as read-only.
*/
- intel_tex_image_s8z24_scatter(intel, intel_image);
+ intel_miptree_s8z24_scatter(intel, mt, tex_image->Level, slice);
}
}
diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c
index 2df4ef6a7f6..543326a0580 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_copy.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c
@@ -71,6 +71,7 @@ intel_copy_texsubimage(struct intel_context *intel,
{
struct gl_context *ctx = &intel->ctx;
struct intel_renderbuffer *irb;
+ struct intel_region *region;
const GLenum internalFormat = intelImage->base.Base.InternalFormat;
bool copy_supported = false;
bool copy_supported_with_alpha_override = false;
@@ -78,11 +79,14 @@ intel_copy_texsubimage(struct intel_context *intel,
intel_prepare_render(intel);
irb = get_teximage_readbuffer(intel, internalFormat);
- if (!intelImage->mt || !irb || !irb->region) {
+ if (!intelImage->mt || !irb || !irb->mt) {
if (unlikely(INTEL_DEBUG & DEBUG_FALLBACKS))
fprintf(stderr, "%s fail %p %p (0x%08x)\n",
__FUNCTION__, intelImage->mt, irb, internalFormat);
return false;
+ } else {
+ region = irb->mt->region;
+ assert(region);
}
copy_supported = intelImage->base.Base.TexFormat == irb->Base.Format;
@@ -127,19 +131,19 @@ intel_copy_texsubimage(struct intel_context *intel,
if (ctx->ReadBuffer->Name == 0) {
/* Flip vertical orientation for system framebuffers */
y = ctx->ReadBuffer->Height - (y + height);
- src_pitch = -irb->region->pitch;
+ src_pitch = -region->pitch;
} else {
/* reading from a FBO, y is already oriented the way we like */
- src_pitch = irb->region->pitch;
+ src_pitch = region->pitch;
}
/* blit from src buffer to texture */
if (!intelEmitCopyBlit(intel,
intelImage->mt->cpp,
src_pitch,
- irb->region->bo,
+ region->bo,
0,
- irb->region->tiling,
+ region->tiling,
intelImage->mt->region->pitch,
intelImage->mt->region->bo,
0,
diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c
index 3fc2128536c..dd0c6d34c63 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_image.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_image.c
@@ -197,134 +197,6 @@ try_pbo_upload(struct gl_context *ctx,
return true;
}
-/**
- * \param scatter Scatter if true. Gather if false.
- *
- * \see intel_tex_image_x8z24_scatter
- * \see intel_tex_image_x8z24_gather
- */
-static void
-intel_tex_image_s8z24_scattergather(struct intel_context *intel,
- struct intel_texture_image *intel_image,
- bool scatter)
-{
- struct gl_context *ctx = &intel->ctx;
- struct gl_renderbuffer *depth_rb = intel_image->depth_rb;
- struct gl_renderbuffer *stencil_rb = intel_image->stencil_rb;
- int w, h, d;
-
- intel_miptree_get_dimensions_for_image(&intel_image->base.Base, &w, &h, &d);
- assert(d == 1); /* FINISHME */
-
- uint32_t depth_row[w];
- uint8_t stencil_row[w];
-
- intel_renderbuffer_map(intel, depth_rb);
- intel_renderbuffer_map(intel, stencil_rb);
-
- if (scatter) {
- for (int y = 0; y < h; ++y) {
- depth_rb->GetRow(ctx, depth_rb, w, 0, y, depth_row);
- for (int x = 0; x < w; ++x) {
- stencil_row[x] = depth_row[x] >> 24;
- }
- stencil_rb->PutRow(ctx, stencil_rb, w, 0, y, stencil_row, NULL);
- }
- } else { /* gather */
- for (int y = 0; y < h; ++y) {
- depth_rb->GetRow(ctx, depth_rb, w, 0, y, depth_row);
- stencil_rb->GetRow(ctx, stencil_rb, w, 0, y, stencil_row);
- for (int x = 0; x < w; ++x) {
- uint32_t s8_x24 = stencil_row[x] << 24;
- uint32_t x8_z24 = depth_row[x] & 0x00ffffff;
- depth_row[x] = s8_x24 | x8_z24;
- }
- depth_rb->PutRow(ctx, depth_rb, w, 0, y, depth_row, NULL);
- }
- }
-
- intel_renderbuffer_unmap(intel, depth_rb);
- intel_renderbuffer_unmap(intel, stencil_rb);
-}
-
-/**
- * Copy the x8 bits from intel_image->depth_rb to intel_image->stencil_rb.
- */
-void
-intel_tex_image_s8z24_scatter(struct intel_context *intel,
- struct intel_texture_image *intel_image)
-{
- intel_tex_image_s8z24_scattergather(intel, intel_image, true);
-}
-
-/**
- * Copy the data in intel_image->stencil_rb to the x8 bits in
- * intel_image->depth_rb.
- */
-void
-intel_tex_image_s8z24_gather(struct intel_context *intel,
- struct intel_texture_image *intel_image)
-{
- intel_tex_image_s8z24_scattergather(intel, intel_image, false);
-}
-
-bool
-intel_tex_image_s8z24_create_renderbuffers(struct intel_context *intel,
- struct intel_texture_image *image)
-{
- struct gl_context *ctx = &intel->ctx;
- bool ok = true;
- int width, height, depth;
- struct gl_renderbuffer *drb;
- struct gl_renderbuffer *srb;
- struct intel_renderbuffer *idrb;
- struct intel_renderbuffer *isrb;
-
- intel_miptree_get_dimensions_for_image(&image->base.Base,
- &width, &height, &depth);
- assert(depth == 1); /* FINISHME */
-
- assert(intel->has_separate_stencil);
- assert(image->base.Base.TexFormat == MESA_FORMAT_S8_Z24);
- assert(image->mt != NULL);
-
- drb = intel_create_wrapped_renderbuffer(ctx, width, height,
- MESA_FORMAT_X8_Z24);
- srb = intel_create_wrapped_renderbuffer(ctx, width, height,
- MESA_FORMAT_S8);
-
- if (!drb || !srb) {
- if (drb) {
- drb->Delete(drb);
- }
- if (srb) {
- srb->Delete(srb);
- }
- return false;
- }
-
- idrb = intel_renderbuffer(drb);
- isrb = intel_renderbuffer(srb);
-
- intel_region_reference(&idrb->region, image->mt->region);
- ok = intel_alloc_renderbuffer_storage(ctx, srb, GL_STENCIL_INDEX8,
- width, height);
-
- if (!ok) {
- drb->Delete(drb);
- srb->Delete(srb);
- return false;
- }
-
- intel_renderbuffer_set_draw_offset(idrb, image, 0);
- intel_renderbuffer_set_draw_offset(isrb, image, 0);
-
- _mesa_reference_renderbuffer(&image->depth_rb, drb);
- _mesa_reference_renderbuffer(&image->stencil_rb, srb);
-
- return true;
-}
-
static void
intelTexImage(struct gl_context * ctx,
GLint dims,
@@ -471,7 +343,7 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
/* If the region isn't set, then intel_update_renderbuffers was unable
* to get the buffers for the drawable.
*/
- if (rb->region == NULL)
+ if (!rb || !rb->mt)
return;
if (texture_format == __DRI_TEXTURE_FORMAT_RGB) {
@@ -485,7 +357,7 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
_mesa_lock_texture(&intel->ctx, texObj);
texImage = _mesa_get_tex_image(ctx, texObj, target, level);
- intel_set_texture_image_region(ctx, texImage, rb->region, target,
+ intel_set_texture_image_region(ctx, texImage, rb->mt->region, target,
internalFormat, texFormat);
_mesa_unlock_texture(&intel->ctx, texObj);
}
diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.c b/src/mesa/drivers/dri/intel/intel_tex_layout.c
index 64f4a70c52c..65645bc46a4 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_layout.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_layout.c
@@ -33,26 +33,113 @@
#include "intel_mipmap_tree.h"
#include "intel_tex_layout.h"
#include "intel_context.h"
+
+#include "main/image.h"
#include "main/macros.h"
+static unsigned int
+intel_horizontal_texture_alignment_unit(struct intel_context *intel,
+ gl_format format)
+{
+ /**
+ * From the "Alignment Unit Size" section of various specs, namely:
+ * - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4
+ * - i965 and G45 PRMs: Volume 1, Section 6.17.3.4.
+ * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4
+ * - BSpec (for Ivybridge and slight variations in separate stencil)
+ *
+ * +----------------------------------------------------------------------+
+ * | | alignment unit width ("i") |
+ * | Surface Property |-----------------------------|
+ * | | 915 | 965 | ILK | SNB | IVB |
+ * +----------------------------------------------------------------------+
+ * | YUV 4:2:2 format | 8 | 4 | 4 | 4 | 4 |
+ * | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 |
+ * | FXT1 compressed format | 8 | 8 | 8 | 8 | 8 |
+ * | Depth Buffer (16-bit) | 4 | 4 | 4 | 4 | 8 |
+ * | Depth Buffer (other) | 4 | 4 | 4 | 4 | 4 |
+ * | Separate Stencil Buffer | N/A | N/A | 8 | 8 | 8 |
+ * | All Others | 4 | 4 | 4 | 4 | 4 |
+ * +----------------------------------------------------------------------+
+ *
+ * On IVB+, non-special cases can be overridden by setting the SURFACE_STATE
+ * "Surface Horizontal Alignment" field to HALIGN_4 or HALIGN_8.
+ */
+ if (_mesa_is_format_compressed(format)) {
+ /* The hardware alignment requirements for compressed textures
+ * happen to match the block boundaries.
+ */
+ unsigned int i, j;
+ _mesa_get_format_block_size(format, &i, &j);
+ return i;
+ }
+
+ if (format == MESA_FORMAT_S8)
+ return 8;
+
+ if (intel->gen >= 7 && format == MESA_FORMAT_Z16)
+ return 8;
+
+ return 4;
+}
+
+static unsigned int
+intel_vertical_texture_alignment_unit(struct intel_context *intel,
+ gl_format format)
+{
+ /**
+ * From the "Alignment Unit Size" section of various specs, namely:
+ * - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4
+ * - i965 and G45 PRMs: Volume 1, Section 6.17.3.4.
+ * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4
+ * - BSpec (for Ivybridge and slight variations in separate stencil)
+ *
+ * +----------------------------------------------------------------------+
+ * | | alignment unit height ("j") |
+ * | Surface Property |-----------------------------|
+ * | | 915 | 965 | ILK | SNB | IVB |
+ * +----------------------------------------------------------------------+
+ * | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 |
+ * | FXT1 compressed format | 4 | 4 | 4 | 4 | 4 |
+ * | Depth Buffer | 2 | 2 | 2 | 4 | 4 |
+ * | Separate Stencil Buffer | N/A | N/A | N/A | 4 | 8 |
+ * | Multisampled (4x or 8x) render target | N/A | N/A | N/A | 4 | 4 |
+ * | All Others | 2 | 2 | 2 | 2 | 2 |
+ * +----------------------------------------------------------------------+
+ *
+ * On SNB+, non-special cases can be overridden by setting the SURFACE_STATE
+ * "Surface Vertical Alignment" field to VALIGN_2 or VALIGN_4.
+ *
+ * We currently don't support multisampling.
+ */
+ if (_mesa_is_format_compressed(format))
+ return 4;
+
+ if (format == MESA_FORMAT_S8)
+ return intel->gen >= 7 ? 8 : 4;
+
+ GLenum base_format = _mesa_get_format_base_format(format);
+
+ if (intel->gen >= 6 &&
+ (base_format == GL_DEPTH_COMPONENT ||
+ base_format == GL_DEPTH_STENCIL)) {
+ return 4;
+ }
+
+ return 2;
+}
+
void
-intel_get_texture_alignment_unit(gl_format format,
+intel_get_texture_alignment_unit(struct intel_context *intel,
+ gl_format format,
unsigned int *w, unsigned int *h)
{
- if (_mesa_is_format_compressed(format)) {
- /* The hardware alignment requirements for compressed textures
- * happen to match the block boundaries.
- */
- _mesa_get_format_block_size(format, w, h);
- } else {
- *w = 4;
- *h = 2;
- }
+ *w = intel_horizontal_texture_alignment_unit(intel, format);
+ *h = intel_vertical_texture_alignment_unit(intel, format);
}
-void i945_miptree_layout_2d(struct intel_mipmap_tree *mt, int nr_images)
+void i945_miptree_layout_2d(struct intel_mipmap_tree *mt)
{
- GLuint align_h, align_w;
GLuint level;
GLuint x = 0;
GLuint y = 0;
@@ -61,10 +148,9 @@ void i945_miptree_layout_2d(struct intel_mipmap_tree *mt, int nr_images)
GLuint depth = mt->depth0; /* number of array layers. */
mt->total_width = mt->width0;
- intel_get_texture_alignment_unit(mt->format, &align_w, &align_h);
if (mt->compressed) {
- mt->total_width = ALIGN(mt->width0, align_w);
+ mt->total_width = ALIGN(mt->width0, mt->align_w);
}
/* May need to adjust width to accomodate the placement of
@@ -76,10 +162,10 @@ void i945_miptree_layout_2d(struct intel_mipmap_tree *mt, int nr_images)
GLuint mip1_width;
if (mt->compressed) {
- mip1_width = ALIGN(minify(mt->width0), align_w)
- + ALIGN(minify(minify(mt->width0)), align_w);
+ mip1_width = ALIGN(minify(mt->width0), mt->align_w)
+ + ALIGN(minify(minify(mt->width0)), mt->align_w);
} else {
- mip1_width = ALIGN(minify(mt->width0), align_w)
+ mip1_width = ALIGN(minify(mt->width0), mt->align_w)
+ minify(minify(mt->width0));
}
@@ -93,12 +179,12 @@ void i945_miptree_layout_2d(struct intel_mipmap_tree *mt, int nr_images)
for ( level = mt->first_level ; level <= mt->last_level ; level++ ) {
GLuint img_height;
- intel_miptree_set_level_info(mt, level, nr_images, x, y, width,
+ intel_miptree_set_level_info(mt, level, x, y, width,
height, depth);
- img_height = ALIGN(height, align_h);
+ img_height = ALIGN(height, mt->align_h);
if (mt->compressed)
- img_height /= align_h;
+ img_height /= mt->align_h;
/* Because the images are packed better, the final offset
* might not be the maximal one:
@@ -108,7 +194,7 @@ void i945_miptree_layout_2d(struct intel_mipmap_tree *mt, int nr_images)
/* Layout_below: step right after second mipmap.
*/
if (level == mt->first_level + 1) {
- x += ALIGN(width, align_w);
+ x += ALIGN(width, mt->align_w);
}
else {
y += img_height;
diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.h b/src/mesa/drivers/dri/intel/intel_tex_layout.h
index 257c07ce476..12ed16d8216 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_layout.h
+++ b/src/mesa/drivers/dri/intel/intel_tex_layout.h
@@ -38,7 +38,9 @@ static INLINE GLuint minify( GLuint d )
return MAX2(1, d>>1);
}
-extern void i945_miptree_layout_2d(struct intel_mipmap_tree *mt,
- int nr_images);
-void intel_get_texture_alignment_unit(gl_format format,
- unsigned int *w, unsigned int *h);
+extern void i945_miptree_layout_2d(struct intel_mipmap_tree *mt);
+
+void
+intel_get_texture_alignment_unit(struct intel_context *intel,
+ gl_format format,
+ unsigned int *w, unsigned int *h);
diff --git a/src/mesa/drivers/dri/intel/intel_tex_obj.h b/src/mesa/drivers/dri/intel/intel_tex_obj.h
index 06904e4869b..8b278ba9875 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_obj.h
+++ b/src/mesa/drivers/dri/intel/intel_tex_obj.h
@@ -66,36 +66,6 @@ struct intel_texture_image
*/
struct intel_mipmap_tree *mt;
bool used_as_render_target;
-
- /**
- * \name Renderbuffers for faking packed depth/stencil
- *
- * These renderbuffers are non-null only if the intel_context is using
- * separate stencil and this texture has a packed depth/stencil format. When
- * glFramebufferTexture is called on this image, the resultant renderbuffer
- * wrapper reuses these renderbuffers as its own.
- *
- * \see intel_wrap_texture
- * \see intel_tex_image_s8z24_create_renderbuffers
- * \see intel_tex_image_s8z24_scatter
- * \see intel_tex_image_s8z24_gather
- *
- * \{
- */
-
- /**
- * The depth buffer has format X8_Z24. The x8 bits are undefined unless
- * intel_tex_image_s8z24_gather has been immediately called. The depth
- * buffer reuses the image miptree's region and hiz_region as its own.
- */
- struct gl_renderbuffer *depth_rb;
-
- /**
- * The stencil buffer has format S8 and keeps its data in its own region.
- */
- struct gl_renderbuffer *stencil_rb;
-
- /** \} */
};
static INLINE struct intel_texture_object *
diff --git a/src/mesa/drivers/dri/intel/intel_tex_validate.c b/src/mesa/drivers/dri/intel/intel_tex_validate.c
index f4c1a688657..748fbdca2b9 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_validate.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_validate.c
@@ -154,7 +154,7 @@ intel_tex_map_image_for_swrast(struct intel_context *intel,
intel_image->base.Data = intel_region_map(intel, mt->region, mode);
} else {
- assert(mt->level[level].depth == 1);
+ assert(intel_image->base.Base.Depth == 1);
intel_miptree_get_image_offset(mt, level, face, 0, &x, &y);
DBG("%s: (%d,%d) -> (%d, %d)/%d\n",