Merge branch 'hiz' of ssh://people.freedesktop.org/~chadversary/mesa

This commit is contained in:
Chad Versace
2011-11-22 10:52:29 -08:00
42 changed files with 2137 additions and 799 deletions
-9
View File
@@ -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;
}
-9
View File
@@ -852,13 +852,6 @@ i915_is_hiz_depth_format(struct intel_context *intel,
return false;
}
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)
{
@@ -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;
}
@@ -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 \
+66
View File
@@ -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
+37
View File
@@ -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;
};
+5 -4
View File
@@ -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
+104 -1
View File
@@ -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;
}
+16 -6
View File
@@ -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();
@@ -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}
};
+16 -27
View File
@@ -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__,
+4 -33
View File
@@ -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) {
@@ -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 */
+19 -1
View File
@@ -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,
@@ -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,
+307 -7
View File
@@ -25,16 +25,316 @@
#include <assert.h>
void
gen6_hiz_resolve_depthbuffer(struct intel_context *intel,
struct intel_region *depth_region)
#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 units 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)
{
assert("!stub");
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_hizbuffer(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_resolve_depth_slice(struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t layer)
{
gen6_resolve_slice(intel, mt, level, layer, BRW_HIZ_OP_DEPTH_RESOLVE);
}
+11 -5
View File
@@ -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);
+15 -3
View File
@@ -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,
+19 -1
View File
@@ -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)
},
+6 -5
View File
@@ -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();
@@ -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;
+1
View File
@@ -0,0 +1 @@
../intel/intel_resolve_map.c
+13 -8
View File
@@ -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);
@@ -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
+5 -4
View File
@@ -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;
}
+64 -21
View File
@@ -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;
if (buffer->attachment == __DRI_BUFFER_HIZ) {
intel_region_reference(&rb->hiz_region, region);
} else {
intel_region_reference(&rb->region, region);
}
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) {
rb->mt->hiz_mt = mt;
} else {
rb->mt = mt;
}
}
/**
@@ -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);
}
}
+9 -4
View File
@@ -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);
/** \} */
/**
+309 -193
View File
@@ -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->mt->region, GL_MAP_READ_BIT);
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];
}
/* 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. */
intel_miptree_check_level_layer(mt, level, layer);
irb->mt_level = level;
irb->mt_layer = layer;
bool ok;
struct intel_renderbuffer *depth_irb =
intel_renderbuffer(intel_image->depth_rb);
if (mt->stencil_mt && _mesa_is_depthstencil_format(rb->InternalFormat)) {
assert((irb->wrapped_depth == NULL) == (irb->wrapped_stencil == NULL));
/* Update the hiz region if necessary. */
ok = intel_update_tex_wrapper_regions(intel, depth_irb, intel_image);
if (!ok) {
return false;
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);
}
}
intel_miptree_reference(&irb->mt, mt);
intel_renderbuffer_set_draw_offset(irb);
/**
* 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);
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.
+55 -37
View File
@@ -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 */
+414 -92
View File
@@ -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;
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);
}
for (slice = 0; slice < depth; slice++) {
unsigned int dst_x, dst_y, src_x, src_y;
intel_miptree_get_image_offset(dst_mt, level, face, slice,
&dst_x, &dst_y);
/* 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);
}
for (int slice = 0; slice < depth; slice++) {
intel_miptree_copy_slice(intel, dst_mt, src_mt, level, face, slice);
}
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);
/* 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];
}
}
}
drm_intel_gem_bo_unmap_gtt(s8_mt->region->bo);
drm_intel_gem_bo_unmap_gtt(s8z24_mt->region->bo);
}
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;
}
}
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);
}
+190 -23
View File
@@ -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. */
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 Number of 2D slices in this miplevel.
*
* 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.
* 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 *x_offset, *y_offset;
/** @} */
GLuint depth;
/**
* \brief List of 2D images in this mipmap level.
*
* 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.
*/
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
*
* 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 non-null only if HiZ is enabled for this miptree.
*
* \see intel_fbo.c:intel_wrap_texture()
* \see intel_miptree_alloc_hiz()
*/
struct intel_region *hiz_region;
struct intel_mipmap_tree *hiz_mt;
/**
* \brief Map of miptree slices to needed resolves.
*
* This is used only when the miptree has a child HiZ miptree.
*
* 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_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);
@@ -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)) {
@@ -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;
}
@@ -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);
+4 -7
View File
@@ -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);
+81 -68
View File
@@ -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);
@@ -287,6 +253,66 @@ intel_framebuffer_unmap(struct intel_context *intel, struct gl_framebuffer *fb)
}
}
/**
* Resolve all buffers that will be mapped by intelSpanRenderStart().
*
* 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.)
*/
static void
intel_span_resolve_buffers(struct intel_context *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);
}
/* 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);
}
/**
* 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);
if (ctx->ReadBuffer != ctx->DrawBuffer) {
intel_framebuffer_map(intel, ctx->ReadBuffer);
}
}
/**
* Prepare for software rendering. Map current read/draw framebuffers'
* renderbuffes and all currently bound texture objects.
@@ -297,25 +323,12 @@ void
intelSpanRenderStart(struct gl_context * ctx)
{
struct intel_context *intel = intel_context(ctx);
GLuint i;
intel_flush(&intel->ctx);
intel_flush(ctx);
intel_prepare_render(intel);
for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
if (ctx->Texture.Unit[i]._ReallyEnabled) {
struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current;
intel_finalize_mipmap_tree(intel, i);
intel_tex_map_images(intel, intel_texture_object(texObj),
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
}
}
intel_framebuffer_map(intel, ctx->DrawBuffer);
if (ctx->ReadBuffer != ctx->DrawBuffer) {
intel_framebuffer_map(intel, ctx->ReadBuffer);
}
intel_span_resolve_buffers(intel);
intel_flush(ctx);
intel_span_map_buffers(intel);
}
/**
@@ -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,
+21 -25
View File
@@ -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);
}
}
+9 -5
View File
@@ -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,
+2 -130
View File
@@ -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);
}
+109 -23
View File
@@ -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"
void
intel_get_texture_alignment_unit(gl_format format,
unsigned int *w, unsigned int *h)
static unsigned int
intel_horizontal_texture_alignment_unit(struct intel_context *intel,
gl_format format)
{
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;
}
/**
* 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;
}
void i945_miptree_layout_2d(struct intel_mipmap_tree *mt, int nr_images)
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(struct intel_context *intel,
gl_format format,
unsigned int *w, unsigned int *h)
{
*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)
{
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;
@@ -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);
@@ -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 *
@@ -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",