pipe_surface_reference(&r300->locked_zbuffer, NULL);
}
-/* Copy a block of pixels from one surface to another using HW. */
-static void r300_hw_copy_region(struct pipe_context* pipe,
- struct pipe_resource *dst,
- unsigned dst_level,
- unsigned dstx, unsigned dsty, unsigned dstz,
- struct pipe_resource *src,
- unsigned src_level,
- const struct pipe_box *src_box)
+bool r300_is_blit_supported(enum pipe_format format)
{
- struct r300_context* r300 = r300_context(pipe);
+ const struct util_format_description *desc =
+ util_format_description(format);
- r300_blitter_begin(r300, R300_COPY);
- util_blitter_copy_texture(r300->blitter, dst, dst_level, dstx, dsty, dstz,
- src, src_level, src_box, TRUE);
- r300_blitter_end(r300);
+ return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ||
+ desc->layout == UTIL_FORMAT_LAYOUT_S3TC ||
+ desc->layout == UTIL_FORMAT_LAYOUT_RGTC;
}
/* Copy a block of pixels from one surface to another. */
unsigned src_level,
const struct pipe_box *src_box)
{
+ struct pipe_screen *screen = pipe->screen;
struct r300_context *r300 = r300_context(pipe);
struct pipe_framebuffer_state *fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
- struct pipe_resource old_src = *src;
- struct pipe_resource old_dst = *dst;
- struct pipe_resource new_src = old_src;
- struct pipe_resource new_dst = old_dst;
- const struct util_format_description *desc =
- util_format_description(dst->format);
+ unsigned src_width0 = r300_resource(src)->tex.width0;
+ unsigned src_height0 = r300_resource(src)->tex.height0;
+ unsigned dst_width0 = r300_resource(dst)->tex.width0;
+ unsigned dst_height0 = r300_resource(dst)->tex.height0;
+ unsigned layout;
struct pipe_box box;
+ struct pipe_sampler_view src_templ, *src_view;
+ struct pipe_surface dst_templ, *dst_view;
/* Fallback for buffers. */
- if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
+ if ((dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) ||
+ !r300_is_blit_supported(dst->format)) {
util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
src, src_level, src_box);
return;
}
- if (r300->zmask_in_use && !r300->locked_zbuffer) {
- if (fb->zsbuf->texture == src ||
- fb->zsbuf->texture == dst) {
- r300_decompress_zmask(r300);
- }
- }
+ /* The code below changes the texture format so that the copy can be done
+ * on hardware. E.g. depth-stencil surfaces are copied as RGBA
+ * colorbuffers. */
+
+ util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz, src_box);
+ util_blitter_default_src_texture(&src_templ, src, src_level);
+
+ layout = util_format_description(dst_templ.format)->layout;
/* Handle non-renderable plain formats. */
- if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
- (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB ||
- !pipe->screen->is_format_supported(pipe->screen,
- src->format, src->target,
- src->nr_samples,
- PIPE_BIND_SAMPLER_VIEW) ||
- !pipe->screen->is_format_supported(pipe->screen,
- dst->format, dst->target,
- dst->nr_samples,
- PIPE_BIND_RENDER_TARGET))) {
- switch (util_format_get_blocksize(old_dst.format)) {
+ if (layout == UTIL_FORMAT_LAYOUT_PLAIN &&
+ (!screen->is_format_supported(screen, src_templ.format, src->target,
+ src->nr_samples,
+ PIPE_BIND_SAMPLER_VIEW) ||
+ !screen->is_format_supported(screen, dst_templ.format, dst->target,
+ dst->nr_samples,
+ PIPE_BIND_RENDER_TARGET))) {
+ switch (util_format_get_blocksize(dst_templ.format)) {
case 1:
- new_dst.format = PIPE_FORMAT_I8_UNORM;
+ dst_templ.format = PIPE_FORMAT_I8_UNORM;
break;
case 2:
- new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM;
+ dst_templ.format = PIPE_FORMAT_B4G4R4A4_UNORM;
break;
case 4:
- new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ dst_templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
break;
case 8:
- new_dst.format = PIPE_FORMAT_R16G16B16A16_UNORM;
+ dst_templ.format = PIPE_FORMAT_R16G16B16A16_UNORM;
break;
default:
- debug_printf("r300: surface_copy: Unhandled format: %s. Falling back to software.\n"
- "r300: surface_copy: Software fallback doesn't work for tiled textures.\n",
- util_format_short_name(dst->format));
+ debug_printf("r300: copy_region: Unhandled format: %s. Falling back to software.\n"
+ "r300: copy_region: Software fallback doesn't work for tiled textures.\n",
+ util_format_short_name(dst_templ.format));
}
- new_src.format = new_dst.format;
+ src_templ.format = dst_templ.format;
}
/* Handle compressed formats. */
- if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC ||
- desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {
- switch (util_format_get_blocksize(old_dst.format)) {
+ if (layout == UTIL_FORMAT_LAYOUT_S3TC ||
+ layout == UTIL_FORMAT_LAYOUT_RGTC) {
+ assert(src_templ.format == dst_templ.format);
+
+ box = *src_box;
+ src_box = &box;
+
+ dst_width0 = align(dst_width0, 4);
+ dst_height0 = align(dst_height0, 4);
+ src_width0 = align(src_width0, 4);
+ src_height0 = align(src_height0, 4);
+ box.width = align(box.width, 4);
+ box.height = align(box.height, 4);
+
+ switch (util_format_get_blocksize(dst_templ.format)) {
case 8:
- /* 1 pixel = 4 bits,
- * we set 1 pixel = 2 bytes ===> 4 times larger pixels. */
- new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM;
+ /* one 4x4 pixel block has 8 bytes.
+ * we set 1 pixel = 4 bytes ===> 1 block corrensponds to 2 pixels. */
+ dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM;
+ dst_width0 = dst_width0 / 2;
+ src_width0 = src_width0 / 2;
+ dstx /= 2;
+ box.x /= 2;
+ box.width /= 2;
break;
case 16:
- /* 1 pixel = 8 bits,
- * we set 1 pixel = 4 bytes ===> 4 times larger pixels. */
- new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ /* one 4x4 pixel block has 16 bytes.
+ * we set 1 pixel = 4 bytes ===> 1 block corresponds to 4 pixels. */
+ dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM;
break;
}
+ src_templ.format = dst_templ.format;
- /* Since the pixels are 4 times larger, we must decrease
- * the image size and the coordinates 4 times. */
- new_src.format = new_dst.format;
- new_dst.height0 = (new_dst.height0 + 3) / 4;
- new_src.height0 = (new_src.height0 + 3) / 4;
+ dst_height0 = dst_height0 / 4;
+ src_height0 = src_height0 / 4;
dsty /= 4;
- box = *src_box;
box.y /= 4;
- box.height = (box.height + 3) / 4;
- src_box = &box;
+ box.height /= 4;
}
- if (old_src.format != new_src.format)
- r300_resource_set_properties(pipe->screen, src, &new_src);
- if (old_dst.format != new_dst.format)
- r300_resource_set_properties(pipe->screen, dst, &new_dst);
+ /* Fallback for textures. */
+ if (!screen->is_format_supported(screen, dst_templ.format,
+ dst->target, dst->nr_samples,
+ PIPE_BIND_RENDER_TARGET) ||
+ !screen->is_format_supported(screen, src_templ.format,
+ src->target, src->nr_samples,
+ PIPE_BIND_SAMPLER_VIEW)) {
+ assert(0 && "this shouldn't happen, update r300_is_blit_supported");
+ util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
+ src, src_level, src_box);
+ return;
+ }
- r300_hw_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
- src, src_level, src_box);
+ /* Decompress ZMASK. */
+ if (r300->zmask_in_use && !r300->locked_zbuffer) {
+ if (fb->zsbuf->texture == src ||
+ fb->zsbuf->texture == dst) {
+ r300_decompress_zmask(r300);
+ }
+ }
+
+ dst_view = r300_create_surface_custom(pipe, dst, &dst_templ, dst_width0, dst_height0);
+ src_view = r300_create_sampler_view_custom(pipe, src, &src_templ, src_width0, src_height0);
+
+ r300_blitter_begin(r300, R300_COPY);
+ util_blitter_copy_texture_view(r300->blitter, dst_view, dstx, dsty,
+ src_view, src_box,
+ src_width0, src_height0);
+ r300_blitter_end(r300);
- if (old_src.format != new_src.format)
- r300_resource_set_properties(pipe->screen, src, &old_src);
- if (old_dst.format != new_dst.format)
- r300_resource_set_properties(pipe->screen, dst, &old_dst);
+ pipe_surface_reference(&dst_view, NULL);
+ pipe_sampler_view_reference(&src_view, NULL);
}
void r300_init_blit_functions(struct r300_context *r300)
struct r300_sampler_view {
struct pipe_sampler_view base;
+ /* For resource_copy_region. */
+ unsigned width0_override;
+ unsigned height0_override;
+
/* Swizzles in the UTIL_FORMAT_SWIZZLE_* representation,
* derived from base. */
unsigned char swizzle[4];
unsigned offset_in_bytes[R300_MAX_TEXTURE_LEVELS];
/* Strides for each mip-level. */
- unsigned stride_in_pixels[R300_MAX_TEXTURE_LEVELS];
unsigned stride_in_bytes[R300_MAX_TEXTURE_LEVELS];
/* Size of one zslice or face or 2D image based on the texture target. */
/* Texture description (addressing, layout, special features). */
struct r300_texture_desc tex;
- /* Registers carrying texture format data. */
- /* Only format-independent bits should be filled in. */
- struct r300_texture_format_state tx_format;
-
/* This is the level tiling flags were last time set for.
* It's used to prevent redundant tiling-flags changes from happening.*/
unsigned surface_level;
void r300_decompress_zmask(struct r300_context *r300);
void r300_decompress_zmask_locked_unsafe(struct r300_context *r300);
void r300_decompress_zmask_locked(struct r300_context *r300);
+bool r300_is_blit_supported(enum pipe_format format);
/* r300_flush.c */
void r300_flush(struct pipe_context *pipe,
enum r300_fb_state_change change);
void r300_mark_fs_code_dirty(struct r300_context *r300);
+struct pipe_sampler_view *
+r300_create_sampler_view_custom(struct pipe_context *pipe,
+ struct pipe_resource *texture,
+ const struct pipe_sampler_view *templ,
+ unsigned width0_override,
+ unsigned height0_override);
+
/* r300_state_derived.c */
void r300_update_derived_state(struct r300_context* r300);
"r300: %s[%i] Dim: %ix%i, Firstlayer: %i, "
"Lastlayer: %i, Level: %i, Format: %s\n"
- "r300: TEX: Macro: %s, Micro: %s, Pitch: %i, "
+ "r300: TEX: Macro: %s, Micro: %s, "
"Dim: %ix%ix%i, LastLevel: %i, Format: %s\n",
binding, index, surf->width, surf->height,
rtex->tex.macrotile[0] ? "YES" : " NO",
rtex->tex.microtile ? "YES" : " NO",
- rtex->tex.stride_in_pixels[0],
tex->width0, tex->height0, tex->depth0,
- tex->last_level, util_format_short_name(tex->format));
+ tex->last_level, util_format_short_name(surf->format));
}
void r300_mark_fb_state_dirty(struct r300_context *r300,
r300_mark_fb_state_dirty(r300, R300_CHANGED_FB_STATE);
if (state->zsbuf) {
- switch (util_format_get_blocksize(state->zsbuf->texture->format)) {
+ switch (util_format_get_blocksize(state->zsbuf->format)) {
case 2:
zbuffer_bpp = 16;
break;
}
}
-static struct pipe_sampler_view *
-r300_create_sampler_view(struct pipe_context *pipe,
+struct pipe_sampler_view *
+r300_create_sampler_view_custom(struct pipe_context *pipe,
struct pipe_resource *texture,
- const struct pipe_sampler_view *templ)
+ const struct pipe_sampler_view *templ,
+ unsigned width0_override,
+ unsigned height0_override)
{
struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view);
struct r300_resource *tex = r300_resource(texture);
view->base.texture = NULL;
pipe_resource_reference(&view->base.texture, texture);
+ view->width0_override = width0_override;
+ view->height0_override = height0_override;
view->swizzle[0] = templ->swizzle_r;
view->swizzle[1] = templ->swizzle_g;
view->swizzle[2] = templ->swizzle_b;
}
assert(hwformat != ~0);
- view->format = tex->tx_format;
+ r300_texture_setup_format_state(r300_screen(pipe->screen), tex,
+ templ->format, 0,
+ width0_override, height0_override,
+ &view->format);
view->format.format1 |= hwformat;
if (is_r500) {
view->format.format2 |= r500_tx_format_msb_bit(templ->format);
return (struct pipe_sampler_view*)view;
}
+static struct pipe_sampler_view *
+r300_create_sampler_view(struct pipe_context *pipe,
+ struct pipe_resource *texture,
+ const struct pipe_sampler_view *templ)
+{
+ return r300_create_sampler_view_custom(pipe, texture, templ,
+ r300_resource(texture)->tex.width0,
+ r300_resource(texture)->tex.height0);
+}
+
+
static void
r300_sampler_view_destroy(struct pipe_context *pipe,
struct pipe_sampler_view *view)
offset = tex->tex.offset_in_bytes[base_level];
r300_texture_setup_format_state(r300->screen, tex,
+ view->base.format,
base_level,
+ view->width0_override,
+ view->height0_override,
&texstate->format);
texstate->format.tile_config |= offset & 0xffffffe0;
assert((offset & 0x1f) == 0);
texstate->format.format1 |= view->texcache_region;
/* Depth textures are kinda special. */
- if (util_format_is_depth_or_stencil(tex->b.b.b.format)) {
+ if (util_format_is_depth_or_stencil(view->base.format)) {
unsigned char depth_swizzle[4];
if (!r300->screen->caps.is_r500 &&
- util_format_get_blocksizebits(tex->b.b.b.format) == 32) {
+ util_format_get_blocksizebits(view->base.format) == 32) {
/* X24x8 is sampled as Y16X16 on r3xx-r4xx.
* The depth here is at the Y component. */
for (j = 0; j < 4; j++)
}
if (r300->screen->caps.dxtc_swizzle &&
- util_format_is_compressed(tex->b.b.b.format)) {
+ util_format_is_compressed(view->base.format)) {
texstate->filter1 |= R400_DXTC_SWIZZLE_ENABLE;
}
}
/* Float textures only support nearest and mip-nearest filtering. */
- if (util_format_is_float(tex->b.b.b.format)) {
+ if (util_format_is_float(view->base.format)) {
/* No MAG linear filtering. */
if ((texstate->filter0 & R300_TX_MAG_FILTER_MASK) ==
R300_TX_MAG_FILTER_LINEAR) {
void r300_texture_setup_format_state(struct r300_screen *screen,
struct r300_resource *tex,
+ enum pipe_format format,
unsigned level,
+ unsigned width0_override,
+ unsigned height0_override,
struct r300_texture_format_state *out)
{
struct pipe_resource *pt = &tex->b.b.b;
unsigned width, height, depth;
unsigned txwidth, txheight, txdepth;
- width = u_minify(desc->width0, level);
- height = u_minify(desc->height0, level);
+ width = u_minify(width0_override, level);
+ height = u_minify(height0_override, level);
depth = u_minify(desc->depth0, level);
txwidth = (width - 1) & 0x7ff;
R300_TX_DEPTH(txdepth);
if (desc->uses_stride_addressing) {
+ unsigned stride =
+ r300_stride_to_width(format, desc->stride_in_bytes[level]);
/* rectangles love this */
out->format0 |= R300_TX_PITCH_EN;
- out->format2 = (desc->stride_in_pixels[level] - 1) & 0x1fff;
+ out->format2 = (stride - 1) & 0x1fff;
}
if (pt->target == PIPE_TEXTURE_CUBE) {
{
struct r300_resource *tex = r300_resource(surf->base.texture);
unsigned level = surf->base.u.tex.level;
+ unsigned stride =
+ r300_stride_to_width(surf->base.format, tex->tex.stride_in_bytes[level]);
/* Set framebuffer state. */
if (util_format_is_depth_or_stencil(surf->base.format)) {
surf->pitch =
- tex->tex.stride_in_pixels[level] |
+ stride |
R300_DEPTHMACROTILE(tex->tex.macrotile[level]) |
R300_DEPTHMICROTILE(tex->tex.microtile);
surf->format = r300_translate_zsformat(surf->base.format);
surf->pitch_hiz = tex->tex.hiz_stride_in_pixels[level];
} else {
surf->pitch =
- tex->tex.stride_in_pixels[level] |
+ stride |
r300_translate_colorformat(surf->base.format) |
R300_COLOR_TILE(tex->tex.macrotile[level]) |
R300_COLOR_MICROTILE(tex->tex.microtile);
}
}
-void r300_resource_set_properties(struct pipe_screen *screen,
+static void r300_resource_set_properties(struct pipe_screen *screen,
struct pipe_resource *tex,
const struct pipe_resource *new_properties)
{
util_format_short_name(new_properties->format));
r300_texture_desc_init(rscreen, res, new_properties);
- r300_texture_setup_format_state(rscreen, res, 0, &res->tx_format);
}
static void r300_texture_destroy(struct pipe_screen *screen,
/* Not required to implement u_resource_vtbl, consider moving to another file:
*/
-struct pipe_surface* r300_create_surface(struct pipe_context * ctx,
+struct pipe_surface* r300_create_surface_custom(struct pipe_context * ctx,
struct pipe_resource* texture,
- const struct pipe_surface *surf_tmpl)
+ const struct pipe_surface *surf_tmpl,
+ unsigned width0_override,
+ unsigned height0_override)
{
struct r300_resource* tex = r300_resource(texture);
struct r300_surface* surface = CALLOC_STRUCT(r300_surface);
pipe_resource_reference(&surface->base.texture, texture);
surface->base.context = ctx;
surface->base.format = surf_tmpl->format;
- surface->base.width = u_minify(texture->width0, level);
- surface->base.height = u_minify(texture->height0, level);
+ surface->base.width = u_minify(width0_override, level);
+ surface->base.height = u_minify(height0_override, level);
surface->base.usage = surf_tmpl->usage;
surface->base.u.tex.level = level;
surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
surface->cbzb_width = align(surface->base.width, 64);
/* Height must be aligned to the size of a tile. */
- tile_height = r300_get_pixel_alignment(tex->b.b.b.format,
+ tile_height = r300_get_pixel_alignment(surface->base.format,
tex->b.b.b.nr_samples,
tex->tex.microtile,
tex->tex.macrotile[level],
return &surface->base;
}
+struct pipe_surface* r300_create_surface(struct pipe_context * ctx,
+ struct pipe_resource* texture,
+ const struct pipe_surface *surf_tmpl)
+{
+ return r300_create_surface_custom(ctx, texture, surf_tmpl,
+ texture->width0,
+ texture->height0);
+}
+
/* Not required to implement u_resource_vtbl, consider moving to another file:
*/
void r300_surface_destroy(struct pipe_context *ctx, struct pipe_surface* s)
uint32_t r500_tx_format_msb_bit(enum pipe_format format);
-void r300_resource_set_properties(struct pipe_screen *screen,
- struct pipe_resource *tex,
- const struct pipe_resource *new_properties);
-
boolean r300_is_colorbuffer_format_supported(enum pipe_format format);
boolean r300_is_zs_format_supported(enum pipe_format format);
void r300_texture_setup_format_state(struct r300_screen *screen,
struct r300_resource *tex,
+ enum pipe_format format,
unsigned level,
+ unsigned width0_override,
+ unsigned height0_override,
struct r300_texture_format_state *out);
boolean r300_resource_get_handle(struct pipe_screen* screen,
r300_texture_create(struct pipe_screen* screen,
const struct pipe_resource* templ);
+struct pipe_surface* r300_create_surface_custom(struct pipe_context * ctx,
+ struct pipe_resource* texture,
+ const struct pipe_surface *surf_tmpl,
+ unsigned width0_override,
+ unsigned height0_override);
struct pipe_surface* r300_create_surface(struct pipe_context *ctx,
struct pipe_resource* texture,
}
/* Get a width in pixels from a stride in bytes. */
-static unsigned stride_to_width(enum pipe_format format,
- unsigned stride_in_bytes)
+unsigned r300_stride_to_width(enum pipe_format format,
+ unsigned stride_in_bytes)
{
return (stride_in_bytes / util_format_get_blocksize(format)) *
util_format_get_blockwidth(format);
tex->tex.size_in_bytes = tex->tex.offset_in_bytes[i] + size;
tex->tex.layer_size_in_bytes[i] = layer_size;
tex->tex.stride_in_bytes[i] = stride;
- tex->tex.stride_in_pixels[i] = stride_to_width(tex->b.b.b.format, stride);
tex->tex.cbzb_allowed[i] = tex->tex.cbzb_allowed[i] && aligned_for_cbzb;
SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d "
tex->tex.uses_stride_addressing =
!util_is_power_of_two(tex->b.b.b.width0) ||
(tex->tex.stride_in_bytes_override &&
- stride_to_width(tex->b.b.b.format,
+ r300_stride_to_width(tex->b.b.b.format,
tex->tex.stride_in_bytes_override) != tex->b.b.b.width0);
tex->tex.is_npot =
for (i = 0; i <= tex->b.b.b.last_level; i++) {
unsigned zcomp_numdw, zcompsize, hiz_numdw, stride, height;
- stride = align(tex->tex.stride_in_pixels[i], 16);
+ stride = r300_stride_to_width(tex->b.b.b.format,
+ tex->tex.stride_in_bytes[i]);
+ stride = align(stride, 16);
height = u_minify(tex->b.b.b.height0, i);
/* The 8x8 compression mode needs macrotiling. */
func,
tex->tex.macrotile[0] ? "YES" : " NO",
tex->tex.microtile ? "YES" : " NO",
- tex->tex.stride_in_pixels[0],
+ r300_stride_to_width(tex->b.b.b.format, tex->tex.stride_in_bytes[0]),
tex->b.b.b.width0, tex->b.b.b.height0, tex->b.b.b.depth0,
tex->b.b.b.last_level, tex->tex.size_in_bytes,
util_format_short_name(tex->b.b.b.format));
unsigned r300_texture_get_offset(struct r300_resource *tex,
unsigned level, unsigned layer);
+unsigned r300_stride_to_width(enum pipe_format format,
+ unsigned stride_in_bytes);
+
#endif
struct r300_resource *tex = r300_resource(texture);
struct r300_transfer *trans;
struct pipe_resource base;
- boolean referenced_cs, referenced_hw, blittable;
- const struct util_format_description *desc =
- util_format_description(texture->format);
+ boolean referenced_cs, referenced_hw;
referenced_cs =
r300->rws->cs_is_buffer_referenced(r300->cs, tex->cs_buf);
r300->rws->buffer_is_busy(tex->buf, RADEON_USAGE_READWRITE);
}
- blittable = desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ||
- desc->layout == UTIL_FORMAT_LAYOUT_S3TC ||
- desc->layout == UTIL_FORMAT_LAYOUT_RGTC;
-
trans = CALLOC_STRUCT(r300_transfer);
if (trans) {
/* Initialize the transfer object. */
* for this transfer.
* Also make write transfers pipelined. */
if (tex->tex.microtile || tex->tex.macrotile[level] ||
- (referenced_hw && blittable && !(usage & PIPE_TRANSFER_READ))) {
+ (referenced_hw && !(usage & PIPE_TRANSFER_READ) &&
+ r300_is_blit_supported(texture->format))) {
if (r300->blitter->running) {
fprintf(stderr, "r300: ERROR: Blitter recursion in texture_get_transfer.\n");
os_break();