mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 04:48:08 +02:00
Support for separate depth and stencil renderbuffers.
If the user creates several stencil renderbuffers and several depth renderbuffers, any combination can get bound to a framebuffer object. Since the hardware only supports combined depth+stencil buffers we need to do some shuffling of buffer data to make things work. This code deals with that. Now fbotexture.c runs in hardware without the -ds flag. Probably quite a few loose ends, clean-ups remain...
This commit is contained in:
parent
78382b4bbe
commit
7f31255eb2
6 changed files with 319 additions and 18 deletions
|
|
@ -47,6 +47,7 @@ DRIVER_SOURCES = \
|
|||
intel_state.c \
|
||||
intel_tris.c \
|
||||
intel_fbo.c \
|
||||
intel_depthstencil.c \
|
||||
intel_bufmgr.c
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "intel_context.h"
|
||||
#include "intel_blit.h"
|
||||
#include "intel_buffers.h"
|
||||
#include "intel_depthstencil.h"
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_tris.h"
|
||||
#include "intel_regions.h"
|
||||
|
|
@ -516,8 +517,8 @@ void
|
|||
intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_region *colorRegion, *depthRegion;
|
||||
struct intel_renderbuffer *irbDepth, *irbStencil;
|
||||
struct intel_region *colorRegion, *depthRegion = NULL;
|
||||
struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
|
||||
int front = 0; /* drawing to front color buffer? */
|
||||
|
||||
if (!fb) {
|
||||
|
|
@ -533,6 +534,8 @@ intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
|
|||
_mesa_update_framebuffer(ctx);
|
||||
/* this updates the DrawBuffer's Width/Height if it's a FBO */
|
||||
_mesa_update_draw_buffer_bounds(ctx);
|
||||
|
||||
intel_validate_depth_stencil(ctx, fb);
|
||||
}
|
||||
|
||||
if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
|
|
@ -607,8 +610,13 @@ intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
|
|||
*** Get depth buffer region and check if we need a software fallback.
|
||||
*** Note the BUFFER_DEPTH attachment is usually a DEPTH_STENCIL buffer.
|
||||
***/
|
||||
#if 0
|
||||
irbDepth = intel_get_renderbuffer(fb, BUFFER_DEPTH);
|
||||
if (irbDepth) {
|
||||
#else
|
||||
if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
|
||||
irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped);
|
||||
#endif
|
||||
if (irbDepth->region) {
|
||||
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
|
||||
depthRegion = irbDepth->region;
|
||||
|
|
@ -638,9 +646,15 @@ intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
|
|||
*** This can only be hardware accelerated if we're using a
|
||||
*** combined DEPTH_STENCIL buffer (for now anyway).
|
||||
***/
|
||||
#if 0
|
||||
irbStencil = intel_get_renderbuffer(fb, BUFFER_STENCIL);
|
||||
if (irbStencil) {
|
||||
if (irbStencil == irbDepth && irbStencil->region) {
|
||||
#else
|
||||
if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
|
||||
irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
|
||||
#endif
|
||||
if ((irbStencil == irbDepth && irbStencil->region) /***||
|
||||
(irbStencil->PairedDepth == irbDepth->Base.Name)**/) {
|
||||
ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
|
||||
/* need to re-compute stencil hw state */
|
||||
|
|
@ -651,10 +665,14 @@ intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
|
|||
}
|
||||
}
|
||||
else {
|
||||
/* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */
|
||||
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
|
||||
/* need to re-compute stencil hw state */
|
||||
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
|
||||
}
|
||||
/*
|
||||
_mesa_debug(ctx, "STENCIL FALLBACK: 0x%x\n", intel->Fallback );
|
||||
*/
|
||||
|
||||
intel->vtbl.set_draw_region( intel, colorRegion, depthRegion );
|
||||
|
||||
|
|
|
|||
269
src/mesa/drivers/dri/i915/intel_depthstencil.c
Normal file
269
src/mesa/drivers/dri/i915/intel_depthstencil.c
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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, sub license, 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 NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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 "glheader.h"
|
||||
#include "imports.h"
|
||||
#include "context.h"
|
||||
#include "depthstencil.h"
|
||||
#include "fbobject.h"
|
||||
#include "framebuffer.h"
|
||||
#include "hash.h"
|
||||
#include "mtypes.h"
|
||||
#include "renderbuffer.h"
|
||||
|
||||
#include "intel_context.h"
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_depthstencil.h"
|
||||
#include "intel_regions.h"
|
||||
|
||||
|
||||
/**
|
||||
* The GL_EXT_framebuffer_object allows the user to create their own
|
||||
* framebuffer objects consisting of color renderbuffers (0 or more),
|
||||
* depth renderbuffers (0 or 1) and stencil renderbuffers (0 or 1).
|
||||
*
|
||||
* The spec considers depth and stencil renderbuffers to be totally independent
|
||||
* buffers. In reality, most graphics hardware today uses a combined
|
||||
* depth+stencil buffer (one 32-bit pixel = 24 bits of Z + 8 bits of stencil).
|
||||
*
|
||||
* This causes difficulty because the user may create some number of depth
|
||||
* renderbuffers and some number of stencil renderbuffers and bind them
|
||||
* together in framebuffers in any combination.
|
||||
*
|
||||
* This code manages all that.
|
||||
*
|
||||
* 1. Depth renderbuffers are always allocated in hardware as 32bpp
|
||||
* GL_DEPTH24_STENCIL8 buffers.
|
||||
*
|
||||
* 2. Stencil renderbuffers are initially allocated in software as 8bpp
|
||||
* GL_STENCIL_INDEX8 buffers.
|
||||
*
|
||||
* 3. Depth and Stencil renderbuffers use the PairedStencil and PairedDepth
|
||||
* fields (respectively) to indicate if the buffer's currently paired
|
||||
* with another stencil or depth buffer (respectively).
|
||||
*
|
||||
* 4. When a depth and stencil buffer are initially both attached to the
|
||||
* current framebuffer, we merge the stencil buffer values into the
|
||||
* depth buffer (really a depth+stencil buffer). The then hardware uses
|
||||
* the combined buffer.
|
||||
*
|
||||
* 5. Whenever a depth or stencil buffer is reallocated (with
|
||||
* glRenderbufferStorage) we undo the pairing and copy the stencil values
|
||||
* from the combined depth/stencil buffer back to the stencil-only buffer.
|
||||
*
|
||||
* 6. We also undo the pairing when we find a change in buffer bindings.
|
||||
*
|
||||
* 7. If a framebuffer is only using a depth renderbuffer (no stencil), we
|
||||
* just use the combined depth/stencil buffer and ignore the stencil values.
|
||||
*
|
||||
* 8. If a framebuffer is only using a stencil renderbuffer (no depth) we have
|
||||
* to promote the 8bpp software stencil buffer to a 32bpp hardware
|
||||
* depth+stencil buffer.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
static void
|
||||
map_regions(GLcontext *ctx,
|
||||
struct intel_renderbuffer *depthRb,
|
||||
struct intel_renderbuffer *stencilRb)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
if (depthRb && depthRb->region) {
|
||||
intel_region_map(intel, depthRb->region);
|
||||
depthRb->pfMap = depthRb->region->map;
|
||||
depthRb->pfPitch = depthRb->region->pitch;
|
||||
}
|
||||
if (stencilRb && stencilRb->region) {
|
||||
intel_region_map(intel, stencilRb->region);
|
||||
stencilRb->pfMap = stencilRb->region->map;
|
||||
stencilRb->pfPitch = stencilRb->region->pitch;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unmap_regions(GLcontext *ctx,
|
||||
struct intel_renderbuffer *depthRb,
|
||||
struct intel_renderbuffer *stencilRb)
|
||||
{
|
||||
struct intel_context *intel = intel_context(ctx);
|
||||
if (depthRb && depthRb->region) {
|
||||
intel_region_unmap(intel, depthRb->region);
|
||||
depthRb->pfMap = NULL;
|
||||
depthRb->pfPitch = 0;
|
||||
}
|
||||
if (stencilRb && stencilRb->region) {
|
||||
intel_region_unmap(intel, stencilRb->region);
|
||||
stencilRb->pfMap = NULL;
|
||||
stencilRb->pfPitch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Undo the pairing/interleaving between depth and stencil buffers.
|
||||
* driRb should be a depth/stencil or stencil renderbuffer.
|
||||
*/
|
||||
void
|
||||
intel_undo_depth_stencil_pairing(GLcontext *ctx,
|
||||
struct intel_renderbuffer *irb)
|
||||
{
|
||||
if (irb->PairedStencil) {
|
||||
/* irb is a depth/stencil buffer */
|
||||
struct gl_renderbuffer *stencilRb;
|
||||
struct intel_renderbuffer *stencilIrb;
|
||||
|
||||
ASSERT(irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
|
||||
stencilRb = _mesa_lookup_renderbuffer(ctx, irb->PairedStencil);
|
||||
stencilIrb = intel_renderbuffer(stencilRb);
|
||||
if (stencilIrb) {
|
||||
/* need to extract stencil values from the depth buffer */
|
||||
ASSERT(stencilIrb->PairedDepth == irb->Base.Name);
|
||||
map_regions(ctx, irb, NULL);
|
||||
_mesa_extract_stencil(ctx, &irb->Base, &stencilIrb->Base);
|
||||
unmap_regions(ctx, irb, NULL);
|
||||
stencilIrb->PairedDepth = 0;
|
||||
}
|
||||
irb->PairedStencil = 0;
|
||||
}
|
||||
else if (irb->PairedDepth) {
|
||||
/* irb is a stencil buffer */
|
||||
struct gl_renderbuffer *depthRb;
|
||||
struct intel_renderbuffer *depthIrb;
|
||||
|
||||
ASSERT(irb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
|
||||
irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
|
||||
depthRb = _mesa_lookup_renderbuffer(ctx, irb->PairedDepth);
|
||||
depthIrb = intel_renderbuffer(depthRb);
|
||||
if (depthIrb) {
|
||||
/* need to extract stencil values from the depth buffer */
|
||||
ASSERT(depthIrb->PairedStencil == irb->Base.Name);
|
||||
map_regions(ctx, irb, NULL);
|
||||
_mesa_extract_stencil(ctx, &depthIrb->Base, &irb->Base);
|
||||
unmap_regions(ctx, irb, NULL);
|
||||
depthIrb->PairedStencil = 0;
|
||||
}
|
||||
irb->PairedDepth = 0;
|
||||
}
|
||||
else {
|
||||
_mesa_problem(ctx, "Problem in undo_depth_stencil_pairing");
|
||||
}
|
||||
|
||||
ASSERT(irb->PairedStencil == 0);
|
||||
ASSERT(irb->PairedDepth == 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Must be called if NewState & _NEW_BUFFER
|
||||
*/
|
||||
void
|
||||
intel_validate_depth_stencil(GLcontext *ctx, struct gl_framebuffer *fb)
|
||||
{
|
||||
struct intel_renderbuffer *depthRb, *stencilRb;
|
||||
|
||||
depthRb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
|
||||
stencilRb = intel_get_renderbuffer(fb, BUFFER_STENCIL);
|
||||
|
||||
if (depthRb && stencilRb) {
|
||||
if (depthRb == stencilRb) {
|
||||
/* Using a user-created combined depth/stencil buffer.
|
||||
* Nothing to do.
|
||||
*/
|
||||
ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_STENCIL_EXT);
|
||||
ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
}
|
||||
else {
|
||||
/* Separate depth/stencil buffers, need to interleave now */
|
||||
ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_COMPONENT);
|
||||
ASSERT(stencilRb->Base._BaseFormat == GL_STENCIL_INDEX);
|
||||
/* may need to interleave depth/stencil now */
|
||||
if (depthRb->PairedStencil == stencilRb->Base.Name) {
|
||||
/* OK, the depth and stencil buffers are already interleaved */
|
||||
ASSERT(stencilRb->PairedDepth == depthRb->Base.Name);
|
||||
}
|
||||
else {
|
||||
/* need to setup pairing/interleaving */
|
||||
if (depthRb->PairedStencil) {
|
||||
intel_undo_depth_stencil_pairing(ctx, depthRb);
|
||||
}
|
||||
if (stencilRb->PairedDepth) {
|
||||
intel_undo_depth_stencil_pairing(ctx, stencilRb);
|
||||
}
|
||||
|
||||
ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
ASSERT(stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT ||
|
||||
stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
|
||||
/* establish new pairing: interleave stencil into depth buffer */
|
||||
map_regions(ctx, depthRb, stencilRb);
|
||||
_mesa_insert_stencil(ctx, &depthRb->Base, &stencilRb->Base);
|
||||
unmap_regions(ctx, depthRb, stencilRb);
|
||||
depthRb->PairedStencil = stencilRb->Base.Name;
|
||||
stencilRb->PairedDepth = depthRb->Base.Name;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if (depthRb) {
|
||||
/* Depth buffer but no stencil buffer.
|
||||
* We'll use a GL_DEPTH24_STENCIL8 buffer and ignore the stencil bits.
|
||||
*/
|
||||
ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
/* intel_undo any previous pairing */
|
||||
if (depthRb->PairedStencil) {
|
||||
intel_undo_depth_stencil_pairing(ctx, depthRb);
|
||||
}
|
||||
}
|
||||
else if (stencilRb) {
|
||||
/* Stencil buffer but no depth buffer.
|
||||
* Since h/w doesn't typically support just 8bpp stencil w/out Z,
|
||||
* we'll use a GL_DEPTH24_STENCIL8 buffer and ignore the depth bits.
|
||||
*/
|
||||
/* undo any previous pairing */
|
||||
if (stencilRb->PairedDepth) {
|
||||
intel_undo_depth_stencil_pairing(ctx, stencilRb);
|
||||
}
|
||||
if (stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT) {
|
||||
/* promote buffer to GL_DEPTH24_STENCIL8 */
|
||||
_mesa_promote_stencil(ctx, &stencilRb->Base);
|
||||
}
|
||||
ASSERT(stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT);
|
||||
}
|
||||
|
||||
_mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH);
|
||||
_mesa_update_stencil_buffer(ctx, fb, BUFFER_DEPTH); /* Yes, not STENCIL */
|
||||
|
||||
/* The hardware should use fb->Attachment[BUFFER_DEPTH].Renderbuffer
|
||||
* first, if present, then fb->Attachment[BUFFER_STENCIL].Renderbuffer
|
||||
* if present.
|
||||
*/
|
||||
}
|
||||
14
src/mesa/drivers/dri/i915/intel_depthstencil.h
Normal file
14
src/mesa/drivers/dri/i915/intel_depthstencil.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
#ifndef INTEL_DEPTH_STENCIL_H
|
||||
#define INTEL_DEPTH_STENCIL_H
|
||||
|
||||
|
||||
extern void
|
||||
intel_undo_depth_stencil_pairing(GLcontext *ctx,
|
||||
struct intel_renderbuffer *driRb);
|
||||
|
||||
extern void
|
||||
intel_validate_depth_stencil(GLcontext *ctx, struct gl_framebuffer *fb);
|
||||
|
||||
|
||||
#endif /* INTEL_DEPTH_STENCIL_H */
|
||||
|
|
@ -37,12 +37,12 @@
|
|||
#include "intel_context.h"
|
||||
#include "intel_buffers.h"
|
||||
#include "intel_bufmgr.h"
|
||||
#include "intel_depthstencil.h"
|
||||
#include "intel_fbo.h"
|
||||
#include "intel_mipmap_tree.h"
|
||||
#include "intel_regions.h"
|
||||
#include "intel_span.h"
|
||||
|
||||
|
||||
#define INTEL_RB_CLASS 0x12345678
|
||||
|
||||
|
||||
|
|
@ -102,6 +102,12 @@ intel_delete_renderbuffer(struct gl_renderbuffer *rb)
|
|||
struct intel_context *intel = intel_context(ctx);
|
||||
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
|
||||
|
||||
ASSERT(irb);
|
||||
|
||||
if (irb->PairedStencil || irb->PairedDepth) {
|
||||
intel_undo_depth_stencil_pairing(ctx, irb);
|
||||
}
|
||||
|
||||
if (intel && irb->region) {
|
||||
intel_region_release(intel, &irb->region);
|
||||
}
|
||||
|
|
@ -156,15 +162,6 @@ intel_alloc_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
|
|||
|
||||
ASSERT(rb->Name != 0);
|
||||
|
||||
/* defaults */
|
||||
rb->RedBits =
|
||||
rb->GreenBits =
|
||||
rb->BlueBits =
|
||||
rb->AlphaBits =
|
||||
rb->IndexBits =
|
||||
rb->DepthBits =
|
||||
rb->StencilBits = 0;
|
||||
|
||||
switch (internalFormat) {
|
||||
case GL_R3_G3_B2:
|
||||
case GL_RGB4:
|
||||
|
|
@ -202,12 +199,11 @@ intel_alloc_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
|
|||
case GL_STENCIL_INDEX4_EXT:
|
||||
case GL_STENCIL_INDEX8_EXT:
|
||||
case GL_STENCIL_INDEX16_EXT:
|
||||
rb->_ActualFormat = GL_STENCIL_INDEX8_EXT;
|
||||
rb->DataType = GL_UNSIGNED_BYTE;
|
||||
/* alloc a depth+stencil buffer */
|
||||
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
|
||||
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
|
||||
rb->StencilBits = 8;
|
||||
cpp = 1;
|
||||
softwareBuffer = GL_TRUE;
|
||||
/* XXX software buffer? */
|
||||
cpp = 4;
|
||||
break;
|
||||
case GL_DEPTH_COMPONENT16:
|
||||
rb->_ActualFormat = GL_DEPTH_COMPONENT16;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@ struct intel_renderbuffer {
|
|||
void *pfMap; /* possibly paged flipped map pointer */
|
||||
GLuint pfPitch; /* possibly paged flipped pitch */
|
||||
GLboolean RenderToTexture; /* RTT? */
|
||||
|
||||
GLuint PairedDepth; /**< only used if this is a depth renderbuffer */
|
||||
GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue