intel: Replace intel_texture_image::stencil_irb with intel_mipmap_tree::stencil_mt [v3]
For depthstencil textures using separate stencil, we embedded a stencil buffer in intel_texture_image. The intention was that the embedded stencil buffer would be the golden copy of the texture's stencil bits. When necessary, we scattered/gathered the stencil bits between the texture miptree and the embedded stencil buffer. This approach had a serious deficiency for mipmapped or multi-layer textures. Any given moment the embedded stencil buffer was consistent with exactly one miptree slice, the most recent one to be scattered. This permitted tests of type A to pass, but broke tests of type B. Test A: 1. Create a depthstencil texture. 2. Upload data into (level=x1,layer=y1). 3. Read and test stencil data at (level=x1, layer=y1). 4. Upload data into (level=x2,layer=y2). 5. Read and test stencil data at (level=x2, layer=y2). Test B: 1. Create a depthstencil texture. 2. Upload data into (level=x1,layer=y1). 3. Upload data into (level=x2,layer=y2). 4. Read and test stencil data at (level=x1, layer=y1). 5. Read and test stencil data at (level=x2, layer=y2). v2: Only allocate stencil miptree if intel->must_use_separate_stencil, because we don't make the conversion from must_use_separate_stencil to has_separate_stencil until commit intel: Use separate stencil whenever possible v3: Don't call ChooseNewTexture in intel_renderbuffer_wrap_miptree() in order to determine the renderbuffer format. Instead, pass the format as a param to that function. CC: Eric Anholt <eric@anholt.net> Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
This commit is contained in:
@@ -36,6 +36,8 @@
|
|||||||
#include "main/renderbuffer.h"
|
#include "main/renderbuffer.h"
|
||||||
#include "main/context.h"
|
#include "main/context.h"
|
||||||
#include "main/teximage.h"
|
#include "main/teximage.h"
|
||||||
|
#include "main/image.h"
|
||||||
|
|
||||||
#include "swrast/swrast.h"
|
#include "swrast/swrast.h"
|
||||||
#include "drivers/common/meta.h"
|
#include "drivers/common/meta.h"
|
||||||
|
|
||||||
@@ -946,12 +948,26 @@ intel_framebuffer_renderbuffer(struct gl_context * ctx,
|
|||||||
intel_draw_buffer(ctx);
|
intel_draw_buffer(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: The 'att' parameter is a kludge that will soon be removed. Its
|
* \par Special case for separate stencil
|
||||||
* presence allows us to refactor the wrapping of depthstencil textures that
|
*
|
||||||
* use separate stencil in two easily manageable steps, rather than in one
|
* When wrapping a depthstencil texture that uses separate stencil, this
|
||||||
* large, hairy step. First, refactor the common wrapping code used by all
|
* function is recursively called twice: once to create \c
|
||||||
* texture formats. Second, refactor the separate stencil code paths.
|
* 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
|
static bool
|
||||||
intel_renderbuffer_update_wrapper(struct intel_context *intel,
|
intel_renderbuffer_update_wrapper(struct intel_context *intel,
|
||||||
@@ -960,17 +976,10 @@ intel_renderbuffer_update_wrapper(struct intel_context *intel,
|
|||||||
uint32_t level,
|
uint32_t level,
|
||||||
uint32_t layer,
|
uint32_t layer,
|
||||||
gl_format format,
|
gl_format format,
|
||||||
GLenum internal_format,
|
GLenum internal_format)
|
||||||
struct gl_renderbuffer_attachment *att)
|
|
||||||
{
|
{
|
||||||
struct gl_renderbuffer *rb = &irb->Base;
|
struct gl_renderbuffer *rb = &irb->Base;
|
||||||
|
|
||||||
/* The image variables are a kludge. See the note above for the att
|
|
||||||
* parameter.
|
|
||||||
*/
|
|
||||||
struct gl_texture_image *texImage = _mesa_get_attachment_teximage(att);
|
|
||||||
struct intel_texture_image *intel_image = intel_texture_image(texImage);
|
|
||||||
|
|
||||||
rb->Format = format;
|
rb->Format = format;
|
||||||
if (!intel_span_supports_format(rb->Format)) {
|
if (!intel_span_supports_format(rb->Format)) {
|
||||||
DBG("Render to texture BAD FORMAT %s\n",
|
DBG("Render to texture BAD FORMAT %s\n",
|
||||||
@@ -993,35 +1002,50 @@ intel_renderbuffer_update_wrapper(struct intel_context *intel,
|
|||||||
irb->mt_level = level;
|
irb->mt_level = level;
|
||||||
irb->mt_layer = layer;
|
irb->mt_layer = layer;
|
||||||
|
|
||||||
if (intel_image->stencil_rb) {
|
if (mt->stencil_mt && _mesa_is_depthstencil_format(rb->InternalFormat)) {
|
||||||
/* The tex image has packed depth/stencil format, but is using separate
|
assert((irb->wrapped_depth == NULL) == (irb->wrapped_stencil == NULL));
|
||||||
* stencil. It shares its embedded depth and stencil renderbuffers with
|
|
||||||
* the renderbuffer wrapper.
|
|
||||||
*
|
|
||||||
* FIXME: glFramebufferTexture*() is broken for depthstencil textures
|
|
||||||
* FIXME: with separate stencil. To fix this, we must create a separate
|
|
||||||
* FIXME: pair of depth/stencil renderbuffers for each attached slice
|
|
||||||
* FIXME: of the miptree.
|
|
||||||
*/
|
|
||||||
struct intel_renderbuffer *depth_irb;
|
struct intel_renderbuffer *depth_irb;
|
||||||
struct intel_renderbuffer *stencil_irb;
|
struct intel_renderbuffer *stencil_irb;
|
||||||
|
|
||||||
_mesa_reference_renderbuffer(&irb->wrapped_depth,
|
if (!irb->wrapped_depth) {
|
||||||
intel_image->depth_rb);
|
depth_irb = intel_renderbuffer_wrap_miptree(intel,
|
||||||
_mesa_reference_renderbuffer(&irb->wrapped_stencil,
|
mt, level, layer,
|
||||||
intel_image->stencil_rb);
|
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);
|
||||||
|
|
||||||
depth_irb = intel_renderbuffer(intel_image->depth_rb);
|
if (!irb->wrapped_depth || !irb->wrapped_stencil)
|
||||||
depth_irb->mt_level = irb->mt_level;
|
return false;
|
||||||
depth_irb->mt_layer = irb->mt_layer;
|
} else {
|
||||||
intel_renderbuffer_set_draw_offset(depth_irb);
|
bool ok = true;
|
||||||
|
|
||||||
stencil_irb = intel_renderbuffer(intel_image->stencil_rb);
|
depth_irb = intel_renderbuffer(irb->wrapped_depth);
|
||||||
stencil_irb->mt_level = irb->mt_level;
|
stencil_irb = intel_renderbuffer(irb->wrapped_stencil);
|
||||||
stencil_irb->mt_layer = irb->mt_layer;
|
|
||||||
intel_renderbuffer_set_draw_offset(stencil_irb);
|
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;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
intel_miptree_reference(&irb->mt, intel_image->mt);
|
intel_miptree_reference(&irb->mt, mt);
|
||||||
intel_renderbuffer_set_draw_offset(irb);
|
intel_renderbuffer_set_draw_offset(irb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1035,12 +1059,6 @@ intel_renderbuffer_update_wrapper(struct intel_context *intel,
|
|||||||
* ``struct intel_renderbuffer`` then calls
|
* ``struct intel_renderbuffer`` then calls
|
||||||
* intel_renderbuffer_update_wrapper() to do the real work.
|
* intel_renderbuffer_update_wrapper() to do the real work.
|
||||||
*
|
*
|
||||||
* NOTE: The 'att' parameter is a kludge that will soon be removed. Its
|
|
||||||
* presence allows us to refactor the wrapping of depthstencil textures that
|
|
||||||
* use separate stencil in two easily manageable steps, rather than in one
|
|
||||||
* large, hairy step. First, refactor the common wrapping code used by all
|
|
||||||
* texture formats. Second, refactor the separate stencil code paths.
|
|
||||||
*
|
|
||||||
* \see intel_renderbuffer_update_wrapper()
|
* \see intel_renderbuffer_update_wrapper()
|
||||||
*/
|
*/
|
||||||
static struct intel_renderbuffer*
|
static struct intel_renderbuffer*
|
||||||
@@ -1049,8 +1067,7 @@ intel_renderbuffer_wrap_miptree(struct intel_context *intel,
|
|||||||
uint32_t level,
|
uint32_t level,
|
||||||
uint32_t layer,
|
uint32_t layer,
|
||||||
gl_format format,
|
gl_format format,
|
||||||
GLenum internal_format,
|
GLenum internal_format)
|
||||||
struct gl_renderbuffer_attachment *att)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const GLuint name = ~0; /* not significant, but distinct for debugging */
|
const GLuint name = ~0; /* not significant, but distinct for debugging */
|
||||||
@@ -1070,8 +1087,7 @@ intel_renderbuffer_wrap_miptree(struct intel_context *intel,
|
|||||||
|
|
||||||
if (!intel_renderbuffer_update_wrapper(intel, irb,
|
if (!intel_renderbuffer_update_wrapper(intel, irb,
|
||||||
mt, level, layer,
|
mt, level, layer,
|
||||||
format, internal_format,
|
format, internal_format)) {
|
||||||
att)) {
|
|
||||||
free(irb);
|
free(irb);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1189,8 +1205,7 @@ intel_render_texture(struct gl_context * ctx,
|
|||||||
att->TextureLevel,
|
att->TextureLevel,
|
||||||
layer,
|
layer,
|
||||||
image->TexFormat,
|
image->TexFormat,
|
||||||
image->InternalFormat,
|
image->InternalFormat);
|
||||||
att);
|
|
||||||
|
|
||||||
if (irb) {
|
if (irb) {
|
||||||
/* bind the wrapper to the attachment point */
|
/* bind the wrapper to the attachment point */
|
||||||
@@ -1206,8 +1221,7 @@ intel_render_texture(struct gl_context * ctx,
|
|||||||
if (!intel_renderbuffer_update_wrapper(intel, irb,
|
if (!intel_renderbuffer_update_wrapper(intel, irb,
|
||||||
mt, att->TextureLevel, layer,
|
mt, att->TextureLevel, layer,
|
||||||
image->TexFormat,
|
image->TexFormat,
|
||||||
image->InternalFormat,
|
image->InternalFormat)) {
|
||||||
att)) {
|
|
||||||
_mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
|
_mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
|
||||||
_swrast_render_texture(ctx, fb, att);
|
_swrast_render_texture(ctx, fb, att);
|
||||||
return;
|
return;
|
||||||
|
@@ -25,14 +25,18 @@
|
|||||||
*
|
*
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "intel_batchbuffer.h"
|
||||||
#include "intel_context.h"
|
#include "intel_context.h"
|
||||||
#include "intel_mipmap_tree.h"
|
#include "intel_mipmap_tree.h"
|
||||||
#include "intel_regions.h"
|
#include "intel_regions.h"
|
||||||
|
#include "intel_span.h"
|
||||||
#include "intel_tex_layout.h"
|
#include "intel_tex_layout.h"
|
||||||
#include "intel_tex.h"
|
#include "intel_tex.h"
|
||||||
#include "intel_blit.h"
|
#include "intel_blit.h"
|
||||||
|
|
||||||
#include "main/enums.h"
|
#include "main/enums.h"
|
||||||
#include "main/formats.h"
|
#include "main/formats.h"
|
||||||
|
#include "main/image.h"
|
||||||
#include "main/teximage.h"
|
#include "main/teximage.h"
|
||||||
|
|
||||||
#define FILE_DEBUG_FLAG DEBUG_MIPTREE
|
#define FILE_DEBUG_FLAG DEBUG_MIPTREE
|
||||||
@@ -54,7 +58,6 @@ target_to_target(GLenum target)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct intel_mipmap_tree *
|
static struct intel_mipmap_tree *
|
||||||
intel_miptree_create_internal(struct intel_context *intel,
|
intel_miptree_create_internal(struct intel_context *intel,
|
||||||
GLenum target,
|
GLenum target,
|
||||||
@@ -93,6 +96,16 @@ intel_miptree_create_internal(struct intel_context *intel,
|
|||||||
mt->depth0 = depth0;
|
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
|
#ifdef I915
|
||||||
(void) intel;
|
(void) intel;
|
||||||
if (intel->is_945)
|
if (intel->is_945)
|
||||||
@@ -103,6 +116,23 @@ intel_miptree_create_internal(struct intel_context *intel,
|
|||||||
brw_miptree_layout(intel, mt);
|
brw_miptree_layout(intel, mt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (intel->must_use_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;
|
return mt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,6 +157,8 @@ intel_miptree_create(struct intel_context *intel,
|
|||||||
(base_format == GL_DEPTH_COMPONENT ||
|
(base_format == GL_DEPTH_COMPONENT ||
|
||||||
base_format == GL_DEPTH_STENCIL_EXT))
|
base_format == GL_DEPTH_STENCIL_EXT))
|
||||||
tiling = I915_TILING_Y;
|
tiling = I915_TILING_Y;
|
||||||
|
else if (format == MESA_FORMAT_S8)
|
||||||
|
tiling = I915_TILING_NONE;
|
||||||
else if (width0 >= 64)
|
else if (width0 >= 64)
|
||||||
tiling = I915_TILING_X;
|
tiling = I915_TILING_X;
|
||||||
}
|
}
|
||||||
@@ -230,6 +262,7 @@ intel_miptree_release(struct intel_mipmap_tree **mt)
|
|||||||
|
|
||||||
intel_region_release(&((*mt)->region));
|
intel_region_release(&((*mt)->region));
|
||||||
intel_region_release(&((*mt)->hiz_region));
|
intel_region_release(&((*mt)->hiz_region));
|
||||||
|
intel_miptree_release(&(*mt)->stencil_mt);
|
||||||
|
|
||||||
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
|
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
|
||||||
free((*mt)->level[i].slice);
|
free((*mt)->level[i].slice);
|
||||||
@@ -423,6 +456,12 @@ intel_miptree_copy_slice(struct intel_context *intel,
|
|||||||
intel_region_unmap(intel, dst_mt->region);
|
intel_region_unmap(intel, dst_mt->region);
|
||||||
intel_region_unmap(intel, src_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -446,3 +485,96 @@ intel_miptree_copy_teximage(struct intel_context *intel,
|
|||||||
intel_miptree_reference(&intelImage->mt, dst_mt);
|
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);
|
||||||
|
}
|
||||||
|
@@ -152,6 +152,19 @@ struct intel_mipmap_tree
|
|||||||
*/
|
*/
|
||||||
struct intel_region *hiz_region;
|
struct intel_region *hiz_region;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \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:
|
/* These are also refcounted:
|
||||||
*/
|
*/
|
||||||
GLuint refcount;
|
GLuint refcount;
|
||||||
@@ -239,6 +252,30 @@ intel_miptree_copy_teximage(struct intel_context *intel,
|
|||||||
struct intel_texture_image *intelImage,
|
struct intel_texture_image *intelImage,
|
||||||
struct intel_mipmap_tree *dst_mt);
|
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);
|
||||||
|
|
||||||
/* i915_mipmap_tree.c:
|
/* i915_mipmap_tree.c:
|
||||||
*/
|
*/
|
||||||
void i915_miptree_layout(struct intel_mipmap_tree *mt);
|
void i915_miptree_layout(struct intel_mipmap_tree *mt);
|
||||||
|
@@ -69,11 +69,6 @@ intel_alloc_texture_image_buffer(struct gl_context *ctx,
|
|||||||
*/
|
*/
|
||||||
ctx->Driver.FreeTextureImageBuffer(ctx, image);
|
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 */
|
/* Allocate the swrast_texture_image::ImageOffsets array now */
|
||||||
switch (texobj->Target) {
|
switch (texobj->Target) {
|
||||||
case GL_TEXTURE_3D:
|
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);
|
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",
|
DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n",
|
||||||
__FUNCTION__, texobj, image->Level,
|
__FUNCTION__, texobj, image->Level,
|
||||||
width, height, depth, intel_image->mt);
|
width, height, depth, intel_image->mt);
|
||||||
@@ -139,9 +129,6 @@ intel_free_texture_image_buffer(struct gl_context * ctx,
|
|||||||
free(intelImage->base.ImageOffsets);
|
free(intelImage->base.ImageOffsets);
|
||||||
intelImage->base.ImageOffsets = NULL;
|
intelImage->base.ImageOffsets = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_mesa_reference_renderbuffer(&intelImage->depth_rb, NULL);
|
|
||||||
_mesa_reference_renderbuffer(&intelImage->stencil_rb, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -174,13 +161,14 @@ intel_map_texture_image(struct gl_context *ctx,
|
|||||||
assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY ||
|
assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY ||
|
||||||
h == 1);
|
h == 1);
|
||||||
|
|
||||||
if (intel_image->stencil_rb) {
|
if (mt->stencil_mt) {
|
||||||
/*
|
/* The miptree has depthstencil format, but uses separate stencil. The
|
||||||
* The texture has packed depth/stencil format, but uses separate
|
* embedded stencil miptree contains the real stencil data, so gather
|
||||||
* stencil. The texture's embedded stencil buffer contains the real
|
* that into the depthstencil miptree.
|
||||||
* stencil data, so copy that into the 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For compressed formats, the stride is the number of bytes per
|
/* For compressed formats, the stride is the number of bytes per
|
||||||
@@ -211,16 +199,19 @@ intel_unmap_texture_image(struct gl_context *ctx,
|
|||||||
{
|
{
|
||||||
struct intel_context *intel = intel_context(ctx);
|
struct intel_context *intel = intel_context(ctx);
|
||||||
struct intel_texture_image *intel_image = intel_texture_image(tex_image);
|
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);
|
intel_region_unmap(intel, intel_image->mt->region);
|
||||||
|
|
||||||
if (intel_image->stencil_rb) {
|
if (mt->stencil_mt) {
|
||||||
/*
|
/* The miptree has depthstencil format, but uses separate stencil. The
|
||||||
* The texture has packed depth/stencil format, but uses separate
|
* embedded stencil miptree must contain the real stencil data after
|
||||||
* stencil. The texture's embedded stencil buffer contains the real
|
* unmapping, so copy it from the depthstencil miptree into the stencil
|
||||||
* stencil data, so copy that into the miptree.
|
* 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -197,134 +197,6 @@ try_pbo_upload(struct gl_context *ctx,
|
|||||||
return true;
|
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_miptree_reference(&idrb->mt, image->mt);
|
|
||||||
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);
|
|
||||||
intel_renderbuffer_set_draw_offset(isrb);
|
|
||||||
|
|
||||||
_mesa_reference_renderbuffer(&image->depth_rb, drb);
|
|
||||||
_mesa_reference_renderbuffer(&image->stencil_rb, srb);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
intelTexImage(struct gl_context * ctx,
|
intelTexImage(struct gl_context * ctx,
|
||||||
GLint dims,
|
GLint dims,
|
||||||
|
@@ -66,36 +66,6 @@ struct intel_texture_image
|
|||||||
*/
|
*/
|
||||||
struct intel_mipmap_tree *mt;
|
struct intel_mipmap_tree *mt;
|
||||||
bool used_as_render_target;
|
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 *
|
static INLINE struct intel_texture_object *
|
||||||
|
Reference in New Issue
Block a user