static void
intel_delete_renderbuffer(struct gl_renderbuffer *rb)
{
- GET_CURRENT_CONTEXT(ctx);
- struct intel_context *intel = intel_context(ctx);
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
ASSERT(irb);
- if (intel && irb->region) {
- intel_region_release(&irb->region);
- }
- if (intel && irb->hiz_region) {
- intel_region_release(&irb->hiz_region);
- }
- if (intel && irb->wrapped_depth) {
- _mesa_reference_renderbuffer(&irb->wrapped_depth, NULL);
- }
- if (intel && irb->wrapped_stencil) {
- _mesa_reference_renderbuffer(&irb->wrapped_stencil, NULL);
- }
+ intel_region_release(&irb->region);
+ intel_region_release(&irb->hiz_region);
+
+ _mesa_reference_renderbuffer(&irb->wrapped_depth, NULL);
+ _mesa_reference_renderbuffer(&irb->wrapped_stencil, NULL);
free(irb);
}
}
-static struct gl_renderbuffer*
-intel_create_wrapped_renderbuffer(struct gl_context * ctx,
- struct gl_renderbuffer *wrapper,
- gl_format format);
-
-
/**
* Called via glRenderbufferStorageEXT() to set the format and allocate
* storage for a user-created renderbuffer.
*/
-static GLboolean
+GLboolean
intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
GLenum internalFormat,
GLuint width, GLuint height)
if (irb->Base.Format == MESA_FORMAT_S8) {
/*
+ * The stencil buffer is W tiled. However, we request from the kernel a
+ * non-tiled buffer because the GTT is incapable of W fencing.
+ *
* The stencil buffer has quirky pitch requirements. From Vol 2a,
* 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
* The pitch must be set to 2x the value computed based on width, as
* To accomplish this, we resort to the nasty hack of doubling the drm
* region's cpp and halving its height.
*
- * If we neglect to double the pitch, then drm_intel_gem_bo_map_gtt()
- * maps the memory incorrectly.
+ * If we neglect to double the pitch, then render corruption occurs.
*/
irb->region = intel_region_alloc(intel->intelScreen,
- I915_TILING_Y,
+ I915_TILING_NONE,
cpp * 2,
- width,
- height / 2,
- GL_TRUE);
+ ALIGN(width, 64),
+ ALIGN((height + 1) / 2, 64),
+ true);
if (!irb->region)
return false;
struct gl_renderbuffer *depth_rb;
struct gl_renderbuffer *stencil_rb;
- depth_rb = intel_create_wrapped_renderbuffer(ctx, rb,
+ depth_rb = intel_create_wrapped_renderbuffer(ctx, width, height,
MESA_FORMAT_X8_Z24);
- stencil_rb = intel_create_wrapped_renderbuffer(ctx, rb,
+ stencil_rb = intel_create_wrapped_renderbuffer(ctx, width, height,
MESA_FORMAT_S8);
ok = depth_rb && stencil_rb;
ok = ok && intel_alloc_renderbuffer_storage(ctx, depth_rb,
return false;
}
+ depth_rb->Wrapped = rb;
+ stencil_rb->Wrapped = rb;
_mesa_reference_renderbuffer(&irb->wrapped_depth, depth_rb);
_mesa_reference_renderbuffer(&irb->wrapped_stencil, stencil_rb);
} else {
irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp,
- width, height, GL_TRUE);
+ width, height, true);
if (!irb->region)
return false;
irb->region->cpp,
irb->region->width,
irb->region->height,
- GL_TRUE);
+ true);
if (!irb->hiz_region) {
intel_region_release(&irb->region);
return false;
}
}
- return GL_TRUE;
+ return true;
}
if (image == NULL)
return;
+ /* __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;
+ }
+
irb = intel_renderbuffer(rb);
- if (irb->region)
- intel_region_release(&irb->region);
intel_region_reference(&irb->region, image->region);
rb->InternalFormat = image->internal_format;
rb->Height = height;
rb->InternalFormat = internalFormat;
- return GL_TRUE;
+ return true;
}
_mesa_resize_framebuffer(ctx, fb, width, height);
- fb->Initialized = GL_TRUE; /* XXX remove someday */
+ fb->Initialized = true; /* XXX remove someday */
if (fb->Name != 0) {
return;
GLenum internalFormat, GLuint width, GLuint height)
{
_mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
- return GL_FALSE;
-}
-
-
-void
-intel_renderbuffer_set_region(struct intel_context *intel,
- struct intel_renderbuffer *rb,
- struct intel_region *region)
-{
- struct intel_region *old;
-
- old = rb->region;
- rb->region = NULL;
- intel_region_reference(&rb->region, region);
- intel_region_release(&old);
+ return false;
}
-
-void
-intel_renderbuffer_set_hiz_region(struct intel_context *intel,
- struct intel_renderbuffer *rb,
- struct intel_region *region)
-{
- struct intel_region *old = rb->hiz_region;
- rb->hiz_region = NULL;
- intel_region_reference(&rb->hiz_region, region);
- intel_region_release(&old);
-}
-
-
/**
* Create a new intel_renderbuffer which corresponds to an on-screen window,
* not a user-created renderbuffer.
}
-static struct gl_renderbuffer *
+struct gl_renderbuffer*
intel_create_wrapped_renderbuffer(struct gl_context * ctx,
- struct gl_renderbuffer *wrapper,
+ int width, int height,
gl_format format)
{
/*
rb->Format = format;
rb->InternalFormat = rb->_BaseFormat;
rb->DataType = intel_mesa_format_to_rb_datatype(format);
- rb->Width = wrapper->Width;
- rb->Height = wrapper->Height;
-
- rb->AllocStorage = intel_nop_alloc_storage;
- rb->Delete = intel_delete_renderbuffer;
- rb->GetPointer = intel_get_pointer;
-
- /*
- * A refcount here would cause a cyclic reference. The wrapper references
- * the unwrapper.
- */
- rb->Wrapped = wrapper;
+ rb->Width = width;
+ rb->Height = height;
return rb;
}
struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
{
if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
- intel_draw_buffer(ctx, fb);
+ intel_draw_buffer(ctx);
}
else {
/* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
intel_flush(ctx);
_mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
- intel_draw_buffer(ctx, fb);
+ intel_draw_buffer(ctx);
}
+static bool
+intel_update_tex_wrapper_regions(struct intel_context *intel,
+ struct intel_renderbuffer *irb,
+ struct intel_texture_image *intel_image);
-static GLboolean
+static bool
intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb,
struct gl_texture_image *texImage)
{
struct intel_context *intel = intel_context(ctx);
struct intel_texture_image *intel_image = intel_texture_image(texImage);
+ int width, height, depth;
if (!intel_span_supports_format(texImage->TexFormat)) {
DBG("Render to texture BAD FORMAT %s\n",
_mesa_get_format_name(texImage->TexFormat));
- return GL_FALSE;
+ return false;
} else {
DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat));
}
+ intel_miptree_get_dimensions_for_image(texImage, &width, &height, &depth);
+
irb->Base.Format = texImage->TexFormat;
irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat);
irb->Base.InternalFormat = texImage->InternalFormat;
irb->Base._BaseFormat = _mesa_base_tex_format(ctx, irb->Base.InternalFormat);
- irb->Base.Width = texImage->Width;
- irb->Base.Height = texImage->Height;
+ irb->Base.Width = width;
+ irb->Base.Height = height;
irb->Base.Delete = intel_delete_renderbuffer;
irb->Base.AllocStorage = intel_nop_alloc_storage;
+ if (intel_image->stencil_rb) {
+ /* The tex image has packed depth/stencil format, but is using separate
+ * stencil. */
+
+ bool ok;
+ struct intel_renderbuffer *depth_irb =
+ intel_renderbuffer(intel_image->depth_rb);
+
+ /* Update the hiz region if necessary. */
+ ok = intel_update_tex_wrapper_regions(intel, depth_irb, intel_image);
+ if (!ok) {
+ return false;
+ }
+
+ /* The tex image shares its embedded depth and stencil renderbuffers with
+ * the renderbuffer wrapper. */
+ _mesa_reference_renderbuffer(&irb->wrapped_depth,
+ intel_image->depth_rb);
+ _mesa_reference_renderbuffer(&irb->wrapped_stencil,
+ intel_image->stencil_rb);
+
+ return true;
+ } else {
+ return intel_update_tex_wrapper_regions(intel, irb, intel_image);
+ }
+}
+
+/**
+ * FIXME: The handling of the hiz region is broken for mipmapped depth textures
+ * FIXME: because intel_finalize_mipmap_tree is unaware of it.
+ */
+static bool
+intel_update_tex_wrapper_regions(struct intel_context *intel,
+ struct intel_renderbuffer *irb,
+ struct intel_texture_image *intel_image)
+{
+ struct gl_renderbuffer *rb = &irb->Base;
+
/* Point the renderbuffer's region to the texture's region. */
if (irb->region != intel_image->mt->region) {
- intel_region_release(&irb->region);
intel_region_reference(&irb->region, intel_image->mt->region);
}
/* Allocate the texture's hiz region if necessary. */
- if (intel->vtbl.is_hiz_depth_format(intel, texImage->TexFormat)
+ if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)
&& !intel_image->mt->hiz_region) {
intel_image->mt->hiz_region =
intel_region_alloc(intel->intelScreen,
I915_TILING_Y,
- _mesa_get_format_bytes(texImage->TexFormat),
- texImage->Width,
- texImage->Height,
- GL_TRUE);
+ _mesa_get_format_bytes(rb->Format),
+ rb->Width,
+ rb->Height,
+ true);
if (!intel_image->mt->hiz_region)
- return GL_FALSE;
+ return false;
}
/* Point the renderbuffer's hiz region to the texture's hiz region. */
if (irb->hiz_region != intel_image->mt->hiz_region) {
- intel_region_release(&irb->hiz_region);
intel_region_reference(&irb->hiz_region, intel_image->mt->hiz_region);
}
- return GL_TRUE;
+ return true;
}
return irb;
}
-static void
+void
intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb,
struct intel_texture_image *intel_image,
int zoffset)
{
- struct intel_mipmap_tree *mt = intel_image->mt;
unsigned int dst_x, dst_y;
/* compute offset of the particular 2D image within the texture region */
intel_miptree_get_image_offset(intel_image->mt,
- intel_image->level,
- intel_image->face,
+ intel_image->base.Base.Level,
+ intel_image->base.Base.Face,
zoffset,
&dst_x, &dst_y);
- irb->draw_offset = (dst_y * mt->region->pitch + dst_x) * mt->cpp;
irb->draw_x = dst_x;
irb->draw_y = dst_y;
}
}
}
+#ifndef I915
+static bool
+need_tile_offset_workaround(struct brw_context *brw,
+ struct intel_renderbuffer *irb)
+{
+ uint32_t tile_x, tile_y;
+
+ if (brw->has_surface_tile_offset)
+ return false;
+
+ intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y);
+
+ return tile_x != 0 || tile_y != 0;
+}
+#endif
+
/**
* Called by glFramebufferTexture[123]DEXT() (and other places) to
* prepare for rendering into texture memory. This might be called
irb->Base.RefCount);
intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
- intel_image->used_as_render_target = GL_TRUE;
+ intel_image->used_as_render_target = true;
#ifndef I915
- if (!brw_context(ctx)->has_surface_tile_offset &&
- (irb->draw_offset & 4095) != 0) {
+ if (need_tile_offset_workaround(brw_context(ctx), irb)) {
/* Original gen4 hardware couldn't draw to a non-tile-aligned
* destination in a miptree unless you actually setup your
* renderbuffer as a miptree and used the fragile
* into that.
*/
struct intel_context *intel = intel_context(ctx);
- struct intel_mipmap_tree *old_mt = intel_image->mt;
struct intel_mipmap_tree *new_mt;
+ int width, height, depth;
+
+ intel_miptree_get_dimensions_for_image(image, &width, &height, &depth);
new_mt = intel_miptree_create(intel, image->TexObject->Target,
- intel_image->base.TexFormat,
- intel_image->level,
- intel_image->level,
- intel_image->base.Width,
- intel_image->base.Height,
- intel_image->base.Depth,
- GL_TRUE);
-
- intel_miptree_image_copy(intel,
- new_mt,
- intel_image->face,
- intel_image->level,
- old_mt);
-
- intel_miptree_release(intel, &intel_image->mt);
- intel_image->mt = new_mt;
+ intel_image->base.Base.TexFormat,
+ intel_image->base.Base.Level,
+ intel_image->base.Base.Level,
+ width, height, depth,
+ true);
+
+ intel_miptree_copy_teximage(intel, intel_image, new_mt);
intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
- intel_region_release(&irb->region);
intel_region_reference(&irb->region, intel_image->mt->region);
+ intel_miptree_release(&new_mt);
}
#endif
/* update drawing region, etc */
- intel_draw_buffer(ctx, fb);
+ intel_draw_buffer(ctx);
}
/* Flag that this image may now be validated into the object's miptree. */
if (intel_image)
- intel_image->used_as_render_target = GL_FALSE;
+ intel_image->used_as_render_target = false;
/* Since we've (probably) rendered to the texture and will (likely) use
* it in the texture domain later on in this batchbuffer, flush the
* The depth and stencil renderbuffers are the same renderbuffer or wrap
* the same texture.
*/
- bool depth_stencil_are_same;
- if (depthRb && stencilRb && depthRb == stencilRb)
- depth_stencil_are_same = true;
- else if (depthRb && stencilRb && depthRb != stencilRb
- && (fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE)
- && (fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE)
- && (fb->Attachment[BUFFER_DEPTH].Texture->Name
- == fb->Attachment[BUFFER_STENCIL].Texture->Name))
- depth_stencil_are_same = true;
- else
- depth_stencil_are_same = false;
-
- bool fb_has_combined_depth_stencil_format =
- (depthRb && depthRb->Base.Format == MESA_FORMAT_S8_Z24) ||
- (stencilRb && stencilRb->Base.Format == MESA_FORMAT_S8_Z24);
-
- bool fb_has_hiz = intel_framebuffer_has_hiz(fb);
-
- if ((intel->must_use_separate_stencil || fb_has_hiz)
- && (depth_stencil_are_same || fb_has_combined_depth_stencil_format)) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
- } else if (!intel->has_separate_stencil && depthRb && stencilRb && !depth_stencil_are_same) {
- fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ if (depthRb && stencilRb) {
+ bool depth_stencil_are_same;
+ if (depthRb == stencilRb)
+ depth_stencil_are_same = true;
+ else if ((fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE) &&
+ (fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE) &&
+ (fb->Attachment[BUFFER_DEPTH].Texture->Name ==
+ fb->Attachment[BUFFER_STENCIL].Texture->Name))
+ depth_stencil_are_same = true;
+ else
+ depth_stencil_are_same = false;
+
+ if (!intel->has_separate_stencil && !depth_stencil_are_same) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ }
}
for (i = 0; i < Elements(fb->Attachment); i++) {
struct gl_texture_image *texImage =
_mesa_select_tex_image(ctx, texObj, target, dstLevel);
- GLenum internalFormat = texImage->InternalFormat;
- if (intel_copy_texsubimage(intel_context(ctx), target,
+ if (intel_copy_texsubimage(intel_context(ctx),
intel_texture_image(texImage),
- internalFormat,
dstX0, dstY0,
srcX0, srcY0,
srcX1 - srcX0, /* width */