3D rendering to tiled textures was being done with non-tile-aligned offsets. The G4X hardware has fields to let us support it easily and correctly, while the pre-G4X hardware requires a path full of suffering, so we just fall back.undefined
@@ -37,6 +37,9 @@ | |||
#include "tnl/tnl.h" | |||
#include "brw_context.h" | |||
#include "brw_fallback.h" | |||
#include "intel_chipset.h" | |||
#include "intel_fbo.h" | |||
#include "intel_regions.h" | |||
#include "glapi/glapi.h" | |||
@@ -44,6 +47,7 @@ | |||
static GLboolean do_check_fallback(struct brw_context *brw) | |||
{ | |||
struct intel_context *intel = &brw->intel; | |||
GLcontext *ctx = &brw->intel.ctx; | |||
GLuint i; | |||
@@ -81,6 +85,33 @@ static GLboolean do_check_fallback(struct brw_context *brw) | |||
return GL_TRUE; | |||
} | |||
/* _NEW_BUFFERS */ | |||
if (IS_965(intel->intelScreen->deviceID) && | |||
!IS_G4X(intel->intelScreen->deviceID)) { | |||
for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { | |||
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i]; | |||
struct intel_renderbuffer *irb = intel_renderbuffer(rb); | |||
/* The original gen4 hardware couldn't set up WM surfaces pointing | |||
* at an offset within a tile, which can happen when rendering to | |||
* anything but the base level of a texture or the +X face/0 depth. | |||
* This was fixed with the 4 Series hardware. | |||
* | |||
* For these original chips, you would have to make the depth and | |||
* color destination surfaces include information on the texture | |||
* type, LOD, face, and various limits to use them as a destination. | |||
* I would have done this, but there's also a nasty requirement that | |||
* the depth and the color surfaces all be of the same LOD, which | |||
* may be a worse requirement than this alignment. (Also, we may | |||
* want to just demote the texture to untiled, instead). | |||
*/ | |||
if (irb->region && irb->region->tiling != I915_TILING_NONE && | |||
(irb->region->draw_offset & 4095)) { | |||
DBG("FALLBACK: non-tile-aligned destination for tiled FBO\n"); | |||
return GL_TRUE; | |||
} | |||
} | |||
} | |||
return GL_FALSE; | |||
} |
@@ -1075,7 +1075,7 @@ struct brw_surface_state | |||
GLuint y_offset:4; | |||
GLuint pad0:1; | |||
GLuint x_offset:7; | |||
} ss5; /* NEW in Integrated Graphics Device */ | |||
} ss5; /* New in G4X */ | |||
}; | |||
@@ -578,7 +578,27 @@ brw_update_renderbuffer_surface(struct brw_context *brw, | |||
surf.ss0.surface_format = key.surface_format; | |||
surf.ss0.surface_type = key.surface_type; | |||
surf.ss1.base_addr = key.draw_offset; | |||
if (key.tiling == I915_TILING_NONE) { | |||
surf.ss1.base_addr = key.draw_offset; | |||
} else { | |||
uint32_t tile_offset = key.draw_offset % 4096; | |||
surf.ss1.base_addr = key.draw_offset - tile_offset; | |||
assert(BRW_IS_G4X(brw) || tile_offset == 0); | |||
if (BRW_IS_G4X(brw)) { | |||
if (key.tiling == I915_TILING_X) { | |||
/* Note that the low bits of these fields are missing, so | |||
* there's the possibility of getting in trouble. | |||
*/ | |||
surf.ss5.x_offset = (tile_offset % 512) / key.cpp / 4; | |||
surf.ss5.y_offset = tile_offset / 512 / 2; | |||
} else { | |||
surf.ss5.x_offset = (tile_offset % 128) / key.cpp / 4; | |||
surf.ss5.y_offset = tile_offset / 128 / 2; | |||
} | |||
} | |||
} | |||
if (region_bo != NULL) | |||
surf.ss1.base_addr += region_bo->offset; /* reloc */ | |||
@@ -609,7 +629,7 @@ brw_update_renderbuffer_surface(struct brw_context *brw, | |||
drm_intel_bo_emit_reloc(brw->wm.surf_bo[unit], | |||
offsetof(struct brw_surface_state, ss1), | |||
region_bo, | |||
key.draw_offset, | |||
surf.ss1.base_addr, | |||
I915_GEM_DOMAIN_RENDER, | |||
I915_GEM_DOMAIN_RENDER); | |||
} |