Implement software fallback for render-to-texture when the texture format

can't be rendered by the hardware.
This commit is contained in:
Brian Paul 2006-03-25 17:56:49 +00:00
parent 460a375d85
commit d65cda4ce3
3 changed files with 64 additions and 27 deletions

View file

@ -384,11 +384,11 @@ static void intelClear(GLcontext *ctx,
GLbitfield tri_mask = 0;
GLbitfield blit_mask = 0;
GLbitfield swrast_mask = 0;
GLuint i;
if (0)
fprintf(stderr, "%s\n", __FUNCTION__);
/* HW color buffers (front, back, aux, generic FBO, etc) */
if (colorMask == ~0) {
/* clear all R,G,B,A */
@ -429,6 +429,18 @@ static void intelClear(GLcontext *ctx,
/* SW fallback clearing */
swrast_mask = mask & ~tri_mask & ~blit_mask;
for (i = 0; i < BUFFER_COUNT; i++) {
GLuint bufBit = 1 << i;
if ((blit_mask | tri_mask) & bufBit) {
if (!ctx->DrawBuffer->Attachment[i].Renderbuffer->ClassID) {
blit_mask &= ~bufBit;
tri_mask &= ~bufBit;
swrast_mask |= bufBit;
}
}
}
intelFlush( ctx ); /* XXX intelClearWithBlit also does this */
if (blit_mask)
@ -603,6 +615,13 @@ intel_draw_buffer(GLcontext *ctx, struct gl_framebuffer *fb)
colorRegion = (irb && irb->region) ? irb->region : NULL;
}
if (!colorRegion) {
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE );
}
else {
FALLBACK( intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE );
}
/***
*** Get depth buffer region and check if we need a software fallback.
*** Note that the depth buffer is usually a DEPTH_STENCIL buffer.

View file

@ -120,29 +120,15 @@ intel_delete_renderbuffer(struct gl_renderbuffer *rb)
/**
* Return a pointer to a specific pixel in a renderbuffer.
* Note: y=0=bottom.
* Called via gl_renderbuffer::GetPointer().
*/
static void *
intel_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb,
GLint x, GLint y)
{
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
/* Actually, we could _always_ return NULL from this function and
* be OK. The swrast code would just use the Get/Put routines as needed.
* But by really implementing this function there's a chance for better
* performance.
/* By returning NULL we force all software rendering to go through
* the span routines.
*/
if (irb->region && irb->region->map) {
int offset;
y = irb->region->height - y - 1;
offset = (y * irb->region->pitch + x) * irb->region->cpp;
return (void *) (irb->region->map + offset);
}
else {
return NULL;
}
return NULL;
}
@ -572,9 +558,7 @@ intel_renderbuffer_texture(GLcontext *ctx,
}
else {
/* fallback to software rendering */
_mesa_problem(ctx, "Render to texture - unsupported hw format");
_mesa_renderbuffer_texture(ctx, fb, att);
/* XXX FBO: Need to map the buffer (or in intelSpanRenderStart???) */
return;
}
}

View file

@ -172,6 +172,11 @@
* XXX in the future, we could probably convey extra information to
* reduce the number of mappings needed. I.e. if doing a glReadPixels
* from the depth buffer, we really only need one mapping.
*
* XXX Rewrite this function someday.
* We can probably just loop over all the renderbuffer attachments,
* map/unmap all of them, and not worry about the _ColorDrawBuffers
* _ColorReadBuffer, _DepthBuffer or _StencilBuffer fields.
*/
static void
intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
@ -185,9 +190,8 @@ intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
for (j = 0; j < ctx->DrawBuffer->_NumColorDrawBuffers[i]; j++) {
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i][j];
irb = intel_renderbuffer(rb);
/* XXX FBO: check irb != NULL to catch software RBs??? */
ASSERT(irb);
if (irb->Base.Name != 0) { /* XXX FBO temporary test */
if (irb && irb->Base.Name != 0) { /* XXX FBO temporary test */
/* this is a user-created intel_renderbuffer */
if (irb->region) {
if (map)
intel_region_map(intel, irb->region);
@ -200,6 +204,24 @@ intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
}
}
/* check for render to textures */
for (i = 0; i < BUFFER_COUNT; i++) {
struct gl_renderbuffer_attachment *att = ctx->DrawBuffer->Attachment + i;
struct gl_texture_object *tex = att->Texture;
if (tex) {
/* render to texture */
ASSERT(att->Renderbuffer);
if (map) {
struct gl_texture_image *texImg;
texImg = tex->Image[att->CubeMapFace][att->TextureLevel];
intel_tex_map_images(intel, intel_texture_object(tex));
}
else {
intel_tex_unmap_images(intel, intel_texture_object(tex));
}
}
}
/* color read buffers */
irb = intel_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
if (irb && irb->region && irb->Base.Name != 0) {
@ -242,10 +264,16 @@ intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
if (ctx->DrawBuffer->_DepthBuffer) {
irb = intel_renderbuffer(ctx->DrawBuffer->_DepthBuffer->Wrapped);
if (irb && irb->region && irb->Base.Name != 0) {
if (map)
if (map) {
intel_region_map(intel, irb->region);
else
irb->pfMap = irb->region->map;
irb->pfPitch = irb->region->pitch;
}
else {
intel_region_unmap(intel, irb->region);
irb->pfMap = NULL;
irb->pfPitch = 0;
}
}
}
@ -253,10 +281,16 @@ intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
if (ctx->DrawBuffer->_StencilBuffer) {
irb = intel_renderbuffer(ctx->DrawBuffer->_StencilBuffer->Wrapped);
if (irb && irb->region && irb->Base.Name != 0) {
if (map)
if (map) {
intel_region_map(intel, irb->region);
else
irb->pfMap = irb->region->map;
irb->pfPitch = irb->region->pitch;
}
else {
intel_region_unmap(intel, irb->region);
irb->pfMap = NULL;
irb->pfPitch = 0;
}
}
}
}