mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-30 05:00:32 +01:00
intel: Convert to using private depth/stencil buffers (v2)
This means that GLX buffer sharing of these no longer works. On the
other hand, just *look* at this code reduction.
v2:
- [chad] Fix intelCreateBuffer for gen < 6. When the branch for
!screen->hw_has_separate_stencil was taken,
intel_create_private_renderbuffer was incorrectly not used.
- [chad] Remove all code in intel_process_dri2_buffer for processing
depth, stencil, and hiz buffers. That code is now dead.
CC: Eric Anholt <eric@anholt.net>
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
parent
433ff3e16e
commit
bce58e155d
3 changed files with 39 additions and 652 deletions
|
|
@ -239,37 +239,17 @@ intel_bits_per_pixel(const struct intel_renderbuffer *rb)
|
|||
}
|
||||
|
||||
static void
|
||||
intel_query_dri2_buffers_no_separate_stencil(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer **buffers,
|
||||
int *count);
|
||||
intel_query_dri2_buffers(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer **buffers,
|
||||
int *count);
|
||||
|
||||
static void
|
||||
intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer *buffer,
|
||||
struct intel_renderbuffer *rb,
|
||||
const char *buffer_name);
|
||||
|
||||
static void
|
||||
intel_query_dri2_buffers_with_separate_stencil(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer **buffers,
|
||||
unsigned **attachments,
|
||||
int *count);
|
||||
|
||||
static void
|
||||
intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer *buffer,
|
||||
struct intel_renderbuffer *rb,
|
||||
const char *buffer_name);
|
||||
static void
|
||||
intel_verify_dri2_has_hiz(struct intel_context *intel,
|
||||
intel_process_dri2_buffer(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer **buffers,
|
||||
unsigned **attachments,
|
||||
int *count);
|
||||
__DRIbuffer *buffer,
|
||||
struct intel_renderbuffer *rb,
|
||||
const char *buffer_name);
|
||||
|
||||
void
|
||||
intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
|
||||
|
|
@ -278,19 +258,9 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
|
|||
struct intel_renderbuffer *rb;
|
||||
struct intel_context *intel = context->driverPrivate;
|
||||
__DRIbuffer *buffers = NULL;
|
||||
unsigned *attachments = NULL;
|
||||
int i, count;
|
||||
const char *region_name;
|
||||
|
||||
bool try_separate_stencil =
|
||||
intel->has_separate_stencil &&
|
||||
intel->intelScreen->dri2_has_hiz != INTEL_DRI2_HAS_HIZ_FALSE &&
|
||||
intel->intelScreen->driScrnPriv->dri2.loader != NULL &&
|
||||
intel->intelScreen->driScrnPriv->dri2.loader->base.version > 2 &&
|
||||
intel->intelScreen->driScrnPriv->dri2.loader->getBuffersWithFormat != NULL;
|
||||
|
||||
assert(!intel->must_use_separate_stencil || try_separate_stencil);
|
||||
|
||||
/* If we're rendering to the fake front buffer, make sure all the
|
||||
* pending drawing has landed on the real front buffer. Otherwise
|
||||
* when we eventually get to DRI2GetBuffersWithFormat the stale
|
||||
|
|
@ -310,13 +280,7 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
|
|||
if (unlikely(INTEL_DEBUG & DEBUG_DRI))
|
||||
fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
|
||||
|
||||
if (try_separate_stencil) {
|
||||
intel_query_dri2_buffers_with_separate_stencil(intel, drawable, &buffers,
|
||||
&attachments, &count);
|
||||
} else {
|
||||
intel_query_dri2_buffers_no_separate_stencil(intel, drawable, &buffers,
|
||||
&count);
|
||||
}
|
||||
intel_query_dri2_buffers(intel, drawable, &buffers, &count);
|
||||
|
||||
if (buffers == NULL)
|
||||
return;
|
||||
|
|
@ -339,26 +303,9 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
|
|||
break;
|
||||
|
||||
case __DRI_BUFFER_DEPTH:
|
||||
rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
|
||||
region_name = "dri2 depth buffer";
|
||||
break;
|
||||
|
||||
case __DRI_BUFFER_HIZ:
|
||||
/* The hiz region resides in the depth renderbuffer. */
|
||||
rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
|
||||
region_name = "dri2 hiz buffer";
|
||||
break;
|
||||
|
||||
case __DRI_BUFFER_DEPTH_STENCIL:
|
||||
rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
|
||||
region_name = "dri2 depth / stencil buffer";
|
||||
break;
|
||||
|
||||
case __DRI_BUFFER_STENCIL:
|
||||
rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
|
||||
region_name = "dri2 stencil buffer";
|
||||
break;
|
||||
|
||||
case __DRI_BUFFER_ACCUM:
|
||||
default:
|
||||
fprintf(stderr,
|
||||
|
|
@ -367,26 +314,9 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
|
|||
return;
|
||||
}
|
||||
|
||||
if (try_separate_stencil) {
|
||||
intel_process_dri2_buffer_with_separate_stencil(intel, drawable,
|
||||
&buffers[i], rb,
|
||||
region_name);
|
||||
} else {
|
||||
intel_process_dri2_buffer_no_separate_stencil(intel, drawable,
|
||||
&buffers[i], rb,
|
||||
region_name);
|
||||
}
|
||||
intel_process_dri2_buffer(intel, drawable, &buffers[i], rb, region_name);
|
||||
}
|
||||
|
||||
if (try_separate_stencil
|
||||
&& intel->intelScreen->dri2_has_hiz == INTEL_DRI2_HAS_HIZ_UNKNOWN) {
|
||||
intel_verify_dri2_has_hiz(intel, drawable, &buffers, &attachments,
|
||||
&count);
|
||||
}
|
||||
|
||||
if (attachments)
|
||||
free(attachments);
|
||||
|
||||
driUpdateFramebufferSize(&intel->ctx, drawable);
|
||||
}
|
||||
|
||||
|
|
@ -887,8 +817,7 @@ intelMakeCurrent(__DRIcontext * driContextPriv,
|
|||
* attached to the drawable's framebuffer. Then request the buffers with
|
||||
* DRI2GetBuffers() or DRI2GetBuffersWithFormat().
|
||||
*
|
||||
* This is called from intel_update_renderbuffers(). It is used only if either
|
||||
* the hardware or the X driver lacks separate stencil support.
|
||||
* This is called from intel_update_renderbuffers().
|
||||
*
|
||||
* \param drawable Drawable whose buffers are queried.
|
||||
* \param buffers [out] List of buffers returned by DRI2 query.
|
||||
|
|
@ -899,13 +828,11 @@ intelMakeCurrent(__DRIcontext * driContextPriv,
|
|||
* \see DRI2GetBuffersWithFormat()
|
||||
*/
|
||||
static void
|
||||
intel_query_dri2_buffers_no_separate_stencil(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer **buffers,
|
||||
int *buffer_count)
|
||||
intel_query_dri2_buffers(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer **buffers,
|
||||
int *buffer_count)
|
||||
{
|
||||
assert(!intel->must_use_separate_stencil);
|
||||
|
||||
__DRIscreen *screen = intel->intelScreen->driScrnPriv;
|
||||
struct gl_framebuffer *fb = drawable->driverPrivate;
|
||||
|
||||
|
|
@ -919,13 +846,9 @@ intel_query_dri2_buffers_no_separate_stencil(struct intel_context *intel,
|
|||
|
||||
struct intel_renderbuffer *front_rb;
|
||||
struct intel_renderbuffer *back_rb;
|
||||
struct intel_renderbuffer *depth_rb;
|
||||
struct intel_renderbuffer *stencil_rb;
|
||||
|
||||
front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
|
||||
back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
|
||||
depth_rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
|
||||
stencil_rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
|
||||
|
||||
if ((intel->is_front_buffer_rendering ||
|
||||
intel->is_front_buffer_reading ||
|
||||
|
|
@ -939,17 +862,6 @@ intel_query_dri2_buffers_no_separate_stencil(struct intel_context *intel,
|
|||
attachments[i++] = intel_bits_per_pixel(back_rb);
|
||||
}
|
||||
|
||||
if (depth_rb && stencil_rb) {
|
||||
attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
|
||||
attachments[i++] = intel_bits_per_pixel(depth_rb);
|
||||
} else if (depth_rb) {
|
||||
attachments[i++] = __DRI_BUFFER_DEPTH;
|
||||
attachments[i++] = intel_bits_per_pixel(depth_rb);
|
||||
} else if (stencil_rb) {
|
||||
attachments[i++] = __DRI_BUFFER_STENCIL;
|
||||
attachments[i++] = intel_bits_per_pixel(stencil_rb);
|
||||
}
|
||||
|
||||
assert(i <= 2 * max_attachments);
|
||||
|
||||
*buffers = screen->dri2.loader->getBuffersWithFormat(drawable,
|
||||
|
|
@ -970,10 +882,6 @@ intel_query_dri2_buffers_no_separate_stencil(struct intel_context *intel,
|
|||
attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
|
||||
if (intel_get_renderbuffer(fb, BUFFER_BACK_LEFT))
|
||||
attachments[i++] = __DRI_BUFFER_BACK_LEFT;
|
||||
if (intel_get_renderbuffer(fb, BUFFER_DEPTH))
|
||||
attachments[i++] = __DRI_BUFFER_DEPTH;
|
||||
if (intel_get_renderbuffer(fb, BUFFER_STENCIL))
|
||||
attachments[i++] = __DRI_BUFFER_STENCIL;
|
||||
|
||||
assert(i <= max_attachments);
|
||||
|
||||
|
|
@ -994,8 +902,7 @@ intel_query_dri2_buffers_no_separate_stencil(struct intel_context *intel,
|
|||
/**
|
||||
* \brief Assign a DRI buffer's DRM region to a renderbuffer.
|
||||
*
|
||||
* This is called from intel_update_renderbuffers(). It is used only if
|
||||
* either the hardware or the X driver lacks separate stencil support.
|
||||
* This is called from intel_update_renderbuffers().
|
||||
*
|
||||
* \par Note:
|
||||
* DRI buffers whose attachment point is DRI2BufferStencil or
|
||||
|
|
@ -1008,16 +915,13 @@ intel_query_dri2_buffers_no_separate_stencil(struct intel_context *intel,
|
|||
* \see intel_region_alloc_for_handle()
|
||||
*/
|
||||
static void
|
||||
intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer *buffer,
|
||||
struct intel_renderbuffer *rb,
|
||||
const char *buffer_name)
|
||||
intel_process_dri2_buffer(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer *buffer,
|
||||
struct intel_renderbuffer *rb,
|
||||
const char *buffer_name)
|
||||
{
|
||||
assert(!intel->must_use_separate_stencil);
|
||||
|
||||
struct gl_framebuffer *fb = drawable->driverPrivate;
|
||||
struct intel_renderbuffer *depth_rb = NULL;
|
||||
struct intel_region *region = NULL;
|
||||
|
||||
if (!rb)
|
||||
return;
|
||||
|
|
@ -1034,472 +938,20 @@ intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel,
|
|||
buffer->cpp, buffer->pitch);
|
||||
}
|
||||
|
||||
bool identify_depth_and_stencil = false;
|
||||
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->mt;
|
||||
}
|
||||
|
||||
if (identify_depth_and_stencil) {
|
||||
if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
|
||||
fprintf(stderr, "(reusing depth buffer as stencil)\n");
|
||||
}
|
||||
intel_miptree_reference(&rb->mt, depth_rb->mt);
|
||||
} else {
|
||||
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,
|
||||
intel_rb_format(rb),
|
||||
region);
|
||||
intel_region_release(®ion);
|
||||
if (!rb->mt)
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer->attachment == __DRI_BUFFER_DEPTH_STENCIL) {
|
||||
struct intel_renderbuffer *stencil_rb =
|
||||
intel_get_renderbuffer(fb, BUFFER_STENCIL);
|
||||
|
||||
if (!stencil_rb)
|
||||
return;
|
||||
|
||||
/* The rb passed in is the BUFFER_DEPTH attachment, and we need
|
||||
* to associate this region to BUFFER_STENCIL as well.
|
||||
*/
|
||||
intel_miptree_reference(&stencil_rb->mt, rb->mt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Query DRI2 to obtain a DRIdrawable's buffers.
|
||||
*
|
||||
* To determine which DRI buffers to request, examine the renderbuffers
|
||||
* attached to the drawable's framebuffer. Then request the buffers with
|
||||
* DRI2GetBuffersWithFormat().
|
||||
*
|
||||
* This is called from intel_update_renderbuffers(). It is used when 1) the
|
||||
* hardware supports separate stencil and 2) the X driver's separate stencil
|
||||
* support has been verified to work or is still unknown.
|
||||
*
|
||||
* \param drawable Drawable whose buffers are queried.
|
||||
* \param buffers [out] List of buffers returned by DRI2 query.
|
||||
* \param buffer_count [out] Number of buffers returned.
|
||||
* \param attachments [out] List of pairs (attachment_point, bits_per_pixel)
|
||||
* that were submitted in the DRI2 query. Number of pairs
|
||||
* is same as buffer_count.
|
||||
*
|
||||
* \see intel_update_renderbuffers()
|
||||
* \see DRI2GetBuffersWithFormat()
|
||||
* \see enum intel_dri2_has_hiz
|
||||
*/
|
||||
static void
|
||||
intel_query_dri2_buffers_with_separate_stencil(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer **buffers,
|
||||
unsigned **attachments,
|
||||
int *count)
|
||||
{
|
||||
assert(intel->has_separate_stencil);
|
||||
|
||||
__DRIscreen *screen = intel->intelScreen->driScrnPriv;
|
||||
struct gl_framebuffer *fb = drawable->driverPrivate;
|
||||
|
||||
const int max_attachments = 5;
|
||||
int i = 0;
|
||||
|
||||
*attachments = calloc(2 * max_attachments, sizeof(unsigned));
|
||||
if (!*attachments) {
|
||||
*buffers = NULL;
|
||||
*count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
struct intel_renderbuffer *front_rb;
|
||||
struct intel_renderbuffer *back_rb;
|
||||
struct intel_renderbuffer *depth_rb;
|
||||
struct intel_renderbuffer *stencil_rb;
|
||||
|
||||
front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
|
||||
back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
|
||||
depth_rb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
|
||||
stencil_rb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
|
||||
|
||||
if ((intel->is_front_buffer_rendering ||
|
||||
intel->is_front_buffer_reading ||
|
||||
!back_rb) && front_rb) {
|
||||
(*attachments)[i++] = __DRI_BUFFER_FRONT_LEFT;
|
||||
(*attachments)[i++] = intel_bits_per_pixel(front_rb);
|
||||
}
|
||||
|
||||
if (back_rb) {
|
||||
(*attachments)[i++] = __DRI_BUFFER_BACK_LEFT;
|
||||
(*attachments)[i++] = intel_bits_per_pixel(back_rb);
|
||||
}
|
||||
|
||||
/*
|
||||
* We request a separate stencil buffer, and perhaps a hiz buffer too, even
|
||||
* if we do not yet know if the X driver supports it. See the comments for
|
||||
* 'enum intel_dri2_has_hiz'.
|
||||
*/
|
||||
|
||||
if (depth_rb) {
|
||||
(*attachments)[i++] = __DRI_BUFFER_DEPTH;
|
||||
(*attachments)[i++] = intel_bits_per_pixel(depth_rb);
|
||||
|
||||
if (intel->vtbl.is_hiz_depth_format(intel, intel_rb_format(depth_rb))) {
|
||||
/* Depth and hiz buffer have same bpp. */
|
||||
(*attachments)[i++] = __DRI_BUFFER_HIZ;
|
||||
(*attachments)[i++] = intel_bits_per_pixel(depth_rb);
|
||||
}
|
||||
}
|
||||
|
||||
if (stencil_rb) {
|
||||
assert(intel_rb_format(stencil_rb) == MESA_FORMAT_S8);
|
||||
(*attachments)[i++] = __DRI_BUFFER_STENCIL;
|
||||
(*attachments)[i++] = intel_bits_per_pixel(stencil_rb);
|
||||
}
|
||||
|
||||
assert(i <= 2 * max_attachments);
|
||||
|
||||
*buffers = screen->dri2.loader->getBuffersWithFormat(drawable,
|
||||
&drawable->w,
|
||||
&drawable->h,
|
||||
*attachments, i / 2,
|
||||
count,
|
||||
drawable->loaderPrivate);
|
||||
|
||||
if (!*buffers) {
|
||||
free(*attachments);
|
||||
*attachments = NULL;
|
||||
*count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Assign a DRI buffer's DRM region to a renderbuffer.
|
||||
*
|
||||
* This is called from intel_update_renderbuffers(). It is used when 1) the
|
||||
* hardware supports separate stencil and 2) the X driver's separate stencil
|
||||
* support has been verified to work or is still unknown.
|
||||
*
|
||||
* \par Note:
|
||||
* DRI buffers whose attachment point is DRI2BufferStencil or DRI2BufferHiz
|
||||
* are handled as special cases.
|
||||
*
|
||||
* \param buffer_name is a human readable name, such as "dri2 front buffer",
|
||||
* that is passed to intel_region_alloc_for_handle().
|
||||
*
|
||||
* \see intel_update_renderbuffers()
|
||||
* \see intel_region_alloc_for_handle()
|
||||
* \see enum intel_dri2_has_hiz
|
||||
*/
|
||||
static void
|
||||
intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer *buffer,
|
||||
struct intel_renderbuffer *rb,
|
||||
const char *buffer_name)
|
||||
{
|
||||
assert(intel->has_separate_stencil);
|
||||
assert(buffer->attachment != __DRI_BUFFER_DEPTH_STENCIL);
|
||||
|
||||
if (!rb)
|
||||
return;
|
||||
|
||||
/* Check if we failed to allocate the depth miptree earlier. */
|
||||
if (buffer->attachment == __DRI_BUFFER_HIZ && rb->mt == NULL)
|
||||
return;
|
||||
|
||||
/* If the renderbuffer's and DRIbuffer's regions match, then continue. */
|
||||
if ((buffer->attachment != __DRI_BUFFER_HIZ &&
|
||||
rb->mt &&
|
||||
rb->mt->region &&
|
||||
rb->mt->region->name == buffer->name) ||
|
||||
(buffer->attachment == __DRI_BUFFER_HIZ &&
|
||||
rb->mt &&
|
||||
rb->mt->hiz_mt &&
|
||||
rb->mt->hiz_mt->region->name == buffer->name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
|
||||
fprintf(stderr,
|
||||
"attaching buffer %d, at %d, cpp %d, pitch %d\n",
|
||||
buffer->name, buffer->attachment,
|
||||
buffer->cpp, buffer->pitch);
|
||||
}
|
||||
|
||||
int buffer_width;
|
||||
int buffer_height;
|
||||
int buffer_cpp = buffer->cpp;
|
||||
int buffer_pitch = buffer->pitch;
|
||||
if (buffer->attachment == __DRI_BUFFER_STENCIL) {
|
||||
/* Stencil buffers use W tiling, a tiling format that the DRM functions
|
||||
* don't properly account for. Therefore, when we allocate a stencil
|
||||
* buffer that is private to Mesa (see intel_miptree_create), we round
|
||||
* the height and width up to the next multiple of the tile size (64x64)
|
||||
* and then ask DRM to allocate an untiled buffer. Consequently, the
|
||||
* height and the width stored in the stencil buffer's region structure
|
||||
* are always multiples of 64, even if the stencil buffer itself is
|
||||
* smaller.
|
||||
*
|
||||
* To avoid inconsistencies between how we represent private buffers and
|
||||
* buffers shared with the window system, round up the height and width
|
||||
* for window system buffers too.
|
||||
*/
|
||||
buffer_width = ALIGN(drawable->w, 64);
|
||||
buffer_height = ALIGN(drawable->h, 64);
|
||||
|
||||
/* Versions 2.17.0 and earlier of xf86-video-intel (a.k.a. the DDX) lie
|
||||
* and send cpp and pitch values that are two times too large for
|
||||
* stencil buffers. Hopefully this will be fixed in a future version
|
||||
* of xf86-video-intel, but for now detect the bug by checking if cpp
|
||||
* is 2, and fixing cpp and pitch if it is.
|
||||
*/
|
||||
if (buffer_cpp == 2) {
|
||||
buffer_cpp = 1;
|
||||
buffer_pitch /= 2;
|
||||
}
|
||||
} else {
|
||||
buffer_width = drawable->w;
|
||||
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) {
|
||||
assert(rb->mt);
|
||||
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,
|
||||
buffer_width,
|
||||
buffer_height,
|
||||
buffer_pitch / buffer_cpp,
|
||||
buffer->name,
|
||||
buffer_name);
|
||||
intel_miptree_release(&rb->mt);
|
||||
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;
|
||||
|
||||
struct intel_mipmap_tree *mt =
|
||||
intel_miptree_create_for_region(intel,
|
||||
GL_TEXTURE_2D,
|
||||
intel_rb_format(rb),
|
||||
region);
|
||||
rb->mt = intel_miptree_create_for_region(intel,
|
||||
GL_TEXTURE_2D,
|
||||
intel_rb_format(rb),
|
||||
region);
|
||||
intel_region_release(®ion);
|
||||
|
||||
/* Associate buffer with new storage. */
|
||||
if (buffer->attachment == __DRI_BUFFER_HIZ) {
|
||||
assert(rb->mt);
|
||||
rb->mt->hiz_mt = mt;
|
||||
} else {
|
||||
rb->mt = mt;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Verify that the X driver supports hiz and separate stencil.
|
||||
*
|
||||
* This implements the cleanup stage of the handshake described in the
|
||||
* comments for 'enum intel_dri2_has_hiz'.
|
||||
*
|
||||
* This should be called from intel_update_renderbuffers() after 1) the
|
||||
* DRIdrawable has been queried for its buffers via DRI2GetBuffersWithFormat()
|
||||
* and 2) the DRM region of each returned DRIbuffer has been assigned to the
|
||||
* appropriate intel_renderbuffer. Furthermore, this should be called *only*
|
||||
* when 1) intel_update_renderbuffers() tried to used the X driver's separate
|
||||
* stencil functionality and 2) it has not yet been determined if the X driver
|
||||
* supports separate stencil.
|
||||
*
|
||||
* If we determine that the X driver does have support, then we set
|
||||
* intel_screen.dri2_has_hiz to true and return.
|
||||
*
|
||||
* If we determine that the X driver lacks support, and we requested
|
||||
* a DRI2BufferDepth and DRI2BufferStencil, then we must remedy the mistake by
|
||||
* taking the following actions:
|
||||
* 1. Discard the framebuffer's stencil and depth renderbuffers.
|
||||
* 2. Create a combined depth/stencil renderbuffer and attach
|
||||
* it to the framebuffer's depth and stencil attachment points.
|
||||
* 3. Query the drawable for a new set of buffers, which consists of the
|
||||
* originally requested set plus DRI2BufferDepthStencil.
|
||||
* 4. Assign the DRI2BufferDepthStencil's DRM region to the new
|
||||
* depth/stencil renderbuffer.
|
||||
*
|
||||
* \pre intel->intelScreen->dri2_has_hiz == INTEL_DRI2_HAS_HIZ_UNKNOWN
|
||||
*
|
||||
* \param drawable Drawable whose buffers were queried.
|
||||
*
|
||||
* \param buffers [in/out] As input, the buffer list returned by the
|
||||
* original DRI2 query. As output, the current buffer
|
||||
* list, which may have been altered by a new DRI2 query.
|
||||
*
|
||||
* \param attachments [in/out] As input, the attachment list submitted
|
||||
* in the original DRI2 query. As output, the attachment
|
||||
* list that was submitted in the DRI2 query that
|
||||
* obtained the current buffer list, as returned in the
|
||||
* output parameter \c buffers. (Note: If no new query
|
||||
* was made, then the list remains unaltered).
|
||||
*
|
||||
* \param count [out] Number of buffers in the current buffer list, as
|
||||
* returned in the output parameter \c buffers.
|
||||
*
|
||||
* \see enum intel_dri2_has_hiz
|
||||
* \see struct intel_screen::dri2_has_hiz
|
||||
* \see intel_update_renderbuffers
|
||||
*/
|
||||
static void
|
||||
intel_verify_dri2_has_hiz(struct intel_context *intel,
|
||||
__DRIdrawable *drawable,
|
||||
__DRIbuffer **buffers,
|
||||
unsigned **attachments,
|
||||
int *count)
|
||||
{
|
||||
assert(intel->intelScreen->dri2_has_hiz == INTEL_DRI2_HAS_HIZ_UNKNOWN);
|
||||
|
||||
struct gl_framebuffer *fb = drawable->driverPrivate;
|
||||
struct intel_renderbuffer *stencil_rb =
|
||||
intel_get_renderbuffer(fb, BUFFER_STENCIL);
|
||||
|
||||
if (stencil_rb) {
|
||||
/*
|
||||
* We requested a DRI2BufferStencil without knowing if the X driver
|
||||
* supports it. Now, check if X handled the request correctly and clean
|
||||
* up if it did not. (See comments for 'enum intel_dri2_has_hiz').
|
||||
*/
|
||||
struct intel_renderbuffer *depth_rb =
|
||||
intel_get_renderbuffer(fb, BUFFER_DEPTH);
|
||||
assert(intel_rb_format(stencil_rb) == MESA_FORMAT_S8);
|
||||
assert(depth_rb && intel_rb_format(depth_rb) == MESA_FORMAT_X8_Z24);
|
||||
|
||||
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
|
||||
* fencing.
|
||||
*/
|
||||
intel->intelScreen->dri2_has_hiz = INTEL_DRI2_HAS_HIZ_TRUE;
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* Oops... the screen doesn't support separate stencil. Discard the
|
||||
* separate depth and stencil buffers and replace them with
|
||||
* a combined depth/stencil buffer. Discard the hiz buffer too.
|
||||
*/
|
||||
intel->intelScreen->dri2_has_hiz = INTEL_DRI2_HAS_HIZ_FALSE;
|
||||
if (intel->must_use_separate_stencil) {
|
||||
_mesa_problem(&intel->ctx,
|
||||
"intel_context requires separate stencil, but the "
|
||||
"DRIscreen does not support it. You may need to "
|
||||
"upgrade the Intel X driver to 2.16.0");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* 1. Discard depth and stencil renderbuffers. */
|
||||
_mesa_remove_renderbuffer(fb, BUFFER_DEPTH);
|
||||
depth_rb = NULL;
|
||||
_mesa_remove_renderbuffer(fb, BUFFER_STENCIL);
|
||||
stencil_rb = NULL;
|
||||
|
||||
/* 2. Create new depth/stencil renderbuffer. */
|
||||
struct intel_renderbuffer *depth_stencil_rb =
|
||||
intel_create_renderbuffer(MESA_FORMAT_S8_Z24);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depth_stencil_rb->Base.Base);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depth_stencil_rb->Base.Base);
|
||||
|
||||
/* 3. Append DRI2BufferDepthStencil to attachment list. */
|
||||
int old_count = *count;
|
||||
unsigned int *old_attachments = *attachments;
|
||||
*count = old_count + 1;
|
||||
*attachments = malloc(2 * (*count) * sizeof(unsigned));
|
||||
memcpy(*attachments, old_attachments, 2 * old_count * sizeof(unsigned));
|
||||
free(old_attachments);
|
||||
(*attachments)[2 * old_count + 0] = __DRI_BUFFER_DEPTH_STENCIL;
|
||||
(*attachments)[2 * old_count + 1] = intel_bits_per_pixel(depth_stencil_rb);
|
||||
|
||||
/* 4. Request new set of DRI2 attachments. */
|
||||
__DRIscreen *screen = intel->intelScreen->driScrnPriv;
|
||||
*buffers = screen->dri2.loader->getBuffersWithFormat(drawable,
|
||||
&drawable->w,
|
||||
&drawable->h,
|
||||
*attachments,
|
||||
*count,
|
||||
count,
|
||||
drawable->loaderPrivate);
|
||||
if (!*buffers)
|
||||
return;
|
||||
|
||||
/*
|
||||
* I don't know how to recover from the failure assertion below.
|
||||
* Rather than fail gradually and unexpectedly, we should just die
|
||||
* now.
|
||||
*/
|
||||
assert(*count == old_count + 1);
|
||||
|
||||
/* 5. Assign the DRI buffer's DRM region to the its renderbuffers. */
|
||||
__DRIbuffer *depth_stencil_buffer = NULL;
|
||||
for (int i = 0; i < *count; ++i) {
|
||||
if ((*buffers)[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) {
|
||||
depth_stencil_buffer = &(*buffers)[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
struct intel_region *region =
|
||||
intel_region_alloc_for_handle(intel->intelScreen,
|
||||
depth_stencil_buffer->cpp,
|
||||
drawable->w,
|
||||
drawable->h,
|
||||
depth_stencil_buffer->pitch
|
||||
/ depth_stencil_buffer->cpp,
|
||||
depth_stencil_buffer->name,
|
||||
"dri2 depth / stencil buffer");
|
||||
if (!region)
|
||||
return;
|
||||
|
||||
struct intel_mipmap_tree *mt =
|
||||
intel_miptree_create_for_region(intel,
|
||||
GL_TEXTURE_2D,
|
||||
intel_rb_format(depth_stencil_rb),
|
||||
region);
|
||||
intel_region_release(®ion);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (intel_framebuffer_has_hiz(fb)) {
|
||||
/*
|
||||
* In the future, the driver may advertise a GL config with hiz
|
||||
* compatible depth bits and 0 stencil bits (for example, when the
|
||||
* driver gains support for float32 depth buffers). When that day comes,
|
||||
* here we need to verify that the X driver does in fact support hiz and
|
||||
* clean up if it doesn't.
|
||||
*
|
||||
* Presently, however, no verification or clean up is necessary, and
|
||||
* execution should not reach here. If the framebuffer still has a hiz
|
||||
* region, then we have already set dri2_has_hiz to true after
|
||||
* confirming above that the stencil buffer is W tiled.
|
||||
*/
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -586,23 +586,17 @@ intelCreateBuffer(__DRIscreen * driScrnPriv,
|
|||
if (mesaVis->depthBits == 24) {
|
||||
assert(mesaVis->stencilBits == 8);
|
||||
|
||||
if (screen->hw_has_separate_stencil
|
||||
&& screen->dri2_has_hiz != INTEL_DRI2_HAS_HIZ_FALSE) {
|
||||
/*
|
||||
* Request a separate stencil buffer even if we do not yet know if
|
||||
* the screen supports it. (See comments for
|
||||
* enum intel_dri2_has_hiz).
|
||||
*/
|
||||
rb = intel_create_renderbuffer(MESA_FORMAT_X8_Z24);
|
||||
if (screen->hw_has_separate_stencil) {
|
||||
rb = intel_create_private_renderbuffer(MESA_FORMAT_X8_Z24);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base);
|
||||
rb = intel_create_renderbuffer(MESA_FORMAT_S8);
|
||||
rb = intel_create_private_renderbuffer(MESA_FORMAT_S8);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, &rb->Base.Base);
|
||||
} else {
|
||||
/*
|
||||
* Use combined depth/stencil. Note that the renderbuffer is
|
||||
* attached to two attachment points.
|
||||
*/
|
||||
rb = intel_create_renderbuffer(MESA_FORMAT_S8_Z24);
|
||||
rb = intel_create_private_renderbuffer(MESA_FORMAT_S8_Z24);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, &rb->Base.Base);
|
||||
}
|
||||
|
|
@ -611,7 +605,7 @@ intelCreateBuffer(__DRIscreen * driScrnPriv,
|
|||
assert(mesaVis->stencilBits == 0);
|
||||
/* just 16-bit depth buffer, no hw stencil */
|
||||
struct intel_renderbuffer *depthRb
|
||||
= intel_create_renderbuffer(MESA_FORMAT_Z16);
|
||||
= intel_create_private_renderbuffer(MESA_FORMAT_Z16);
|
||||
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base.Base);
|
||||
}
|
||||
else {
|
||||
|
|
@ -854,7 +848,6 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp)
|
|||
|
||||
intelScreen->hw_has_separate_stencil = intelScreen->gen >= 6;
|
||||
intelScreen->hw_must_use_separate_stencil = intelScreen->gen >= 7;
|
||||
intelScreen->dri2_has_hiz = INTEL_DRI2_HAS_HIZ_UNKNOWN;
|
||||
|
||||
int has_llc = 0;
|
||||
bool success = intel_get_param(intelScreen->driScrnPriv, I915_PARAM_HAS_LLC,
|
||||
|
|
|
|||
|
|
@ -35,63 +35,6 @@
|
|||
#include "i915_drm.h"
|
||||
#include "xmlconfig.h"
|
||||
|
||||
/**
|
||||
* \brief Does X driver support DRI2BufferHiz and DRI2BufferStencil?
|
||||
*
|
||||
* (Here, "X driver" referes to the DDX driver, xf86-video-intel).
|
||||
*
|
||||
* The DRI2 protocol does not allow us to query the X driver's version nor
|
||||
* query for a list of buffer formats that the driver supports. So, to
|
||||
* determine if the X driver supports DRI2BufferHiz and DRI2BufferStencil we
|
||||
* must resort to a handshake.
|
||||
*
|
||||
* If the hardware lacks support for separate stencil (and consequently, lacks
|
||||
* support for hiz also), then the X driver's separate stencil and hiz support
|
||||
* is irrelevant and the handshake never occurs.
|
||||
*
|
||||
* Complications
|
||||
* -------------
|
||||
* The handshake is complicated by a bug in xf86-video-intel 2.15. Even though
|
||||
* that version of the X driver did not supppot requests for DRI2BufferHiz or
|
||||
* DRI2BufferStencil, if requested one it still allocated and returned one.
|
||||
* The returned buffer, however, was incorrectly X tiled.
|
||||
*
|
||||
* How the handshake works
|
||||
* -----------------------
|
||||
* Initially, intel_screen.dri2_has_hiz is set to unknown. The first time the
|
||||
* user requests a depth and stencil buffer, intelCreateBuffers() creates a
|
||||
* framebuffer with separate depth and stencil attachments (with formats
|
||||
* x8_z24 and s8).
|
||||
*
|
||||
* Eventually, intel_update_renderbuffers() makes a DRI2 request for
|
||||
* DRI2BufferStencil and DRI2BufferHiz. If the stencil buffer's tiling is
|
||||
* I915_TILING_NONE [1], then we joyfully set intel_screen.dri2_has_hiz to
|
||||
* true and continue as if nothing happend.
|
||||
*
|
||||
* [1] The stencil buffer is actually W tiled. However, we request from the
|
||||
* kernel a non-tiled buffer because the GTT is incapable of W fencing.
|
||||
*
|
||||
* If the buffers are X tiled, however, the handshake has failed and we must
|
||||
* clean up.
|
||||
* 1. Angrily set intel_screen.dri2_has_hiz to false.
|
||||
* 2. Discard the framebuffer's depth and stencil attachments.
|
||||
* 3. Attach a packed depth/stencil buffer to the framebuffer (with format
|
||||
* s8_z24).
|
||||
* 4. Make a DRI2 request for the new buffer, using attachment type
|
||||
* DRI2BufferDepthStencil).
|
||||
*
|
||||
* Future Considerations
|
||||
* ---------------------
|
||||
* On a sunny day in the far future, when we are certain that no one has an
|
||||
* xf86-video-intel installed without hiz and separate stencil support, then
|
||||
* this enumerant and the handshake should die.
|
||||
*/
|
||||
enum intel_dri2_has_hiz {
|
||||
INTEL_DRI2_HAS_HIZ_UNKNOWN,
|
||||
INTEL_DRI2_HAS_HIZ_TRUE,
|
||||
INTEL_DRI2_HAS_HIZ_FALSE,
|
||||
};
|
||||
|
||||
struct intel_screen
|
||||
{
|
||||
int deviceID;
|
||||
|
|
@ -111,7 +54,6 @@ struct intel_screen
|
|||
*/
|
||||
bool hw_has_separate_stencil;
|
||||
bool hw_must_use_separate_stencil;
|
||||
enum intel_dri2_has_hiz dri2_has_hiz;
|
||||
|
||||
bool kernel_has_gen7_sol_reset;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue