2007-11-07 10:04:59 -08:00
|
|
|
/**************************************************************************
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
2011-10-31 17:07:34 -07:00
|
|
|
#include "main/enums.h"
|
2008-09-18 15:17:05 -06:00
|
|
|
#include "main/imports.h"
|
2009-01-22 15:43:40 -07:00
|
|
|
#include "main/macros.h"
|
2011-01-09 01:25:54 -08:00
|
|
|
#include "main/mfeatures.h"
|
2008-09-18 15:17:05 -06:00
|
|
|
#include "main/mtypes.h"
|
|
|
|
#include "main/fbobject.h"
|
|
|
|
#include "main/framebuffer.h"
|
|
|
|
#include "main/renderbuffer.h"
|
|
|
|
#include "main/context.h"
|
2011-02-05 10:21:11 +00:00
|
|
|
#include "main/teximage.h"
|
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>
2011-11-15 22:17:34 -08:00
|
|
|
#include "main/image.h"
|
|
|
|
|
2011-06-13 16:07:32 -06:00
|
|
|
#include "swrast/swrast.h"
|
2009-08-10 13:43:00 -06:00
|
|
|
#include "drivers/common/meta.h"
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
#include "intel_context.h"
|
2009-12-09 11:36:45 -08:00
|
|
|
#include "intel_batchbuffer.h"
|
2007-11-07 10:04:59 -08:00
|
|
|
#include "intel_buffers.h"
|
2011-10-19 10:31:40 -07:00
|
|
|
#include "intel_blit.h"
|
2007-11-07 10:04:59 -08:00
|
|
|
#include "intel_fbo.h"
|
|
|
|
#include "intel_mipmap_tree.h"
|
|
|
|
#include "intel_regions.h"
|
2010-12-09 17:08:31 -08:00
|
|
|
#include "intel_tex.h"
|
|
|
|
#include "intel_span.h"
|
2011-01-10 15:45:28 -08:00
|
|
|
#ifndef I915
|
|
|
|
#include "brw_context.h"
|
|
|
|
#endif
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
#define FILE_DEBUG_FLAG DEBUG_FBO
|
|
|
|
|
2011-12-07 15:38:08 -08:00
|
|
|
static struct gl_renderbuffer *
|
|
|
|
intel_new_renderbuffer(struct gl_context * ctx, GLuint name);
|
|
|
|
|
2011-11-13 23:06:17 -08:00
|
|
|
struct intel_region*
|
|
|
|
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
|
|
|
|
{
|
|
|
|
struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex);
|
2011-12-07 15:02:02 -08:00
|
|
|
if (irb && irb->mt) {
|
|
|
|
if (attIndex == BUFFER_STENCIL && irb->mt->stencil_mt)
|
|
|
|
return irb->mt->stencil_mt->region;
|
|
|
|
else
|
|
|
|
return irb->mt->region;
|
|
|
|
} else
|
2011-11-13 23:06:17 -08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-11-07 10:04:59 -08:00
|
|
|
/**
|
|
|
|
* Create a new framebuffer object.
|
|
|
|
*/
|
|
|
|
static struct gl_framebuffer *
|
2010-10-12 12:26:10 -04:00
|
|
|
intel_new_framebuffer(struct gl_context * ctx, GLuint name)
|
2007-11-07 10:04:59 -08:00
|
|
|
{
|
|
|
|
/* Only drawable state in intel_framebuffer at this time, just use Mesa's
|
|
|
|
* class
|
|
|
|
*/
|
|
|
|
return _mesa_new_framebuffer(ctx, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-29 14:57:31 -07:00
|
|
|
/** Called by gl_renderbuffer::Delete() */
|
2007-11-07 10:04:59 -08:00
|
|
|
static void
|
2012-11-30 10:04:48 -07:00
|
|
|
intel_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
|
2007-11-07 10:04:59 -08:00
|
|
|
{
|
|
|
|
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
|
|
|
|
|
|
|
|
ASSERT(irb);
|
|
|
|
|
2011-11-16 14:04:25 -08:00
|
|
|
intel_miptree_release(&irb->mt);
|
2011-06-29 11:37:35 -07:00
|
|
|
|
2012-11-30 10:04:48 -07:00
|
|
|
_mesa_delete_renderbuffer(ctx, rb);
|
2007-11-07 10:04:59 -08:00
|
|
|
}
|
|
|
|
|
2011-11-08 18:17:33 -08:00
|
|
|
/**
|
|
|
|
* \see dd_function_table::MapRenderbuffer
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
intel_map_renderbuffer(struct gl_context *ctx,
|
|
|
|
struct gl_renderbuffer *rb,
|
|
|
|
GLuint x, GLuint y, GLuint w, GLuint h,
|
|
|
|
GLbitfield mode,
|
|
|
|
GLubyte **out_map,
|
|
|
|
GLint *out_stride)
|
|
|
|
{
|
|
|
|
struct intel_context *intel = intel_context(ctx);
|
2012-01-24 15:52:52 -08:00
|
|
|
struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb;
|
2011-11-08 18:17:33 -08:00
|
|
|
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
|
2011-11-30 08:31:53 -08:00
|
|
|
void *map;
|
|
|
|
int stride;
|
2011-11-08 18:17:33 -08:00
|
|
|
|
2012-01-24 15:52:52 -08:00
|
|
|
if (srb->Buffer) {
|
|
|
|
/* this is a malloc'd renderbuffer (accum buffer), not an irb */
|
2012-01-07 15:05:35 -07:00
|
|
|
GLint bpp = _mesa_get_format_bytes(rb->Format);
|
2012-01-24 15:52:52 -08:00
|
|
|
GLint rowStride = srb->RowStride;
|
|
|
|
*out_map = (GLubyte *) srb->Buffer + y * rowStride + x * bpp;
|
2012-01-07 15:05:35 -07:00
|
|
|
*out_stride = rowStride;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-11-08 18:17:33 -08:00
|
|
|
/* We sometimes get called with this by our intel_span.c usage. */
|
2011-12-07 14:50:02 -08:00
|
|
|
if (!irb->mt) {
|
2011-11-08 18:17:33 -08:00
|
|
|
*out_map = NULL;
|
|
|
|
*out_stride = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-11-30 08:31:53 -08:00
|
|
|
/* For a window-system renderbuffer, we need to flip the mapping we receive
|
|
|
|
* upside-down. So we need to ask for a rectangle on flipped vertically, and
|
|
|
|
* we then return a pointer to the bottom of it with a negative stride.
|
|
|
|
*/
|
|
|
|
if (rb->Name == 0) {
|
|
|
|
y = rb->Height - y - h;
|
|
|
|
}
|
2011-11-28 16:08:46 -08:00
|
|
|
|
2011-11-30 08:31:53 -08:00
|
|
|
intel_miptree_map(intel, irb->mt, irb->mt_level, irb->mt_layer,
|
|
|
|
x, y, w, h, mode, &map, &stride);
|
2011-11-28 16:08:46 -08:00
|
|
|
|
2011-11-30 08:31:53 -08:00
|
|
|
if (rb->Name == 0) {
|
|
|
|
map += (h - 1) * stride;
|
|
|
|
stride = -stride;
|
|
|
|
}
|
2011-11-28 16:08:46 -08:00
|
|
|
|
2011-11-30 08:31:53 -08:00
|
|
|
DBG("%s: rb %d (%s) mt mapped: (%d, %d) (%dx%d) -> %p/%d\n",
|
|
|
|
__FUNCTION__, rb->Name, _mesa_get_format_name(rb->Format),
|
2011-12-13 12:03:37 -08:00
|
|
|
x, y, w, h, map, stride);
|
2011-11-28 16:08:46 -08:00
|
|
|
|
2011-11-30 08:31:53 -08:00
|
|
|
*out_map = map;
|
|
|
|
*out_stride = stride;
|
2011-11-08 18:17:33 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \see dd_function_table::UnmapRenderbuffer
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
intel_unmap_renderbuffer(struct gl_context *ctx,
|
|
|
|
struct gl_renderbuffer *rb)
|
|
|
|
{
|
2011-11-28 16:08:46 -08:00
|
|
|
struct intel_context *intel = intel_context(ctx);
|
2012-01-24 15:52:52 -08:00
|
|
|
struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb;
|
2011-11-08 18:17:33 -08:00
|
|
|
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
|
|
|
|
|
|
|
|
DBG("%s: rb %d (%s)\n", __FUNCTION__,
|
|
|
|
rb->Name, _mesa_get_format_name(rb->Format));
|
|
|
|
|
2012-01-24 15:52:52 -08:00
|
|
|
if (srb->Buffer) {
|
2012-01-07 15:05:35 -07:00
|
|
|
/* this is a malloc'd renderbuffer (accum buffer) */
|
|
|
|
/* nothing to do */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-11-30 08:31:53 -08:00
|
|
|
intel_miptree_unmap(intel, irb->mt, irb->mt_level, irb->mt_layer);
|
2011-10-11 14:22:45 -07:00
|
|
|
}
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
|
i965/gen6: Initial implementation of MSAA.
This patch enables MSAA for Gen6, by modifying intel_mipmap_tree to
understand multisampled buffers, adapting the rendering pipeline setup
to enable multisampled rendering, and adding multisample resolve
operations to brw_blorp_blit.cpp. Some preparation work is also
included for Gen7, but it is not yet enabled.
MSAA support is still fairly preliminary. In particular, the
following are not yet supported:
- Fully general blits between MSAA and non-MSAA buffers.
- Formats other than RGBA8, DEPTH24, and STENCIL8.
- Centroid interpolation.
- Coverage parameters (glSampleCoverage, GL_SAMPLE_ALPHA_TO_COVERAGE,
GL_SAMPLE_ALPHA_TO_ONE, GL_SAMPLE_COVERAGE, GL_SAMPLE_COVERAGE_VALUE,
GL_SAMPLE_COVERAGE_INVERT).
Fixes piglit tests "EXT_framebuffer_multisample/accuracy" on
i965/Gen6.
v2:
- In intel_alloc_renderbuffer_storage(), quantize the requested number
of samples to the next higher sample count supported by the
hardware. This ensures that a query of GL_SAMPLES will return the
correct value. It also ensures that MSAA is fully disabled on Gen7
for now (since Gen7 MSAA support doesn't work yet).
- When reading from a non-MSAA surface, ensure that s_is_zero is true
so that we won't try to read from a nonexistent sample.
2012-04-29 21:41:42 -07:00
|
|
|
/**
|
|
|
|
* Round up the requested multisample count to the next supported sample size.
|
|
|
|
*/
|
2012-07-11 14:52:53 -07:00
|
|
|
unsigned
|
|
|
|
intel_quantize_num_samples(struct intel_screen *intel, unsigned num_samples)
|
i965/gen6: Initial implementation of MSAA.
This patch enables MSAA for Gen6, by modifying intel_mipmap_tree to
understand multisampled buffers, adapting the rendering pipeline setup
to enable multisampled rendering, and adding multisample resolve
operations to brw_blorp_blit.cpp. Some preparation work is also
included for Gen7, but it is not yet enabled.
MSAA support is still fairly preliminary. In particular, the
following are not yet supported:
- Fully general blits between MSAA and non-MSAA buffers.
- Formats other than RGBA8, DEPTH24, and STENCIL8.
- Centroid interpolation.
- Coverage parameters (glSampleCoverage, GL_SAMPLE_ALPHA_TO_COVERAGE,
GL_SAMPLE_ALPHA_TO_ONE, GL_SAMPLE_COVERAGE, GL_SAMPLE_COVERAGE_VALUE,
GL_SAMPLE_COVERAGE_INVERT).
Fixes piglit tests "EXT_framebuffer_multisample/accuracy" on
i965/Gen6.
v2:
- In intel_alloc_renderbuffer_storage(), quantize the requested number
of samples to the next higher sample count supported by the
hardware. This ensures that a query of GL_SAMPLES will return the
correct value. It also ensures that MSAA is fully disabled on Gen7
for now (since Gen7 MSAA support doesn't work yet).
- When reading from a non-MSAA surface, ensure that s_is_zero is true
so that we won't try to read from a nonexistent sample.
2012-04-29 21:41:42 -07:00
|
|
|
{
|
|
|
|
switch (intel->gen) {
|
|
|
|
case 6:
|
|
|
|
/* Gen6 supports only 4x multisampling. */
|
|
|
|
if (num_samples > 0)
|
|
|
|
return 4;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
case 7:
|
2012-07-17 21:06:01 -07:00
|
|
|
/* Gen7 supports 4x and 8x multisampling. */
|
|
|
|
if (num_samples > 4)
|
|
|
|
return 8;
|
|
|
|
else if (num_samples > 0)
|
i965/msaa: Enable 4x MSAA on Gen7.
Basic 4x MSAA support now works on Gen7. This patch enables it.
As with Gen6, MSAA support is still fairly preliminary. In
particular, the following are not yet supported:
- 8x oversampling (Gen7 has hardware support for this, but we do not
yet expose it).
- Fully general blits between MSAA and non-MSAA buffers.
- Formats other than RGBA8, DEPTH24, and STENCIL8.
- Centrold interpolation.
- Coverage parameters (glSampleCoverage, GL_SAMPLE_ALPHA_TO_COVERAGE,
GL_SAMPLE_ALPHA_TO_ONE, GL_SAMPLE_COVERAGE, GL_SAMPLE_COVERAGE_VALUE,
GL_SAMPLE_COVERAGE_INVERT).
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2012-05-09 15:51:11 -07:00
|
|
|
return 4;
|
|
|
|
else
|
|
|
|
return 0;
|
i965/gen6: Initial implementation of MSAA.
This patch enables MSAA for Gen6, by modifying intel_mipmap_tree to
understand multisampled buffers, adapting the rendering pipeline setup
to enable multisampled rendering, and adding multisample resolve
operations to brw_blorp_blit.cpp. Some preparation work is also
included for Gen7, but it is not yet enabled.
MSAA support is still fairly preliminary. In particular, the
following are not yet supported:
- Fully general blits between MSAA and non-MSAA buffers.
- Formats other than RGBA8, DEPTH24, and STENCIL8.
- Centroid interpolation.
- Coverage parameters (glSampleCoverage, GL_SAMPLE_ALPHA_TO_COVERAGE,
GL_SAMPLE_ALPHA_TO_ONE, GL_SAMPLE_COVERAGE, GL_SAMPLE_COVERAGE_VALUE,
GL_SAMPLE_COVERAGE_INVERT).
Fixes piglit tests "EXT_framebuffer_multisample/accuracy" on
i965/Gen6.
v2:
- In intel_alloc_renderbuffer_storage(), quantize the requested number
of samples to the next higher sample count supported by the
hardware. This ensures that a query of GL_SAMPLES will return the
correct value. It also ensures that MSAA is fully disabled on Gen7
for now (since Gen7 MSAA support doesn't work yet).
- When reading from a non-MSAA surface, ensure that s_is_zero is true
so that we won't try to read from a nonexistent sample.
2012-04-29 21:41:42 -07:00
|
|
|
return 0;
|
|
|
|
default:
|
2012-07-26 18:02:20 -07:00
|
|
|
/* MSAA unsupported. However, a careful reading of
|
|
|
|
* EXT_framebuffer_multisample reveals that we need to permit
|
|
|
|
* num_samples to be 1 (since num_samples is permitted to be as high as
|
|
|
|
* GL_MAX_SAMPLES, and GL_MAX_SAMPLES must be at least 1). Since
|
|
|
|
* platforms before Gen6 don't support MSAA, this is safe, because
|
|
|
|
* multisampling won't happen anyhow.
|
|
|
|
*/
|
|
|
|
if (num_samples > 0)
|
|
|
|
return 1;
|
i965/gen6: Initial implementation of MSAA.
This patch enables MSAA for Gen6, by modifying intel_mipmap_tree to
understand multisampled buffers, adapting the rendering pipeline setup
to enable multisampled rendering, and adding multisample resolve
operations to brw_blorp_blit.cpp. Some preparation work is also
included for Gen7, but it is not yet enabled.
MSAA support is still fairly preliminary. In particular, the
following are not yet supported:
- Fully general blits between MSAA and non-MSAA buffers.
- Formats other than RGBA8, DEPTH24, and STENCIL8.
- Centroid interpolation.
- Coverage parameters (glSampleCoverage, GL_SAMPLE_ALPHA_TO_COVERAGE,
GL_SAMPLE_ALPHA_TO_ONE, GL_SAMPLE_COVERAGE, GL_SAMPLE_COVERAGE_VALUE,
GL_SAMPLE_COVERAGE_INVERT).
Fixes piglit tests "EXT_framebuffer_multisample/accuracy" on
i965/Gen6.
v2:
- In intel_alloc_renderbuffer_storage(), quantize the requested number
of samples to the next higher sample count supported by the
hardware. This ensures that a query of GL_SAMPLES will return the
correct value. It also ensures that MSAA is fully disabled on Gen7
for now (since Gen7 MSAA support doesn't work yet).
- When reading from a non-MSAA surface, ensure that s_is_zero is true
so that we won't try to read from a nonexistent sample.
2012-04-29 21:41:42 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-07 10:04:59 -08:00
|
|
|
/**
|
|
|
|
* Called via glRenderbufferStorageEXT() to set the format and allocate
|
|
|
|
* storage for a user-created renderbuffer.
|
|
|
|
*/
|
2012-09-21 10:36:22 +02:00
|
|
|
static GLboolean
|
2010-10-12 12:26:10 -04:00
|
|
|
intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
|
2007-11-07 10:04:59 -08:00
|
|
|
GLenum internalFormat,
|
|
|
|
GLuint width, GLuint height)
|
|
|
|
{
|
|
|
|
struct intel_context *intel = intel_context(ctx);
|
2012-07-11 14:52:53 -07:00
|
|
|
struct intel_screen *screen = intel->intelScreen;
|
2007-11-07 10:04:59 -08:00
|
|
|
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
|
2012-07-11 14:52:53 -07:00
|
|
|
rb->NumSamples = intel_quantize_num_samples(screen, rb->NumSamples);
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
switch (internalFormat) {
|
2010-12-09 17:15:26 -08:00
|
|
|
default:
|
|
|
|
/* Use the same format-choice logic as for textures.
|
|
|
|
* Renderbuffers aren't any different from textures for us,
|
|
|
|
* except they're less useful because you can't texture with
|
|
|
|
* them.
|
|
|
|
*/
|
2012-08-24 08:31:37 -06:00
|
|
|
rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, GL_TEXTURE_2D,
|
|
|
|
internalFormat,
|
2011-01-04 13:44:34 -08:00
|
|
|
GL_NONE, GL_NONE);
|
2010-08-25 06:14:42 -07:00
|
|
|
break;
|
2007-11-07 10:04:59 -08:00
|
|
|
case GL_STENCIL_INDEX:
|
|
|
|
case GL_STENCIL_INDEX1_EXT:
|
|
|
|
case GL_STENCIL_INDEX4_EXT:
|
|
|
|
case GL_STENCIL_INDEX8_EXT:
|
|
|
|
case GL_STENCIL_INDEX16_EXT:
|
2010-12-09 17:15:26 -08:00
|
|
|
/* These aren't actual texture formats, so force them here. */
|
2011-05-23 13:47:35 -07:00
|
|
|
if (intel->has_separate_stencil) {
|
|
|
|
rb->Format = MESA_FORMAT_S8;
|
|
|
|
} else {
|
|
|
|
assert(!intel->must_use_separate_stencil);
|
|
|
|
rb->Format = MESA_FORMAT_S8_Z24;
|
|
|
|
}
|
2007-11-07 10:04:59 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-06-17 12:12:35 -07:00
|
|
|
rb->Width = width;
|
|
|
|
rb->Height = height;
|
2009-10-08 20:27:27 -06:00
|
|
|
rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
|
|
|
|
|
2011-11-16 14:04:25 -08:00
|
|
|
intel_miptree_release(&irb->mt);
|
2007-11-07 10:04:59 -08:00
|
|
|
|
2011-10-31 17:07:34 -07:00
|
|
|
DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__,
|
|
|
|
_mesa_lookup_enum_by_nr(internalFormat),
|
|
|
|
_mesa_get_format_name(rb->Format), width, height);
|
2007-11-07 10:04:59 -08:00
|
|
|
|
2012-04-23 14:14:11 -07:00
|
|
|
if (width == 0 || height == 0)
|
|
|
|
return true;
|
|
|
|
|
2011-12-07 15:38:08 -08:00
|
|
|
irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format,
|
i965/gen6: Initial implementation of MSAA.
This patch enables MSAA for Gen6, by modifying intel_mipmap_tree to
understand multisampled buffers, adapting the rendering pipeline setup
to enable multisampled rendering, and adding multisample resolve
operations to brw_blorp_blit.cpp. Some preparation work is also
included for Gen7, but it is not yet enabled.
MSAA support is still fairly preliminary. In particular, the
following are not yet supported:
- Fully general blits between MSAA and non-MSAA buffers.
- Formats other than RGBA8, DEPTH24, and STENCIL8.
- Centroid interpolation.
- Coverage parameters (glSampleCoverage, GL_SAMPLE_ALPHA_TO_COVERAGE,
GL_SAMPLE_ALPHA_TO_ONE, GL_SAMPLE_COVERAGE, GL_SAMPLE_COVERAGE_VALUE,
GL_SAMPLE_COVERAGE_INVERT).
Fixes piglit tests "EXT_framebuffer_multisample/accuracy" on
i965/Gen6.
v2:
- In intel_alloc_renderbuffer_storage(), quantize the requested number
of samples to the next higher sample count supported by the
hardware. This ensures that a query of GL_SAMPLES will return the
correct value. It also ensures that MSAA is fully disabled on Gen7
for now (since Gen7 MSAA support doesn't work yet).
- When reading from a non-MSAA surface, ensure that s_is_zero is true
so that we won't try to read from a nonexistent sample.
2012-04-29 21:41:42 -07:00
|
|
|
width, height,
|
|
|
|
rb->NumSamples);
|
2011-12-07 15:38:08 -08:00
|
|
|
if (!irb->mt)
|
|
|
|
return false;
|
2011-06-17 12:12:35 -07:00
|
|
|
|
2011-10-07 12:26:50 -07:00
|
|
|
return true;
|
2007-11-07 10:04:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-11 19:04:02 -05:00
|
|
|
static void
|
2010-10-12 12:26:10 -04:00
|
|
|
intel_image_target_renderbuffer_storage(struct gl_context *ctx,
|
2010-02-11 19:04:02 -05:00
|
|
|
struct gl_renderbuffer *rb,
|
|
|
|
void *image_handle)
|
|
|
|
{
|
|
|
|
struct intel_context *intel = intel_context(ctx);
|
|
|
|
struct intel_renderbuffer *irb;
|
|
|
|
__DRIscreen *screen;
|
|
|
|
__DRIimage *image;
|
|
|
|
|
|
|
|
screen = intel->intelScreen->driScrnPriv;
|
2010-09-22 22:01:17 -04:00
|
|
|
image = screen->dri2.image->lookupEGLImage(screen, image_handle,
|
|
|
|
screen->loaderPrivate);
|
2010-02-11 19:04:02 -05:00
|
|
|
if (image == NULL)
|
|
|
|
return;
|
|
|
|
|
2011-08-21 21:36:40 +08:00
|
|
|
/* __DRIimage is opaque to the core so it has to be checked here */
|
|
|
|
switch (image->format) {
|
|
|
|
case MESA_FORMAT_RGBA8888_REV:
|
|
|
|
_mesa_error(&intel->ctx, GL_INVALID_OPERATION,
|
|
|
|
"glEGLImageTargetRenderbufferStorage(unsupported image format");
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-02-11 19:04:02 -05:00
|
|
|
irb = intel_renderbuffer(rb);
|
2011-11-16 14:04:25 -08:00
|
|
|
intel_miptree_release(&irb->mt);
|
|
|
|
irb->mt = intel_miptree_create_for_region(intel,
|
|
|
|
GL_TEXTURE_2D,
|
|
|
|
image->format,
|
|
|
|
image->region);
|
|
|
|
if (!irb->mt)
|
|
|
|
return;
|
2010-02-11 19:04:02 -05:00
|
|
|
|
2010-03-02 15:41:12 -05:00
|
|
|
rb->InternalFormat = image->internal_format;
|
2010-02-11 19:04:02 -05:00
|
|
|
rb->Width = image->region->width;
|
|
|
|
rb->Height = image->region->height;
|
|
|
|
rb->Format = image->format;
|
|
|
|
rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx,
|
|
|
|
image->internal_format);
|
|
|
|
}
|
|
|
|
|
2007-11-07 10:04:59 -08:00
|
|
|
/**
|
|
|
|
* Called for each hardware renderbuffer when a _window_ is resized.
|
|
|
|
* Just update fields.
|
|
|
|
* Not used for user-created renderbuffers!
|
|
|
|
*/
|
|
|
|
static GLboolean
|
2010-10-12 12:26:10 -04:00
|
|
|
intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
|
2007-11-07 10:04:59 -08:00
|
|
|
GLenum internalFormat, GLuint width, GLuint height)
|
|
|
|
{
|
|
|
|
ASSERT(rb->Name == 0);
|
|
|
|
rb->Width = width;
|
|
|
|
rb->Height = height;
|
2009-10-08 20:27:27 -06:00
|
|
|
rb->InternalFormat = internalFormat;
|
2007-11-07 10:04:59 -08:00
|
|
|
|
2011-10-07 12:26:50 -07:00
|
|
|
return true;
|
2007-11-07 10:04:59 -08:00
|
|
|
}
|
|
|
|
|
2009-01-29 14:57:31 -07:00
|
|
|
|
2007-11-07 10:04:59 -08:00
|
|
|
static void
|
2010-10-12 12:26:10 -04:00
|
|
|
intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
|
2007-11-07 10:04:59 -08:00
|
|
|
GLuint width, GLuint height)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
_mesa_resize_framebuffer(ctx, fb, width, height);
|
|
|
|
|
2011-10-07 12:26:50 -07:00
|
|
|
fb->Initialized = true; /* XXX remove someday */
|
2007-11-07 10:04:59 -08:00
|
|
|
|
2012-07-18 12:54:48 -07:00
|
|
|
if (_mesa_is_user_fbo(fb)) {
|
2007-11-07 10:04:59 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-01-01 23:21:16 -05:00
|
|
|
|
2007-11-07 10:04:59 -08:00
|
|
|
/* Make sure all window system renderbuffers are up to date */
|
2010-01-01 23:21:16 -05:00
|
|
|
for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) {
|
|
|
|
struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
/* only resize if size is changing */
|
|
|
|
if (rb && (rb->Width != width || rb->Height != height)) {
|
|
|
|
rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-29 14:57:31 -07:00
|
|
|
|
|
|
|
/** Dummy function for gl_renderbuffer::AllocStorage() */
|
2007-11-07 10:04:59 -08:00
|
|
|
static GLboolean
|
2010-10-12 12:26:10 -04:00
|
|
|
intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
|
2007-11-07 10:04:59 -08:00
|
|
|
GLenum internalFormat, GLuint width, GLuint height)
|
|
|
|
{
|
|
|
|
_mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
|
2011-10-07 12:26:50 -07:00
|
|
|
return false;
|
2007-11-07 10:04:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new intel_renderbuffer which corresponds to an on-screen window,
|
|
|
|
* not a user-created renderbuffer.
|
2012-07-11 15:10:49 -07:00
|
|
|
*
|
|
|
|
* \param num_samples must be quantized.
|
2007-11-07 10:04:59 -08:00
|
|
|
*/
|
|
|
|
struct intel_renderbuffer *
|
2012-07-11 15:10:49 -07:00
|
|
|
intel_create_renderbuffer(gl_format format, unsigned num_samples)
|
2007-11-07 10:04:59 -08:00
|
|
|
{
|
|
|
|
struct intel_renderbuffer *irb;
|
2012-01-16 12:40:01 -07:00
|
|
|
struct gl_renderbuffer *rb;
|
|
|
|
|
|
|
|
GET_CURRENT_CONTEXT(ctx);
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
irb = CALLOC_STRUCT(intel_renderbuffer);
|
|
|
|
if (!irb) {
|
|
|
|
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-01-16 12:40:01 -07:00
|
|
|
rb = &irb->Base.Base;
|
|
|
|
|
|
|
|
_mesa_init_renderbuffer(rb, 0);
|
|
|
|
rb->ClassID = INTEL_RB_CLASS;
|
|
|
|
rb->_BaseFormat = _mesa_get_format_base_format(format);
|
|
|
|
rb->Format = format;
|
|
|
|
rb->InternalFormat = rb->_BaseFormat;
|
2012-07-11 15:10:49 -07:00
|
|
|
rb->NumSamples = num_samples;
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
/* intel-specific methods */
|
2012-01-16 12:40:01 -07:00
|
|
|
rb->Delete = intel_delete_renderbuffer;
|
|
|
|
rb->AllocStorage = intel_alloc_window_storage;
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
return irb;
|
|
|
|
}
|
|
|
|
|
2012-07-04 10:52:31 -07:00
|
|
|
/**
|
|
|
|
* Private window-system buffers (as opposed to ones shared with the display
|
|
|
|
* server created with intel_create_renderbuffer()) are most similar in their
|
|
|
|
* handling to user-created renderbuffers, but they have a resize handler that
|
|
|
|
* may be called at intel_update_renderbuffers() time.
|
2012-07-11 15:10:49 -07:00
|
|
|
*
|
|
|
|
* \param num_samples must be quantized.
|
2012-07-04 10:52:31 -07:00
|
|
|
*/
|
|
|
|
struct intel_renderbuffer *
|
2012-07-11 15:10:49 -07:00
|
|
|
intel_create_private_renderbuffer(gl_format format, unsigned num_samples)
|
2012-07-04 10:52:31 -07:00
|
|
|
{
|
|
|
|
struct intel_renderbuffer *irb;
|
|
|
|
|
2012-07-11 15:10:49 -07:00
|
|
|
irb = intel_create_renderbuffer(format, num_samples);
|
2012-07-04 10:52:31 -07:00
|
|
|
irb->Base.Base.AllocStorage = intel_alloc_renderbuffer_storage;
|
|
|
|
|
|
|
|
return irb;
|
|
|
|
}
|
|
|
|
|
2007-11-07 10:04:59 -08:00
|
|
|
/**
|
|
|
|
* Create a new renderbuffer object.
|
|
|
|
* Typically called via glBindRenderbufferEXT().
|
|
|
|
*/
|
|
|
|
static struct gl_renderbuffer *
|
2010-10-12 12:26:10 -04:00
|
|
|
intel_new_renderbuffer(struct gl_context * ctx, GLuint name)
|
2007-11-07 10:04:59 -08:00
|
|
|
{
|
|
|
|
/*struct intel_context *intel = intel_context(ctx); */
|
|
|
|
struct intel_renderbuffer *irb;
|
2012-01-16 12:40:01 -07:00
|
|
|
struct gl_renderbuffer *rb;
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
irb = CALLOC_STRUCT(intel_renderbuffer);
|
|
|
|
if (!irb) {
|
|
|
|
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-01-16 12:40:01 -07:00
|
|
|
rb = &irb->Base.Base;
|
|
|
|
|
|
|
|
_mesa_init_renderbuffer(rb, name);
|
|
|
|
rb->ClassID = INTEL_RB_CLASS;
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
/* intel-specific methods */
|
2012-01-16 12:40:01 -07:00
|
|
|
rb->Delete = intel_delete_renderbuffer;
|
|
|
|
rb->AllocStorage = intel_alloc_renderbuffer_storage;
|
2007-11-07 10:04:59 -08:00
|
|
|
/* span routines set in alloc_storage function */
|
|
|
|
|
2012-01-16 12:40:01 -07:00
|
|
|
return rb;
|
2007-11-07 10:04:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called via glBindFramebufferEXT().
|
|
|
|
*/
|
|
|
|
static void
|
2010-10-12 12:26:10 -04:00
|
|
|
intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
|
2007-11-07 10:04:59 -08:00
|
|
|
struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
|
|
|
|
{
|
|
|
|
if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
|
2011-08-26 09:54:40 -07:00
|
|
|
intel_draw_buffer(ctx);
|
2007-11-07 10:04:59 -08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called via glFramebufferRenderbufferEXT().
|
|
|
|
*/
|
|
|
|
static void
|
2010-10-12 12:26:10 -04:00
|
|
|
intel_framebuffer_renderbuffer(struct gl_context * ctx,
|
2007-11-07 10:04:59 -08:00
|
|
|
struct gl_framebuffer *fb,
|
|
|
|
GLenum attachment, struct gl_renderbuffer *rb)
|
|
|
|
{
|
|
|
|
DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
|
|
|
|
|
|
|
|
_mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
|
2011-08-26 09:54:40 -07:00
|
|
|
intel_draw_buffer(ctx);
|
2007-11-07 10:04:59 -08:00
|
|
|
}
|
|
|
|
|
2011-10-07 12:26:50 -07:00
|
|
|
static bool
|
2011-11-15 22:11:33 -08:00
|
|
|
intel_renderbuffer_update_wrapper(struct intel_context *intel,
|
|
|
|
struct intel_renderbuffer *irb,
|
2012-01-19 17:40:41 -08:00
|
|
|
struct gl_texture_image *image,
|
|
|
|
uint32_t layer)
|
2007-11-07 10:04:59 -08:00
|
|
|
{
|
2012-01-16 12:40:01 -07:00
|
|
|
struct gl_renderbuffer *rb = &irb->Base.Base;
|
2012-01-19 17:40:41 -08:00
|
|
|
struct intel_texture_image *intel_image = intel_texture_image(image);
|
|
|
|
struct intel_mipmap_tree *mt = intel_image->mt;
|
|
|
|
int level = image->Level;
|
2011-11-15 22:11:33 -08:00
|
|
|
|
2012-01-19 17:40:41 -08:00
|
|
|
rb->Format = image->TexFormat;
|
|
|
|
rb->InternalFormat = image->InternalFormat;
|
2012-01-19 17:41:39 -08:00
|
|
|
rb->_BaseFormat = image->_BaseFormat;
|
2011-11-15 22:11:33 -08:00
|
|
|
rb->Width = mt->level[level].width;
|
|
|
|
rb->Height = mt->level[level].height;
|
2007-11-07 10:04:59 -08:00
|
|
|
|
2012-01-16 12:40:01 -07:00
|
|
|
rb->Delete = intel_delete_renderbuffer;
|
|
|
|
rb->AllocStorage = intel_nop_alloc_storage;
|
2007-11-07 10:04:59 -08:00
|
|
|
|
2011-11-15 22:11:33 -08:00
|
|
|
intel_miptree_check_level_layer(mt, level, layer);
|
|
|
|
irb->mt_level = level;
|
|
|
|
irb->mt_layer = layer;
|
2011-11-15 10:05:21 -08:00
|
|
|
|
2011-12-07 15:02:02 -08:00
|
|
|
intel_miptree_reference(&irb->mt, mt);
|
2011-11-15 22:51:35 -08:00
|
|
|
|
2011-12-08 08:33:28 -08:00
|
|
|
intel_renderbuffer_set_draw_offset(irb);
|
|
|
|
|
|
|
|
if (mt->hiz_mt == NULL &&
|
|
|
|
intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
|
i965/gen6: Initial implementation of MSAA.
This patch enables MSAA for Gen6, by modifying intel_mipmap_tree to
understand multisampled buffers, adapting the rendering pipeline setup
to enable multisampled rendering, and adding multisample resolve
operations to brw_blorp_blit.cpp. Some preparation work is also
included for Gen7, but it is not yet enabled.
MSAA support is still fairly preliminary. In particular, the
following are not yet supported:
- Fully general blits between MSAA and non-MSAA buffers.
- Formats other than RGBA8, DEPTH24, and STENCIL8.
- Centroid interpolation.
- Coverage parameters (glSampleCoverage, GL_SAMPLE_ALPHA_TO_COVERAGE,
GL_SAMPLE_ALPHA_TO_ONE, GL_SAMPLE_COVERAGE, GL_SAMPLE_COVERAGE_VALUE,
GL_SAMPLE_COVERAGE_INVERT).
Fixes piglit tests "EXT_framebuffer_multisample/accuracy" on
i965/Gen6.
v2:
- In intel_alloc_renderbuffer_storage(), quantize the requested number
of samples to the next higher sample count supported by the
hardware. This ensures that a query of GL_SAMPLES will return the
correct value. It also ensures that MSAA is fully disabled on Gen7
for now (since Gen7 MSAA support doesn't work yet).
- When reading from a non-MSAA surface, ensure that s_is_zero is true
so that we won't try to read from a nonexistent sample.
2012-04-29 21:41:42 -07:00
|
|
|
intel_miptree_alloc_hiz(intel, mt, 0 /* num_samples */);
|
2011-12-08 08:33:28 -08:00
|
|
|
if (!mt->hiz_mt)
|
|
|
|
return false;
|
2011-05-23 13:48:10 -07:00
|
|
|
}
|
2011-11-15 22:11:33 -08:00
|
|
|
|
2011-10-07 12:26:50 -07:00
|
|
|
return true;
|
2008-03-14 11:39:08 +08:00
|
|
|
}
|
|
|
|
|
2011-06-22 10:26:26 -07:00
|
|
|
void
|
2011-11-15 10:22:14 -08:00
|
|
|
intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb)
|
2011-01-10 15:45:28 -08:00
|
|
|
{
|
|
|
|
unsigned int dst_x, dst_y;
|
|
|
|
|
|
|
|
/* compute offset of the particular 2D image within the texture region */
|
2011-11-15 10:22:14 -08:00
|
|
|
intel_miptree_get_image_offset(irb->mt,
|
|
|
|
irb->mt_level,
|
|
|
|
irb->mt_layer,
|
2011-01-10 15:45:28 -08:00
|
|
|
&dst_x, &dst_y);
|
|
|
|
|
2011-05-31 14:27:18 -07:00
|
|
|
irb->draw_x = dst_x;
|
|
|
|
irb->draw_y = dst_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Rendering to tiled buffers requires that the base address of the
|
|
|
|
* buffer be aligned to a page boundary. We generally render to
|
|
|
|
* textures by pointing the surface at the mipmap image level, which
|
|
|
|
* may not be aligned to a tile boundary.
|
|
|
|
*
|
|
|
|
* This function returns an appropriately-aligned base offset
|
|
|
|
* according to the tiling restrictions, plus any required x/y offset
|
|
|
|
* from there.
|
|
|
|
*/
|
|
|
|
uint32_t
|
|
|
|
intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
|
|
|
|
uint32_t *tile_x,
|
|
|
|
uint32_t *tile_y)
|
|
|
|
{
|
2011-11-16 14:04:25 -08:00
|
|
|
struct intel_region *region = irb->mt->region;
|
i965: Fix mipmap offsets for HiZ and separate stencil buffers.
When rendering to a miplevel other than 0 within a color, depth,
stencil, or HiZ buffer, we need to tell the GPU to render to an offset
within the buffer, so that the data is written into the correct
miplevel. We do this using a coarse offset (in pages), and a fine
adjustment (the so-called "tile_x" and "tile_y" values, which are
measured in pixels).
We have always computed the coarse offset and fine adjustment using
intel_renderbuffer_tile_offsets() function. This worked fine for
color and combined depth/stencil buffers, but failed to work properly
when HiZ and separate stencil were in use. It failed to work because
there is only one set of fine adjustment controls shared by the HiZ,
depth, and stencil buffers, so we need to choose tile_x and tile_y
values that are compatible with the tiling of all three buffers, and
then compute separate coarse offsets for each buffer.
This patch fixes the HiZ and separate stencil case by replacing the
call to intel_renderbuffer_tile_offsets() with calls to two functions:
intel_region_get_tile_masks(), which determines how much of the
adjustment can be performed using offsets and how much can be
performed using tile_x and tile_y, and
intel_region_get_aligned_offset(), which computes the coarse offset.
intel_region_get_tile_offsets() is still used for color renderbuffers,
so to avoid code duplication, I've re-worked it to use
intel_region_get_tile_masks() and intel_region_get_aligned_offset().
On i965 Gen6, fixes piglit tests
"texturing/depthstencil-render-miplevels 1024 X" where X is one of
(depth, depth_and_stencil, depth_stencil_single_binding, depth_x,
depth_x_and_stencil, stencil, stencil_and_depth, stencil_and_depth_x).
On i965 Gen7, the variants of
"texturing/depthstencil-render-miplevels" that contain a stencil
buffer still fail, due to another problem: Gen7 seems to ignore the 3
LSB's of the tile_y adjustment (and possibly also tile_x).
v2: Removed spurious comments. Added assertions to check
preconditions of intel_region_get_aligned_offset().
Reviewed-by: Chad Versace <chad.versace@linux.intel.com>
Acked-by: Kenneth Graunke <kenneth@whitecape.org>
2012-04-15 10:35:01 -07:00
|
|
|
uint32_t mask_x, mask_y;
|
|
|
|
|
2012-08-30 10:57:03 -07:00
|
|
|
intel_region_get_tile_masks(region, &mask_x, &mask_y, false);
|
i965: Fix mipmap offsets for HiZ and separate stencil buffers.
When rendering to a miplevel other than 0 within a color, depth,
stencil, or HiZ buffer, we need to tell the GPU to render to an offset
within the buffer, so that the data is written into the correct
miplevel. We do this using a coarse offset (in pages), and a fine
adjustment (the so-called "tile_x" and "tile_y" values, which are
measured in pixels).
We have always computed the coarse offset and fine adjustment using
intel_renderbuffer_tile_offsets() function. This worked fine for
color and combined depth/stencil buffers, but failed to work properly
when HiZ and separate stencil were in use. It failed to work because
there is only one set of fine adjustment controls shared by the HiZ,
depth, and stencil buffers, so we need to choose tile_x and tile_y
values that are compatible with the tiling of all three buffers, and
then compute separate coarse offsets for each buffer.
This patch fixes the HiZ and separate stencil case by replacing the
call to intel_renderbuffer_tile_offsets() with calls to two functions:
intel_region_get_tile_masks(), which determines how much of the
adjustment can be performed using offsets and how much can be
performed using tile_x and tile_y, and
intel_region_get_aligned_offset(), which computes the coarse offset.
intel_region_get_tile_offsets() is still used for color renderbuffers,
so to avoid code duplication, I've re-worked it to use
intel_region_get_tile_masks() and intel_region_get_aligned_offset().
On i965 Gen6, fixes piglit tests
"texturing/depthstencil-render-miplevels 1024 X" where X is one of
(depth, depth_and_stencil, depth_stencil_single_binding, depth_x,
depth_x_and_stencil, stencil, stencil_and_depth, stencil_and_depth_x).
On i965 Gen7, the variants of
"texturing/depthstencil-render-miplevels" that contain a stencil
buffer still fail, due to another problem: Gen7 seems to ignore the 3
LSB's of the tile_y adjustment (and possibly also tile_x).
v2: Removed spurious comments. Added assertions to check
preconditions of intel_region_get_aligned_offset().
Reviewed-by: Chad Versace <chad.versace@linux.intel.com>
Acked-by: Kenneth Graunke <kenneth@whitecape.org>
2012-04-15 10:35:01 -07:00
|
|
|
|
|
|
|
*tile_x = irb->draw_x & mask_x;
|
|
|
|
*tile_y = irb->draw_y & mask_y;
|
|
|
|
return intel_region_get_aligned_offset(region, irb->draw_x & ~mask_x,
|
2012-08-30 11:16:44 -07:00
|
|
|
irb->draw_y & ~mask_y, false);
|
2011-01-10 15:45:28 -08:00
|
|
|
}
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called by glFramebufferTexture[123]DEXT() (and other places) to
|
|
|
|
* prepare for rendering into texture memory. This might be called
|
|
|
|
* many times to choose different texture levels, cube faces, etc
|
|
|
|
* before intel_finish_render_texture() is ever called.
|
|
|
|
*/
|
|
|
|
static void
|
2010-10-12 12:26:10 -04:00
|
|
|
intel_render_texture(struct gl_context * ctx,
|
2007-11-07 10:04:59 -08:00
|
|
|
struct gl_framebuffer *fb,
|
|
|
|
struct gl_renderbuffer_attachment *att)
|
|
|
|
{
|
2011-11-15 22:11:33 -08:00
|
|
|
struct intel_context *intel = intel_context(ctx);
|
2011-05-31 15:07:56 -07:00
|
|
|
struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
|
2007-11-07 10:04:59 -08:00
|
|
|
struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
|
2011-05-31 15:07:56 -07:00
|
|
|
struct intel_texture_image *intel_image = intel_texture_image(image);
|
2011-11-15 22:11:33 -08:00
|
|
|
struct intel_mipmap_tree *mt = intel_image->mt;
|
2012-01-12 11:41:42 -07:00
|
|
|
int layer;
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
(void) fb;
|
|
|
|
|
2011-11-15 22:11:33 -08:00
|
|
|
if (att->CubeMapFace > 0) {
|
|
|
|
assert(att->Zoffset == 0);
|
|
|
|
layer = att->CubeMapFace;
|
|
|
|
} else {
|
|
|
|
layer = att->Zoffset;
|
|
|
|
}
|
|
|
|
|
2009-05-20 14:16:34 -07:00
|
|
|
if (!intel_image->mt) {
|
|
|
|
/* Fallback on drawing to a texture that doesn't have a miptree
|
|
|
|
* (has a border, width/height 0, etc.)
|
2008-12-06 15:47:23 -08:00
|
|
|
*/
|
2009-01-29 14:57:31 -07:00
|
|
|
_mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
|
2011-06-13 13:44:35 -06:00
|
|
|
_swrast_render_texture(ctx, fb, att);
|
2009-01-29 14:57:31 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (!irb) {
|
2012-01-19 17:32:55 -08:00
|
|
|
intel_miptree_check_level_layer(mt, att->TextureLevel, layer);
|
|
|
|
|
|
|
|
irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0);
|
2011-11-15 22:11:33 -08:00
|
|
|
|
2007-11-07 10:04:59 -08:00
|
|
|
if (irb) {
|
|
|
|
/* bind the wrapper to the attachment point */
|
2012-01-16 12:40:01 -07:00
|
|
|
_mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base);
|
2007-11-07 10:04:59 -08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* fallback to software rendering */
|
2011-06-13 13:44:35 -06:00
|
|
|
_swrast_render_texture(ctx, fb, att);
|
2007-11-07 10:04:59 -08:00
|
|
|
return;
|
|
|
|
}
|
2009-01-29 14:57:31 -07:00
|
|
|
}
|
|
|
|
|
2012-01-19 17:40:41 -08:00
|
|
|
if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) {
|
2008-03-14 11:39:08 +08:00
|
|
|
_mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
|
2011-06-13 13:44:35 -06:00
|
|
|
_swrast_render_texture(ctx, fb, att);
|
2008-03-14 11:39:08 +08:00
|
|
|
return;
|
2007-11-07 10:04:59 -08:00
|
|
|
}
|
|
|
|
|
2012-02-10 12:54:25 -08:00
|
|
|
irb->tex_image = image;
|
|
|
|
|
2011-11-15 12:53:18 -08:00
|
|
|
DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n",
|
|
|
|
_mesa_get_format_name(image->TexFormat),
|
2011-05-31 15:07:56 -07:00
|
|
|
att->Texture->Name, image->Width, image->Height,
|
2012-01-16 12:40:01 -07:00
|
|
|
irb->Base.Base.RefCount);
|
2007-11-07 10:04:59 -08:00
|
|
|
|
|
|
|
/* update drawing region, etc */
|
2011-08-26 09:54:40 -07:00
|
|
|
intel_draw_buffer(ctx);
|
2007-11-07 10:04:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called by Mesa when rendering to a texture is done.
|
|
|
|
*/
|
|
|
|
static void
|
2010-10-12 12:26:10 -04:00
|
|
|
intel_finish_render_texture(struct gl_context * ctx,
|
2007-11-07 10:04:59 -08:00
|
|
|
struct gl_renderbuffer_attachment *att)
|
|
|
|
{
|
2009-12-09 11:36:45 -08:00
|
|
|
struct intel_context *intel = intel_context(ctx);
|
2009-11-04 14:54:09 -08:00
|
|
|
struct gl_texture_object *tex_obj = att->Texture;
|
|
|
|
struct gl_texture_image *image =
|
|
|
|
tex_obj->Image[att->CubeMapFace][att->TextureLevel];
|
2012-02-10 12:54:25 -08:00
|
|
|
struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
|
2010-09-24 11:20:16 -07:00
|
|
|
|
2011-11-15 12:53:18 -08:00
|
|
|
DBG("Finish render %s texture tex=%u\n",
|
|
|
|
_mesa_get_format_name(image->TexFormat), att->Texture->Name);
|
2009-11-04 14:54:09 -08:00
|
|
|
|
2012-02-10 12:54:25 -08:00
|
|
|
if (irb)
|
|
|
|
irb->tex_image = NULL;
|
2007-11-07 10:04:59 -08:00
|
|
|
|
2009-12-09 11:36:45 -08:00
|
|
|
/* Since we've (probably) rendered to the texture and will (likely) use
|
|
|
|
* it in the texture domain later on in this batchbuffer, flush the
|
|
|
|
* batch. Once again, we wish for a domain tracker in libdrm to cover
|
|
|
|
* usage inside of a batchbuffer like GEM does in the kernel.
|
|
|
|
*/
|
2011-02-10 20:25:51 +00:00
|
|
|
intel_batchbuffer_emit_mi_flush(intel);
|
2009-12-09 11:36:45 -08:00
|
|
|
}
|
2007-11-07 10:04:59 -08:00
|
|
|
|
2009-01-20 15:30:22 -07:00
|
|
|
/**
|
|
|
|
* Do additional "completeness" testing of a framebuffer object.
|
|
|
|
*/
|
|
|
|
static void
|
2010-10-12 12:26:10 -04:00
|
|
|
intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
|
2009-01-20 15:30:22 -07:00
|
|
|
{
|
2011-01-07 15:45:33 -08:00
|
|
|
struct intel_context *intel = intel_context(ctx);
|
2009-01-22 15:32:38 -07:00
|
|
|
const struct intel_renderbuffer *depthRb =
|
|
|
|
intel_get_renderbuffer(fb, BUFFER_DEPTH);
|
|
|
|
const struct intel_renderbuffer *stencilRb =
|
|
|
|
intel_get_renderbuffer(fb, BUFFER_STENCIL);
|
2011-12-07 17:51:14 -08:00
|
|
|
struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL;
|
2009-04-09 18:30:12 -07:00
|
|
|
int i;
|
2009-01-22 15:32:38 -07:00
|
|
|
|
2012-02-10 12:24:50 -08:00
|
|
|
DBG("%s() on fb %p (%s)\n", __FUNCTION__,
|
|
|
|
fb, (fb == ctx->DrawBuffer ? "drawbuffer" :
|
|
|
|
(fb == ctx->ReadBuffer ? "readbuffer" : "other buffer")));
|
|
|
|
|
2011-12-07 17:51:14 -08:00
|
|
|
if (depthRb)
|
|
|
|
depth_mt = depthRb->mt;
|
2011-12-07 15:02:02 -08:00
|
|
|
if (stencilRb) {
|
2011-12-07 17:51:14 -08:00
|
|
|
stencil_mt = stencilRb->mt;
|
2011-12-07 15:02:02 -08:00
|
|
|
if (stencil_mt->stencil_mt)
|
|
|
|
stencil_mt = stencil_mt->stencil_mt;
|
|
|
|
}
|
2011-12-07 17:51:14 -08:00
|
|
|
|
|
|
|
if (depth_mt && stencil_mt) {
|
|
|
|
if (depth_mt == stencil_mt) {
|
|
|
|
/* For true packed depth/stencil (not faked on prefers-separate-stencil
|
|
|
|
* hardware) we need to be sure they're the same level/layer, since
|
|
|
|
* we'll be emitting a single packet describing the packed setup.
|
|
|
|
*/
|
|
|
|
if (depthRb->mt_level != stencilRb->mt_level ||
|
|
|
|
depthRb->mt_layer != stencilRb->mt_layer) {
|
2012-02-10 12:24:50 -08:00
|
|
|
DBG("depth image level/layer %d/%d != stencil image %d/%d\n",
|
|
|
|
depthRb->mt_level,
|
|
|
|
depthRb->mt_layer,
|
|
|
|
stencilRb->mt_level,
|
|
|
|
stencilRb->mt_layer);
|
2011-12-07 17:51:14 -08:00
|
|
|
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
|
|
|
|
}
|
|
|
|
} else {
|
2012-02-10 12:24:50 -08:00
|
|
|
if (!intel->has_separate_stencil) {
|
|
|
|
DBG("separate stencil unsupported\n");
|
2011-12-07 17:51:14 -08:00
|
|
|
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
|
2012-02-10 12:24:50 -08:00
|
|
|
}
|
|
|
|
if (stencil_mt->format != MESA_FORMAT_S8) {
|
|
|
|
DBG("separate stencil is %s instead of S8\n",
|
|
|
|
_mesa_get_format_name(stencil_mt->format));
|
2011-12-07 17:51:14 -08:00
|
|
|
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
|
2012-02-10 12:24:50 -08:00
|
|
|
}
|
2012-01-19 13:08:48 -08:00
|
|
|
if (intel->gen < 7 && depth_mt->hiz_mt == NULL) {
|
|
|
|
/* Before Gen7, separate depth and stencil buffers can be used
|
|
|
|
* only if HiZ is enabled. From the Sandybridge PRM, Volume 2,
|
|
|
|
* Part 1, Bit 3DSTATE_DEPTH_BUFFER.SeparateStencilBufferEnable:
|
|
|
|
* [DevSNB]: This field must be set to the same value (enabled
|
|
|
|
* or disabled) as Hierarchical Depth Buffer Enable.
|
|
|
|
*/
|
2012-02-10 12:24:50 -08:00
|
|
|
DBG("separate stencil without HiZ\n");
|
2012-01-19 13:08:48 -08:00
|
|
|
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
|
|
|
|
}
|
2011-07-12 10:01:32 -07:00
|
|
|
}
|
2009-01-22 15:32:38 -07:00
|
|
|
}
|
2009-02-26 16:51:50 -07:00
|
|
|
|
2011-01-04 09:57:21 -08:00
|
|
|
for (i = 0; i < Elements(fb->Attachment); i++) {
|
|
|
|
struct gl_renderbuffer *rb;
|
|
|
|
struct intel_renderbuffer *irb;
|
2009-04-09 18:30:12 -07:00
|
|
|
|
2011-01-04 09:57:21 -08:00
|
|
|
if (fb->Attachment[i].Type == GL_NONE)
|
2009-04-09 18:30:12 -07:00
|
|
|
continue;
|
|
|
|
|
2011-01-04 09:57:21 -08:00
|
|
|
/* A supported attachment will have a Renderbuffer set either
|
|
|
|
* from being a Renderbuffer or being a texture that got the
|
|
|
|
* intel_wrap_texture() treatment.
|
|
|
|
*/
|
|
|
|
rb = fb->Attachment[i].Renderbuffer;
|
|
|
|
if (rb == NULL) {
|
|
|
|
DBG("attachment without renderbuffer\n");
|
|
|
|
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
intel: FBOs with texture border are unsupported
FBOs differ from textures in a significant way. With textures, we can
strip the border and get correct rendering except when the application
fetches texels outside [0,1].
With an FBO, the pixel at (0,0) is in the border. The
ARB_framebuffer_object spec says:
"If the attached image is a texture image, then the window
coordinates (x[w], y[w]) correspond to the texel (i, j, k), from
figure 3.10 as follows:
i = (x[w] - b)
j = (y[w] - b)
k = (layer - b)
where <b> is the texture image's border width..."
Since the border doesn't exist, we can never render any pixels in the
correct location. Just mark these FBOs FRAMEBUFFER_UNSUPPORTED.
NOTE: This is a candidate for the 8.0 branch.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=42336
2012-02-01 10:18:13 -07:00
|
|
|
if (fb->Attachment[i].Type == GL_TEXTURE) {
|
|
|
|
const struct gl_texture_image *img =
|
|
|
|
_mesa_get_attachment_teximage_const(&fb->Attachment[i]);
|
|
|
|
|
|
|
|
if (img->Border) {
|
|
|
|
DBG("texture with border\n");
|
|
|
|
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-04 09:57:21 -08:00
|
|
|
irb = intel_renderbuffer(rb);
|
2009-05-20 14:05:03 -07:00
|
|
|
if (irb == NULL) {
|
2009-12-28 14:38:43 -08:00
|
|
|
DBG("software rendering renderbuffer\n");
|
2009-05-20 14:05:03 -07:00
|
|
|
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-01-19 17:23:25 -08:00
|
|
|
if (!intel->vtbl.render_target_supported(intel, rb)) {
|
2011-11-15 12:15:37 -08:00
|
|
|
DBG("Unsupported HW texture/renderbuffer format attached: %s\n",
|
2012-01-16 12:29:11 -07:00
|
|
|
_mesa_get_format_name(intel_rb_format(irb)));
|
2009-04-09 18:30:12 -07:00
|
|
|
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
|
2009-02-26 16:51:50 -07:00
|
|
|
}
|
|
|
|
}
|
2009-01-20 15:30:22 -07:00
|
|
|
}
|
|
|
|
|
2011-02-05 10:21:11 +00:00
|
|
|
/**
|
|
|
|
* Try to do a glBlitFramebuffer using glCopyTexSubImage2D
|
|
|
|
* We can do this when the dst renderbuffer is actually a texture and
|
|
|
|
* there is no scaling, mirroring or scissoring.
|
|
|
|
*
|
|
|
|
* \return new buffer mask indicating the buffers left to blit using the
|
|
|
|
* normal path.
|
|
|
|
*/
|
|
|
|
static GLbitfield
|
|
|
|
intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
|
|
|
|
GLint srcX0, GLint srcY0,
|
|
|
|
GLint srcX1, GLint srcY1,
|
|
|
|
GLint dstX0, GLint dstY0,
|
|
|
|
GLint dstX1, GLint dstY1,
|
|
|
|
GLbitfield mask, GLenum filter)
|
|
|
|
{
|
|
|
|
if (mask & GL_COLOR_BUFFER_BIT) {
|
|
|
|
const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
|
|
|
|
const struct gl_framebuffer *readFb = ctx->ReadBuffer;
|
|
|
|
const struct gl_renderbuffer_attachment *drawAtt =
|
|
|
|
&drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
|
2011-12-29 06:36:55 -07:00
|
|
|
struct intel_renderbuffer *srcRb =
|
|
|
|
intel_renderbuffer(readFb->_ColorReadBuffer);
|
2011-02-05 10:21:11 +00:00
|
|
|
|
|
|
|
/* If the source and destination are the same size with no
|
|
|
|
mirroring, the rectangles are within the size of the
|
|
|
|
texture and there is no scissor then we can use
|
|
|
|
glCopyTexSubimage2D to implement the blit. This will end
|
|
|
|
up as a fast hardware blit on some drivers */
|
2011-12-29 06:36:55 -07:00
|
|
|
if (srcRb && drawAtt && drawAtt->Texture &&
|
2011-02-05 10:21:11 +00:00
|
|
|
srcX0 - srcX1 == dstX0 - dstX1 &&
|
|
|
|
srcY0 - srcY1 == dstY0 - dstY1 &&
|
|
|
|
srcX1 >= srcX0 &&
|
|
|
|
srcY1 >= srcY0 &&
|
|
|
|
srcX0 >= 0 && srcX1 <= readFb->Width &&
|
|
|
|
srcY0 >= 0 && srcY1 <= readFb->Height &&
|
|
|
|
dstX0 >= 0 && dstX1 <= drawFb->Width &&
|
|
|
|
dstY0 >= 0 && dstY1 <= drawFb->Height &&
|
|
|
|
!ctx->Scissor.Enabled) {
|
|
|
|
const struct gl_texture_object *texObj = drawAtt->Texture;
|
|
|
|
const GLuint dstLevel = drawAtt->TextureLevel;
|
|
|
|
const GLenum target = texObj->Target;
|
|
|
|
|
|
|
|
struct gl_texture_image *texImage =
|
|
|
|
_mesa_select_tex_image(ctx, texObj, target, dstLevel);
|
|
|
|
|
2011-08-26 10:03:26 -07:00
|
|
|
if (intel_copy_texsubimage(intel_context(ctx),
|
2011-02-05 10:21:11 +00:00
|
|
|
intel_texture_image(texImage),
|
|
|
|
dstX0, dstY0,
|
2011-12-29 06:36:55 -07:00
|
|
|
srcRb,
|
2011-02-05 10:21:11 +00:00
|
|
|
srcX0, srcY0,
|
|
|
|
srcX1 - srcX0, /* width */
|
|
|
|
srcY1 - srcY0))
|
|
|
|
mask &= ~GL_COLOR_BUFFER_BIT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
intel_blit_framebuffer(struct gl_context *ctx,
|
|
|
|
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
|
|
|
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
|
|
|
GLbitfield mask, GLenum filter)
|
|
|
|
{
|
|
|
|
/* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
|
|
|
|
mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
|
|
|
|
srcX0, srcY0, srcX1, srcY1,
|
|
|
|
dstX0, dstY0, dstX1, dstY1,
|
|
|
|
mask, filter);
|
|
|
|
if (mask == 0x0)
|
|
|
|
return;
|
|
|
|
|
i965/gen6+: Add code to perform blits on the render path ("blorp").
This patch expands the "blorp" component to be able to perform blits
as well as HiZ resolves. The new blitting code is located in
brw_blorp_blit.cpp. This includes the necessary fragment shader code
to look up pixels in the source buffer (which is configured as a
texture) and output them to the destination buffer (which is
configured as the render target).
Most of the time the fragment shader code is simple and
straightforward, since it merely has to apply a coordinate offset,
read from the texture, and write to the render target. However, in
the case of blitting stencil buffers, things are more complicated,
since the GPU stores stencil data using W tiling, and W tiling is not
supported for textures or render targets. So, we set up the stencil
buffers as Y tiled, and emit fragment shader code that adjusts the
coordinates to account for the difference between W and Y tiling.
Furthermore, since a rectangular region in W tiling does not
necessarily correspond to a rectangular region in Y tiling, we widen
the rectangle primitive to the nearest tile boundary and have the
fragment shader "kill" any pixels that don't fall inside the actual
desired destination rectangle.
All of this is a necessary prerequisite for implementing MSAA, since
we'll need to be able to blit between multisample color, depth, and
stencil buffers and their non-multisampled counterparts, and none of
the existing blitting mechanisms support multisampling.
In addition, the new blitting code should speed up operations where we
previously fell back to software rasterization, such as blitting of
stencil buffers. The current fallback sequence is: first we try to do
a blit using the hardware blitting engine. If that fails we try to do
a blit using the render path. If that also fails then we do the blit
using a meta-op (which may or may not fall back to software
rasterization).
Note that blitting using the render path has some limitations at the
moment: it only supports a few formats, and it doesn't support
clipping or scissoring. These limitations will be addressed in future
patch series.
v2:
- Add the code that configures the WM program to
gen{6,7}_emit_wm_config() and gen7_emit_ps_config() rather than
creating separate ...enable() functions.
- Call intel_prepare_render before determining which miptrees we are
blitting from/to, because it may cause miptrees to be reallocated.
- Allow the blit to mirror X and/or Y coordinates.
- Disable blorp blits on Gen7 for now, since they aren't working yet.
2012-04-29 22:44:25 -07:00
|
|
|
#ifndef I915
|
|
|
|
mask = brw_blorp_framebuffer(intel_context(ctx),
|
|
|
|
srcX0, srcY0, srcX1, srcY1,
|
|
|
|
dstX0, dstY0, dstX1, dstY1,
|
|
|
|
mask, filter);
|
|
|
|
if (mask == 0x0)
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
2011-02-05 10:21:11 +00:00
|
|
|
_mesa_meta_BlitFramebuffer(ctx,
|
|
|
|
srcX0, srcY0, srcX1, srcY1,
|
|
|
|
dstX0, dstY0, dstX1, dstY1,
|
|
|
|
mask, filter);
|
|
|
|
}
|
2009-01-20 15:30:22 -07:00
|
|
|
|
2012-07-26 16:47:35 -07:00
|
|
|
/**
|
|
|
|
* This is a no-op except on multisample buffers shared with DRI2.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
intel_renderbuffer_set_needs_downsample(struct intel_renderbuffer *irb)
|
|
|
|
{
|
|
|
|
if (irb->mt && irb->mt->singlesample_mt)
|
|
|
|
irb->mt->need_downsample = true;
|
|
|
|
}
|
|
|
|
|
2011-11-17 08:03:48 -08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-08-08 09:29:46 -07:00
|
|
|
void
|
|
|
|
intel_renderbuffer_move_to_temp(struct intel_context *intel,
|
|
|
|
struct intel_renderbuffer *irb)
|
|
|
|
{
|
|
|
|
struct intel_texture_image *intel_image =
|
|
|
|
intel_texture_image(irb->tex_image);
|
|
|
|
struct intel_mipmap_tree *new_mt;
|
|
|
|
int width, height, depth;
|
|
|
|
|
|
|
|
intel_miptree_get_dimensions_for_image(irb->tex_image, &width, &height, &depth);
|
|
|
|
|
|
|
|
new_mt = intel_miptree_create(intel, irb->tex_image->TexObject->Target,
|
|
|
|
intel_image->base.Base.TexFormat,
|
|
|
|
intel_image->base.Base.Level,
|
|
|
|
intel_image->base.Base.Level,
|
|
|
|
width, height, depth,
|
|
|
|
true,
|
|
|
|
irb->mt->num_samples,
|
|
|
|
irb->mt->msaa_layout);
|
|
|
|
|
|
|
|
intel_miptree_copy_teximage(intel, intel_image, new_mt);
|
|
|
|
intel_miptree_reference(&irb->mt, intel_image->mt);
|
|
|
|
intel_renderbuffer_set_draw_offset(irb);
|
|
|
|
intel_miptree_release(&new_mt);
|
|
|
|
}
|
|
|
|
|
2007-11-07 10:04:59 -08:00
|
|
|
/**
|
|
|
|
* Do one-time context initializations related to GL_EXT_framebuffer_object.
|
|
|
|
* Hook in device driver functions.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
intel_fbo_init(struct intel_context *intel)
|
|
|
|
{
|
|
|
|
intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
|
|
|
|
intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
|
2011-10-11 14:22:45 -07:00
|
|
|
intel->ctx.Driver.MapRenderbuffer = intel_map_renderbuffer;
|
|
|
|
intel->ctx.Driver.UnmapRenderbuffer = intel_unmap_renderbuffer;
|
2007-11-07 10:04:59 -08:00
|
|
|
intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
|
|
|
|
intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
|
|
|
|
intel->ctx.Driver.RenderTexture = intel_render_texture;
|
|
|
|
intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
|
|
|
|
intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
|
2009-01-20 15:30:22 -07:00
|
|
|
intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
|
2011-02-05 10:21:11 +00:00
|
|
|
intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
|
2010-02-11 19:04:02 -05:00
|
|
|
intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
|
|
|
|
intel_image_target_renderbuffer_storage;
|
2007-11-07 10:04:59 -08:00
|
|
|
}
|