#include "intel_context.h"
#include "intel_buffers.h"
#include "intel_fbo.h"
+
#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
/**
* Return pointer to current color drawing region, or NULL.
* color buffers.
*/
void
-intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
+intel_draw_buffer(struct gl_context * ctx, struct gl_framebuffer *fb)
{
struct intel_context *intel = intel_context(ctx);
struct intel_region *colorRegions[MAX_DRAW_BUFFERS], *depthRegion = NULL;
struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
+ bool fb_has_hiz = intel_framebuffer_has_hiz(fb);
if (!fb) {
/* this can happen during the initial context initialization */
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.
*/
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
}
- /***
- *** Get depth buffer region and check if we need a software fallback.
- *** Note that the depth buffer is usually a DEPTH_STENCIL buffer.
- ***/
- if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) {
- irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped);
- if (irbDepth && irbDepth->region) {
- FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
- depthRegion = irbDepth->region;
- }
- else {
- FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE);
- depthRegion = NULL;
- }
- }
- else {
- /* not using depth buffer */
+ /* Check for depth fallback. */
+ if (irbDepth && irbDepth->region) {
+ assert(!fb_has_hiz || irbDepth->Base.Format != MESA_FORMAT_S8_Z24);
+ FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
+ depthRegion = irbDepth->region;
+ } else if (irbDepth && !irbDepth->region) {
+ FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE);
+ depthRegion = NULL;
+ } else { /* !irbDepth */
+ /* No fallback is needed because there is no depth buffer. */
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE);
depthRegion = NULL;
}
- /***
- *** Stencil buffer
- *** This can only be hardware accelerated if we're using a
- *** combined DEPTH_STENCIL buffer.
- ***/
- if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) {
- irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped);
- if (irbStencil && irbStencil->region) {
- ASSERT(irbStencil->Base.Format == MESA_FORMAT_S8_Z24);
- FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
- }
- else {
- FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
- }
- }
- else {
- /* XXX FBO: instead of FALSE, pass ctx->Stencil._Enabled ??? */
+ /* Check for stencil fallback. */
+ if (irbStencil && irbStencil->region) {
+ if (!intel->has_separate_stencil)
+ assert(irbStencil->Base.Format == MESA_FORMAT_S8_Z24);
+ if (fb_has_hiz || intel->must_use_separate_stencil)
+ assert(irbStencil->Base.Format == MESA_FORMAT_S8);
+ if (irbStencil->Base.Format == MESA_FORMAT_S8)
+ assert(intel->has_separate_stencil);
+ FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
+ } else if (irbStencil && !irbStencil->region) {
+ FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE);
+ } else { /* !irbStencil */
+ /* No fallback is needed because there is no stencil buffer. */
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE);
}
/* If we have a (packed) stencil buffer attached but no depth buffer,
* we still need to set up the shared depth/stencil state so we can use it.
*/
- if (depthRegion == NULL && irbStencil && irbStencil->region)
+ if (depthRegion == NULL && irbStencil && irbStencil->region
+ && irbStencil->Base.Format == MESA_FORMAT_S8_Z24) {
depthRegion = irbStencil->region;
+ }
/*
* Update depth and stencil test state
* only changes with _NEW_STENCIL (which seems sensible). So flag it
* here since this is the _NEW_BUFFERS path.
*/
- ctx->NewState |= (_NEW_DEPTH | _NEW_STENCIL);
+ intel->NewGLState |= (_NEW_DEPTH | _NEW_STENCIL);
}
intel->vtbl.set_draw_region(intel, colorRegions, depthRegion,
fb->_NumColorDrawBuffers);
+ intel->NewGLState |= _NEW_BUFFERS;
/* update viewport since it depends on window size */
#ifdef I915
intelCalcViewport(ctx);
#else
- ctx->NewState |= _NEW_VIEWPORT;
+ intel->NewGLState |= _NEW_VIEWPORT;
#endif
/* Set state we know depends on drawable parameters:
*/
if (ctx->Driver.FrontFace)
ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace);
else
- ctx->NewState |= _NEW_POLYGON;
+ intel->NewGLState |= _NEW_POLYGON;
}
static void
-intelDrawBuffer(GLcontext * ctx, GLenum mode)
+intelDrawBuffer(struct gl_context * ctx, GLenum mode)
{
if ((ctx->DrawBuffer != NULL) && (ctx->DrawBuffer->Name == 0)) {
struct intel_context *const intel = intel_context(ctx);
intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT)
|| (mode == GL_FRONT);
- /* If we weren't front-buffer rendering before but we are now, make sure
- * that the front-buffer has actually been allocated.
+ /* If we weren't front-buffer rendering before but we are now,
+ * invalidate our DRI drawable so we'll ask for new buffers
+ * (including the fake front) before we start rendering again.
*/
- if (!was_front_buffer_rendering && intel->is_front_buffer_rendering) {
- intel_update_renderbuffers(intel->driContext,
- intel->driContext->driDrawablePriv);
- }
+ if (!was_front_buffer_rendering && intel->is_front_buffer_rendering)
+ dri2InvalidateDrawable(intel->driContext->driDrawablePriv);
}
intel_draw_buffer(ctx, ctx->DrawBuffer);
static void
-intelReadBuffer(GLcontext * ctx, GLenum mode)
+intelReadBuffer(struct gl_context * ctx, GLenum mode)
{
if ((ctx->DrawBuffer != NULL) && (ctx->DrawBuffer->Name == 0)) {
struct intel_context *const intel = intel_context(ctx);
intel->is_front_buffer_reading = (mode == GL_FRONT_LEFT)
|| (mode == GL_FRONT);
- /* If we weren't front-buffer reading before but we are now, make sure
- * that the front-buffer has actually been allocated.
+ /* If we weren't front-buffer reading before but we are now,
+ * invalidate our DRI drawable so we'll ask for new buffers
+ * (including the fake front) before we start reading again.
*/
- if (!was_front_buffer_reading && intel->is_front_buffer_reading) {
- intel_update_renderbuffers(intel->driContext,
- intel->driContext->driDrawablePriv);
- }
+ if (!was_front_buffer_reading && intel->is_front_buffer_reading)
+ dri2InvalidateDrawable(intel->driContext->driReadablePriv);
}
-
- if (ctx->ReadBuffer == ctx->DrawBuffer) {
- /* This will update FBO completeness status.
- * A framebuffer will be incomplete if the GL_READ_BUFFER setting
- * refers to a missing renderbuffer. Calling glReadBuffer can set
- * that straight and can make the drawing buffer complete.
- */
- intel_draw_buffer(ctx, ctx->DrawBuffer);
- }
- /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc)
- * reference ctx->ReadBuffer and do appropriate state checks.
- */
}