summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/intel/intel_fbo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/intel/intel_fbo.c')
-rw-r--r--src/mesa/drivers/dri/intel/intel_fbo.c205
1 files changed, 118 insertions, 87 deletions
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c
index 7cf12619d6..084095fc96 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.c
+++ b/src/mesa/drivers/dri/intel/intel_fbo.c
@@ -27,6 +27,7 @@
#include "main/imports.h"
+#include "main/macros.h"
#include "main/mtypes.h"
#include "main/fbobject.h"
#include "main/framebuffer.h"
@@ -34,61 +35,17 @@
#include "main/context.h"
#include "main/texformat.h"
#include "main/texrender.h"
+#include "drivers/common/meta.h"
#include "intel_context.h"
#include "intel_buffers.h"
-#include "intel_depthstencil.h"
#include "intel_fbo.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
-#include "intel_span.h"
#define FILE_DEBUG_FLAG DEBUG_FBO
-#define INTEL_RB_CLASS 0x12345678
-
-
-/* XXX FBO: move this to intel_context.h (inlined) */
-/**
- * Return a gl_renderbuffer ptr casted to intel_renderbuffer.
- * NULL will be returned if the rb isn't really an intel_renderbuffer.
- * This is determiend by checking the ClassID.
- */
-struct intel_renderbuffer *
-intel_renderbuffer(struct gl_renderbuffer *rb)
-{
- struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
- if (irb && irb->Base.ClassID == INTEL_RB_CLASS) {
- /*_mesa_warning(NULL, "Returning non-intel Rb\n");*/
- return irb;
- }
- else
- return NULL;
-}
-
-
-struct intel_renderbuffer *
-intel_get_renderbuffer(struct gl_framebuffer *fb, int attIndex)
-{
- if (attIndex >= 0)
- return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
- else
- return NULL;
-}
-
-struct intel_region *
-intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
-{
- struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex);
-
- if (irb)
- return irb->region;
- else
- return NULL;
-}
-
-
/**
* Create a new framebuffer object.
@@ -103,6 +60,7 @@ intel_new_framebuffer(GLcontext * ctx, GLuint name)
}
+/** Called by gl_renderbuffer::Delete() */
static void
intel_delete_renderbuffer(struct gl_renderbuffer *rb)
{
@@ -112,10 +70,6 @@ intel_delete_renderbuffer(struct gl_renderbuffer *rb)
ASSERT(irb);
- if (irb->PairedStencil || irb->PairedDepth) {
- intel_unpair_depth_stencil(ctx, irb);
- }
-
if (irb->span_cache != NULL)
_mesa_free(irb->span_cache);
@@ -127,7 +81,6 @@ intel_delete_renderbuffer(struct gl_renderbuffer *rb)
}
-
/**
* Return a pointer to a specific pixel in a renderbuffer.
*/
@@ -142,7 +95,6 @@ intel_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
}
-
/**
* Called via glRenderbufferStorageEXT() to set the format and allocate
* storage for a user-created renderbuffer.
@@ -168,6 +120,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
rb->RedBits = 5;
rb->GreenBits = 6;
rb->BlueBits = 5;
+ irb->texformat = &_mesa_texformat_rgb565;
cpp = 2;
break;
case GL_RGB:
@@ -181,6 +134,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
rb->GreenBits = 8;
rb->BlueBits = 8;
rb->AlphaBits = 0;
+ irb->texformat = &_mesa_texformat_argb8888; /* XXX: Need xrgb8888 */
cpp = 4;
break;
case GL_RGBA:
@@ -197,6 +151,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
rb->GreenBits = 8;
rb->BlueBits = 8;
rb->AlphaBits = 8;
+ irb->texformat = &_mesa_texformat_argb8888;
cpp = 4;
break;
case GL_STENCIL_INDEX:
@@ -209,20 +164,15 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
rb->StencilBits = 8;
cpp = 4;
+ irb->texformat = &_mesa_texformat_s8_z24;
break;
case GL_DEPTH_COMPONENT16:
-#if 0
rb->_ActualFormat = GL_DEPTH_COMPONENT16;
rb->DataType = GL_UNSIGNED_SHORT;
rb->DepthBits = 16;
cpp = 2;
+ irb->texformat = &_mesa_texformat_z16;
break;
-#else
- /* fall-through.
- * 16bpp depth renderbuffer can't be paired with a stencil buffer so
- * always used combined depth/stencil format.
- */
-#endif
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
@@ -230,6 +180,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
rb->DepthBits = 24;
cpp = 4;
+ irb->texformat = &_mesa_texformat_s8_z24;
break;
case GL_DEPTH_STENCIL_EXT:
case GL_DEPTH24_STENCIL8_EXT:
@@ -238,6 +189,7 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
rb->DepthBits = 24;
rb->StencilBits = 8;
cpp = 4;
+ irb->texformat = &_mesa_texformat_s8_z24;
break;
default:
_mesa_problem(ctx,
@@ -266,7 +218,9 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width,
height, pitch);
- irb->region = intel_region_alloc(intel, cpp, width, height, pitch);
+ irb->region = intel_region_alloc(intel, I915_TILING_NONE,
+ cpp, width, height, pitch,
+ GL_TRUE);
if (!irb->region)
return GL_FALSE; /* out of memory? */
@@ -280,7 +234,6 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
}
-
/**
* Called for each hardware renderbuffer when a _window_ is resized.
* Just update fields.
@@ -298,6 +251,7 @@ intel_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
return GL_TRUE;
}
+
static void
intel_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb,
GLuint width, GLuint height)
@@ -324,6 +278,8 @@ intel_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb,
}
}
+
+/** Dummy function for gl_renderbuffer::AllocStorage() */
static GLboolean
intel_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLuint width, GLuint height)
@@ -343,10 +299,9 @@ intel_renderbuffer_set_region(struct intel_renderbuffer *rb,
rb->region = NULL;
intel_region_reference(&rb->region, region);
intel_region_release(&old);
-
- rb->pfPitch = region->pitch;
}
+
/**
* Create a new intel_renderbuffer which corresponds to an on-screen window,
* not a user-created renderbuffer.
@@ -376,6 +331,17 @@ intel_create_renderbuffer(GLenum intFormat)
irb->Base.GreenBits = 6;
irb->Base.BlueBits = 5;
irb->Base.DataType = GL_UNSIGNED_BYTE;
+ irb->texformat = &_mesa_texformat_rgb565;
+ break;
+ case GL_RGB8:
+ irb->Base._ActualFormat = GL_RGB8;
+ irb->Base._BaseFormat = GL_RGB;
+ irb->Base.RedBits = 8;
+ irb->Base.GreenBits = 8;
+ irb->Base.BlueBits = 8;
+ irb->Base.AlphaBits = 0;
+ irb->Base.DataType = GL_UNSIGNED_BYTE;
+ irb->texformat = &_mesa_texformat_argb8888; /* XXX: Need xrgb8888 */
break;
case GL_RGBA8:
irb->Base._ActualFormat = GL_RGBA8;
@@ -385,24 +351,28 @@ intel_create_renderbuffer(GLenum intFormat)
irb->Base.BlueBits = 8;
irb->Base.AlphaBits = 8;
irb->Base.DataType = GL_UNSIGNED_BYTE;
+ irb->texformat = &_mesa_texformat_argb8888;
break;
case GL_STENCIL_INDEX8_EXT:
irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT;
irb->Base._BaseFormat = GL_STENCIL_INDEX;
irb->Base.StencilBits = 8;
irb->Base.DataType = GL_UNSIGNED_BYTE;
+ irb->texformat = &_mesa_texformat_s8_z24;
break;
case GL_DEPTH_COMPONENT16:
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
irb->Base.DepthBits = 16;
irb->Base.DataType = GL_UNSIGNED_SHORT;
+ irb->texformat = &_mesa_texformat_z16;
break;
case GL_DEPTH_COMPONENT24:
irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
irb->Base.DepthBits = 24;
irb->Base.DataType = GL_UNSIGNED_INT;
+ irb->texformat = &_mesa_texformat_s8_z24;
break;
case GL_DEPTH24_STENCIL8_EXT:
irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
@@ -410,6 +380,7 @@ intel_create_renderbuffer(GLenum intFormat)
irb->Base.DepthBits = 24;
irb->Base.StencilBits = 8;
irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
+ irb->texformat = &_mesa_texformat_s8_z24;
break;
default:
_mesa_problem(NULL,
@@ -466,9 +437,6 @@ intel_bind_framebuffer(GLcontext * ctx, GLenum target,
{
if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
intel_draw_buffer(ctx, fb);
- /* Integer depth range depends on depth buffer bits */
- if (ctx->Driver.DepthRange != NULL)
- ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far);
}
else {
/* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
@@ -492,10 +460,13 @@ intel_framebuffer_renderbuffer(GLcontext * ctx,
intel_draw_buffer(ctx, fb);
}
+
static GLboolean
intel_update_wrapper(GLcontext *ctx, struct intel_renderbuffer *irb,
struct gl_texture_image *texImage)
{
+ irb->texformat = texImage->TexFormat;
+
if (texImage->TexFormat == &_mesa_texformat_argb8888) {
irb->Base._ActualFormat = GL_RGBA8;
irb->Base._BaseFormat = GL_RGBA;
@@ -505,9 +476,21 @@ intel_update_wrapper(GLcontext *ctx, struct intel_renderbuffer *irb,
else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
irb->Base._ActualFormat = GL_RGB5;
irb->Base._BaseFormat = GL_RGB;
- irb->Base.DataType = GL_UNSIGNED_SHORT;
+ irb->Base.DataType = GL_UNSIGNED_BYTE;
DBG("Render to RGB5 texture OK\n");
}
+ else if (texImage->TexFormat == &_mesa_texformat_argb1555) {
+ irb->Base._ActualFormat = GL_RGB5_A1;
+ irb->Base._BaseFormat = GL_RGBA;
+ irb->Base.DataType = GL_UNSIGNED_BYTE;
+ DBG("Render to ARGB1555 texture OK\n");
+ }
+ else if (texImage->TexFormat == &_mesa_texformat_argb4444) {
+ irb->Base._ActualFormat = GL_RGBA4;
+ irb->Base._BaseFormat = GL_RGBA;
+ irb->Base.DataType = GL_UNSIGNED_BYTE;
+ DBG("Render to ARGB4444 texture OK\n");
+ }
else if (texImage->TexFormat == &_mesa_texformat_z16) {
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
@@ -534,15 +517,15 @@ intel_update_wrapper(GLcontext *ctx, struct intel_renderbuffer *irb,
irb->Base.BlueBits = texImage->TexFormat->BlueBits;
irb->Base.AlphaBits = texImage->TexFormat->AlphaBits;
irb->Base.DepthBits = texImage->TexFormat->DepthBits;
+ irb->Base.StencilBits = texImage->TexFormat->StencilBits;
irb->Base.Delete = intel_delete_renderbuffer;
irb->Base.AllocStorage = intel_nop_alloc_storage;
- irb->RenderToTexture = GL_TRUE;
-
return GL_TRUE;
}
+
/**
* When glFramebufferTexture[123]D is called this function sets up the
* gl_renderbuffer wrapper around the texture image.
@@ -551,7 +534,7 @@ intel_update_wrapper(GLcontext *ctx, struct intel_renderbuffer *irb,
static struct intel_renderbuffer *
intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
{
- const GLuint name = ~0; /* not significant, but distinct for debugging */
+ const GLuint name = ~0; /* not significant, but distinct for debugging */
struct intel_renderbuffer *irb;
/* make an intel_renderbuffer to wrap the texture image */
@@ -594,14 +577,16 @@ intel_render_texture(GLcontext * ctx,
ASSERT(newImage);
- if (newImage->Border != 0) {
- /* Fallback on drawing to a texture with a border, which won't have a
- * miptree.
+ intel_image = intel_texture_image(newImage);
+ if (!intel_image->mt) {
+ /* Fallback on drawing to a texture that doesn't have a miptree
+ * (has a border, width/height 0, etc.)
*/
- _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
- _mesa_render_texture(ctx, fb, att);
- return;
- } else if (!irb) {
+ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
+ _mesa_render_texture(ctx, fb, att);
+ return;
+ }
+ else if (!irb) {
irb = intel_wrap_texture(ctx, newImage);
if (irb) {
/* bind the wrapper to the attachment point */
@@ -612,7 +597,9 @@ intel_render_texture(GLcontext * ctx,
_mesa_render_texture(ctx, fb, att);
return;
}
- } if (!intel_update_wrapper(ctx, irb, newImage)) {
+ }
+
+ if (!intel_update_wrapper(ctx, irb, newImage)) {
_mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
_mesa_render_texture(ctx, fb, att);
return;
@@ -624,7 +611,6 @@ intel_render_texture(GLcontext * ctx,
irb->Base.RefCount);
/* point the renderbufer's region to the texture image region */
- intel_image = intel_texture_image(newImage);
if (irb->region != intel_image->mt->region) {
if (irb->region)
intel_region_release(&irb->region);
@@ -657,18 +643,59 @@ static void
intel_finish_render_texture(GLcontext * ctx,
struct gl_renderbuffer_attachment *att)
{
- struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
+ /* no-op
+ * Previously we released the renderbuffer's intel_region but
+ * that's not necessary and actually caused problems when trying
+ * to do a glRead/CopyPixels from the renderbuffer later.
+ * The region will be released later if the texture is replaced
+ * or the renderbuffer deleted.
+ *
+ * The intention of this driver hook is more of a "done rendering
+ * to texture, please re-twiddle/etc if necessary".
+ */
+}
- DBG("End render texture (tid %x) tex %u\n", _glthread_GetID(), att->Texture->Name);
- if (irb) {
- /* just release the region */
- intel_region_release(&irb->region);
+/**
+ * Do additional "completeness" testing of a framebuffer object.
+ */
+static void
+intel_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
+{
+ const struct intel_renderbuffer *depthRb =
+ intel_get_renderbuffer(fb, BUFFER_DEPTH);
+ const struct intel_renderbuffer *stencilRb =
+ intel_get_renderbuffer(fb, BUFFER_STENCIL);
+ int i;
+
+ if (stencilRb && stencilRb != depthRb) {
+ /* we only support combined depth/stencil buffers, not separate
+ * stencil buffers.
+ */
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
}
- else if (att->Renderbuffer) {
- /* software fallback */
- _mesa_finish_render_texture(ctx, att);
- /* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */
+
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
+ struct intel_renderbuffer *irb = intel_renderbuffer(rb);
+
+ if (rb == NULL)
+ continue;
+
+ if (irb == NULL) {
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ continue;
+ }
+
+ switch (irb->texformat->MesaFormat) {
+ case MESA_FORMAT_ARGB8888:
+ case MESA_FORMAT_RGB565:
+ case MESA_FORMAT_ARGB1555:
+ case MESA_FORMAT_ARGB4444:
+ break;
+ default:
+ fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
+ }
}
}
@@ -687,4 +714,8 @@ intel_fbo_init(struct intel_context *intel)
intel->ctx.Driver.RenderTexture = intel_render_texture;
intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
+ intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
+#if FEATURE_EXT_framebuffer_blit
+ intel->ctx.Driver.BlitFramebuffer = _mesa_meta_blit_framebuffer;
+#endif
}