/** Called by gl_renderbuffer::Delete() */
static void
-intel_delete_renderbuffer(struct gl_renderbuffer *rb)
+intel_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
intel_miptree_release(&irb->mt);
- free(irb);
+ _mesa_delete_renderbuffer(ctx, rb);
}
/**
/**
* Round up the requested multisample count to the next supported sample size.
*/
-static unsigned
-quantize_num_samples(struct intel_context *intel, unsigned num_samples)
+unsigned
+intel_quantize_num_samples(struct intel_screen *intel, unsigned num_samples)
{
switch (intel->gen) {
case 6:
return 0;
return 0;
default:
- /* MSAA unsupported */
+ /* 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;
return 0;
}
}
* Called via glRenderbufferStorageEXT() to set the format and allocate
* storage for a user-created renderbuffer.
*/
-GLboolean
+static GLboolean
intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
GLenum internalFormat,
GLuint width, GLuint height)
{
struct intel_context *intel = intel_context(ctx);
+ struct intel_screen *screen = intel->intelScreen;
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
- rb->NumSamples = quantize_num_samples(intel, rb->NumSamples);
+ rb->NumSamples = intel_quantize_num_samples(screen, rb->NumSamples);
switch (internalFormat) {
default:
* except they're less useful because you can't texture with
* them.
*/
- rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat,
+ rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, GL_TEXTURE_2D,
+ internalFormat,
GL_NONE, GL_NONE);
break;
case GL_STENCIL_INDEX:
if (!irb->mt)
return false;
- if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
- bool ok = intel_miptree_alloc_hiz(intel, irb->mt, rb->NumSamples);
- if (!ok) {
- intel_miptree_release(&irb->mt);
- return false;
- }
- }
-
- if (irb->mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) {
- bool ok = intel_miptree_alloc_mcs(intel, irb->mt, rb->NumSamples);
- if (!ok) {
- intel_miptree_release(&irb->mt);
- return false;
- }
- }
-
return true;
}
-#if FEATURE_OES_EGL_image
static void
intel_image_target_renderbuffer_storage(struct gl_context *ctx,
struct gl_renderbuffer *rb,
rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx,
image->internal_format);
}
-#endif
/**
* Called for each hardware renderbuffer when a _window_ is resized.
/**
* Create a new intel_renderbuffer which corresponds to an on-screen window,
* not a user-created renderbuffer.
+ *
+ * \param num_samples must be quantized.
*/
struct intel_renderbuffer *
-intel_create_renderbuffer(gl_format format)
+intel_create_renderbuffer(gl_format format, unsigned num_samples)
{
struct intel_renderbuffer *irb;
struct gl_renderbuffer *rb;
rb->_BaseFormat = _mesa_get_format_base_format(format);
rb->Format = format;
rb->InternalFormat = rb->_BaseFormat;
+ rb->NumSamples = num_samples;
/* intel-specific methods */
rb->Delete = intel_delete_renderbuffer;
* 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.
+ *
+ * \param num_samples must be quantized.
*/
struct intel_renderbuffer *
-intel_create_private_renderbuffer(gl_format format)
+intel_create_private_renderbuffer(gl_format format, unsigned num_samples)
{
struct intel_renderbuffer *irb;
- irb = intel_create_renderbuffer(format);
+ irb = intel_create_renderbuffer(format, num_samples);
irb->Base.Base.AllocStorage = intel_alloc_renderbuffer_storage;
return irb;
intel_draw_buffer(ctx);
}
-/**
- * \par Special case for separate stencil
- *
- * When wrapping a depthstencil texture that uses separate stencil, this
- * function is recursively called twice: once to create \c
- * irb->wrapped_depth and again to create \c irb->wrapped_stencil. On the
- * call to create \c irb->wrapped_depth, the \c format and \c
- * internal_format parameters do not match \c mt->format. In that case, \c
- * mt->format is MESA_FORMAT_S8_Z24 and \c format is \c
- * MESA_FORMAT_X8_Z24.
- *
- * @return true on success
- */
-
static bool
intel_renderbuffer_update_wrapper(struct intel_context *intel,
struct intel_renderbuffer *irb,
/* compute offset of the particular 2D image within the texture region */
intel_miptree_get_image_offset(irb->mt,
irb->mt_level,
- 0, /* face, which we ignore */
irb->mt_layer,
&dst_x, &dst_y);
struct intel_region *region = irb->mt->region;
uint32_t mask_x, mask_y;
- intel_region_get_tile_masks(region, &mask_x, &mask_y);
+ intel_region_get_tile_masks(region, &mask_x, &mask_y, false);
*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,
- irb->draw_y & ~mask_y);
+ irb->draw_y & ~mask_y, false);
}
/**
GLbitfield mask, GLenum filter)
{
if (mask & GL_COLOR_BUFFER_BIT) {
+ GLint i;
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]];
+ const struct gl_renderbuffer_attachment *drawAtt;
struct intel_renderbuffer *srcRb =
intel_renderbuffer(readFb->_ColorReadBuffer);
- /* 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 */
- if (srcRb && drawAtt && drawAtt->Texture &&
- 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);
-
- if (intel_copy_texsubimage(intel_context(ctx),
- intel_texture_image(texImage),
- dstX0, dstY0,
- srcRb,
- srcX0, srcY0,
- srcX1 - srcX0, /* width */
- srcY1 - srcY0))
- mask &= ~GL_COLOR_BUFFER_BIT;
+ /* 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.
+ */
+ const GLboolean use_intel_copy_texsubimage =
+ 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;
+
+ /* Verify that all the draw buffers can be blitted using
+ * intel_copy_texsubimage().
+ */
+ for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
+ int idx = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
+ if (idx == -1)
+ continue;
+ drawAtt = &drawFb->Attachment[idx];
+
+ if (srcRb && drawAtt && drawAtt->Texture &&
+ use_intel_copy_texsubimage)
+ continue;
+ else
+ return mask;
}
+
+ /* Blit to all active draw buffers */
+ for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
+ int idx = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
+ if (idx == -1)
+ continue;
+ drawAtt = &drawFb->Attachment[idx];
+
+ {
+ 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);
+
+ if (!intel_copy_texsubimage(intel_context(ctx),
+ intel_texture_image(texImage),
+ dstX0, dstY0,
+ srcRb,
+ srcX0, srcY0,
+ srcX1 - srcX0, /* width */
+ srcY1 - srcY0))
+ return mask;
+ }
+ }
+
+ mask &= ~GL_COLOR_BUFFER_BIT;
}
return mask;
mask, filter);
}
+/**
+ * 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;
+}
+
void
intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb)
{
return false;
}
+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,
+ false /* force_y_tiling */);
+
+ 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);
+}
+
/**
* Do one-time context initializations related to GL_EXT_framebuffer_object.
* Hook in device driver functions.
intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
-
-#if FEATURE_OES_EGL_image
intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
intel_image_target_renderbuffer_storage;
-#endif
}