diff options
Diffstat (limited to 'src/gallium/drivers/r300')
34 files changed, 1625 insertions, 1940 deletions
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index a43e83c0d36..4f86db39926 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -55,11 +55,12 @@ static void r300_blitter_begin(struct r300_context* r300, enum r300_blitter_op o util_blitter_save_viewport(r300->blitter, &r300->viewport); util_blitter_save_clip(r300->blitter, (struct pipe_clip_state*)r300->clip_state.state); util_blitter_save_vertex_elements(r300->blitter, r300->velems); - util_blitter_save_vertex_buffers(r300->blitter, r300->vertex_buffer_count, - r300->vertex_buffer); + util_blitter_save_vertex_buffers(r300->blitter, r300->vbuf_mgr->nr_vertex_buffers, + r300->vbuf_mgr->vertex_buffer); - if (op & (R300_CLEAR_SURFACE | R300_COPY)) + if (op & (R300_CLEAR_SURFACE | R300_COPY)) { util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); + } if (op & R300_COPY) { struct r300_textures_state* state = @@ -108,6 +109,14 @@ static boolean r300_cbzb_clear_allowed(struct r300_context *r300, return r300_surface(fb->cbufs[0])->cbzb_allowed; } +static boolean r300_fast_zclear_allowed(struct r300_context *r300) +{ + struct pipe_framebuffer_state *fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; + + return r300_resource(fb->zsbuf->texture)->tex.zmask_dwords[fb->zsbuf->u.tex.level]; +} + static uint32_t r300_depth_clear_value(enum pipe_format format, double depth, unsigned stencil) { @@ -132,37 +141,46 @@ static void r300_clear(struct pipe_context* pipe, double depth, unsigned stencil) { - /* My notes about fastfill: + /* My notes about Zbuffer compression: * - * 1) Only the zbuffer is cleared. + * 1) The zbuffer must be micro-tiled and whole microtiles must be + * written if compression is enabled. If microtiling is disabled, + * it locks up. * - * 2) The zbuffer must be micro-tiled and whole microtiles must be - * written. If microtiling is disabled, it locks up. + * 2) There is ZMASK RAM which contains a compressed zbuffer. + * Each dword of the Z Mask contains compression information + * for 16 4x4 pixel tiles, that is 2 bits for each tile. + * On chips with 2 Z pipes, every other dword maps to a different + * pipe. On newer chipsets, there is a new compression mode + * with 8x8 pixel tiles per 2 bits. * - * 3) There is Z Mask RAM which contains a compressed zbuffer and - * it interacts with fastfill. We should figure out how to use it - * to get more performance. - * This is what we know about the Z Mask: + * 3) The FASTFILL bit has nothing to do with filling. It only tells hw + * it should look in the ZMASK RAM first before fetching from a real + * zbuffer. * - * Each dword of the Z Mask contains compression information - * for 16 4x4 pixel blocks, that is 2 bits for each block. - * On chips with 2 Z pipes, every other dword maps to a different - * pipe. + * 4) If a pixel is in a cleared state, ZB_DEPTHCLEARVALUE is returned + * during zbuffer reads instead of the value that is actually stored + * in the zbuffer memory. A pixel is in a cleared state when its ZMASK + * is equal to 0. Therefore, if you clear ZMASK with zeros, you may + * leave the zbuffer memory uninitialized, but then you must enable + * compression, so that the ZMASK RAM is actually used. * - * 4) ZB_DEPTHCLEARVALUE is used to clear the zbuffer and the Z Mask must - * be equal to 0. (clear the Z Mask RAM with zeros) + * 5) Each 4x4 (or 8x8) tile is automatically decompressed and recompressed + * during zbuffer updates. A special decompressing operation should be + * used to fully decompress a zbuffer, which basically just stores all + * compressed tiles in ZMASK to the zbuffer memory. * - * 5) For 16-bit zbuffer, compression causes a hung with one or + * 6) For a 16-bit zbuffer, compression causes a hung with one or * two samples and should not be used. * - * 6) FORCE_COMPRESSED_STENCIL_VALUE should be enabled for stencil clears + * 7) FORCE_COMPRESSED_STENCIL_VALUE should be enabled for stencil clears * to avoid needless decompression. * - * 7) Fastfill must not be used if reading of compressed Z data is disabled + * 8) Fastfill must not be used if reading of compressed Z data is disabled * and writing of compressed Z data is enabled (RD/WR_COMP_ENABLE), * i.e. it cannot be used to compress the zbuffer. * - * 8) ZB_CB_CLEAR does not interact with fastfill in any way. + * 9) ZB_CB_CLEAR does not interact with zbuffer compression in any way. * * - Marek */ @@ -172,32 +190,30 @@ static void r300_clear(struct pipe_context* pipe, (struct pipe_framebuffer_state*)r300->fb_state.state; struct r300_hyperz_state *hyperz = (struct r300_hyperz_state*)r300->hyperz_state.state; - struct r300_texture *zstex = - fb->zsbuf ? r300_texture(fb->zsbuf->texture) : NULL; + struct r300_resource *zstex = + fb->zsbuf ? r300_resource(fb->zsbuf->texture) : NULL; uint32_t width = fb->width; uint32_t height = fb->height; boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ); uint32_t hyperz_dcv = hyperz->zb_depthclearvalue; - /* Decompress zbuffers that are bound as textures. If we didn't flush here, - * it would happen inside the blitter when updating derived state, - * causing a blitter operation to be called from inside the blitter, - * which would overwrite saved states and they would never get restored. */ - r300_flush_depth_textures(r300); - /* Enable fast Z clear. * The zbuffer must be in micro-tiled mode, otherwise it locks up. */ if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && can_hyperz) { hyperz_dcv = hyperz->zb_depthclearvalue = r300_depth_clear_value(fb->zsbuf->format, depth, stencil); - r300_mark_fb_state_dirty(r300, R300_CHANGED_ZCLEAR_FLAG); - if (zstex->zmask_mem[fb->zsbuf->u.tex.level]) { + if (r300_fast_zclear_allowed(r300)) { r300_mark_atom_dirty(r300, &r300->zmask_clear); buffers &= ~PIPE_CLEAR_DEPTHSTENCIL; } + if (zstex->hiz_mem[fb->zsbuf->u.tex.level]) r300_mark_atom_dirty(r300, &r300->hiz_clear); + + /* XXX Change this to r300_mark_atom_dirty(r300, &r300->hyperz_state); + * once hiz offset is constant. */ + r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG); } /* Enable CBZB clear. */ @@ -211,7 +227,7 @@ static void r300_clear(struct pipe_context* pipe, height = surf->cbzb_height; r300->cbzb_clear = TRUE; - r300_mark_fb_state_dirty(r300, R300_CHANGED_CBZB_FLAG); + r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG); } /* Clear. */ @@ -225,7 +241,7 @@ static void r300_clear(struct pipe_context* pipe, buffers, rgba, depth, stencil); r300_blitter_end(r300); } else if (r300->zmask_clear.dirty) { - /* Just clear zmask and hiz now, this does not use a standard draw + /* Just clear zmask and hiz now, this does not use the standard draw * procedure. */ unsigned dwords; @@ -257,16 +273,15 @@ static void r300_clear(struct pipe_context* pipe, if (r300->cbzb_clear) { r300->cbzb_clear = FALSE; hyperz->zb_depthclearvalue = hyperz_dcv; - r300_mark_fb_state_dirty(r300, R300_CHANGED_CBZB_FLAG); + r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG); } /* Enable fastfill and/or hiz. * * If we cleared zmask/hiz, it's in use now. The Hyper-Z state update * looks if zmask/hiz is in use and enables fastfill accordingly. */ - if (zstex && - (zstex->zmask_in_use[fb->zsbuf->u.tex.level] || - zstex->hiz_in_use[fb->zsbuf->u.tex.level])) { + if (r300->zmask_in_use || + (zstex && zstex->hiz_in_use[fb->zsbuf->u.tex.level])) { r300_mark_atom_dirty(r300, &r300->hyperz_state); } } @@ -280,16 +295,16 @@ static void r300_clear_render_target(struct pipe_context *pipe, { struct r300_context *r300 = r300_context(pipe); - /* Decompress zbuffers that are bound as textures. If we didn't flush here, - * it would happen inside the blitter when updating derived state, - * causing a blitter operation to be called from inside the blitter, - * which would overwrite saved states and they would never get restored. */ - r300_flush_depth_textures(r300); + r300->zmask_locked = TRUE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); r300_blitter_begin(r300, R300_CLEAR_SURFACE); util_blitter_clear_render_target(r300->blitter, dst, rgba, dstx, dsty, width, height); r300_blitter_end(r300); + + r300->zmask_locked = FALSE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); } /* Clear a region of a depth stencil surface. */ @@ -302,83 +317,70 @@ static void r300_clear_depth_stencil(struct pipe_context *pipe, unsigned width, unsigned height) { struct r300_context *r300 = r300_context(pipe); + struct pipe_framebuffer_state *fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; - /* Decompress zbuffers that are bound as textures. If we didn't flush here, - * it would happen inside the blitter when updating derived state, - * causing a blitter operation to be called from inside the blitter, - * which would overwrite saved states and they would never get restored. */ - r300_flush_depth_textures(r300); + if (r300->zmask_in_use && !r300->zmask_locked) { + if (fb->zsbuf->texture == dst->texture) { + r300_decompress_zmask(r300); + } else { + r300->zmask_locked = TRUE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); + } + } r300_blitter_begin(r300, R300_CLEAR_SURFACE); util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil, dstx, dsty, width, height); r300_blitter_end(r300); + + if (r300->zmask_locked) { + r300->zmask_locked = FALSE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); + } } -/* Flush a depth stencil buffer. */ -static void r300_flush_depth_stencil(struct pipe_context *pipe, - struct pipe_resource *dst, - unsigned level, - unsigned layer) +void r300_decompress_zmask(struct r300_context *r300) { - struct r300_context *r300 = r300_context(pipe); - struct pipe_surface *dstsurf, surf_tmpl; - struct r300_texture *tex = r300_texture(dst); + struct pipe_framebuffer_state *fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; - if (!tex->zmask_mem[level]) - return; - if (!tex->zmask_in_use[level]) + if (!r300->zmask_in_use || r300->zmask_locked) return; - surf_tmpl.format = dst->format; - surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; - surf_tmpl.u.tex.level = level; - surf_tmpl.u.tex.first_layer = layer; - surf_tmpl.u.tex.last_layer = layer; - dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl); + r300->zmask_decompress = TRUE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); - r300->z_decomp_rd = TRUE; - - r300_blitter_begin(r300, R300_CLEAR_SURFACE); - util_blitter_flush_depth_stencil(r300->blitter, dstsurf); + r300_blitter_begin(r300, R300_CLEAR); + util_blitter_clear_depth_custom(r300->blitter, fb->width, fb->height, 0, + r300->dsa_decompress_zmask); r300_blitter_end(r300); - r300->z_decomp_rd = FALSE; - tex->zmask_in_use[level] = FALSE; - pipe_surface_reference(&dstsurf, NULL); + r300->zmask_decompress = FALSE; + r300->zmask_in_use = FALSE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); } -/* We can't use compressed zbuffers as samplers. */ -void r300_flush_depth_textures(struct r300_context *r300) +void r300_decompress_zmask_locked_unsafe(struct r300_context *r300) { - struct r300_textures_state *state = - (struct r300_textures_state*)r300->textures_state.state; - unsigned i, level; - unsigned count = MIN2(state->sampler_view_count, - state->sampler_state_count); - - if (r300->z_decomp_rd) - return; - - for (i = 0; i < count; i++) - if (state->sampler_views[i] && state->sampler_states[i]) { - struct pipe_resource *tex = state->sampler_views[i]->base.texture; - - if (tex->target == PIPE_TEXTURE_3D || - tex->target == PIPE_TEXTURE_CUBE) - continue; + struct pipe_framebuffer_state fb = {0}; + fb.width = r300->locked_zbuffer->width; + fb.height = r300->locked_zbuffer->height; + fb.nr_cbufs = 0; + fb.zsbuf = r300->locked_zbuffer; + + r300->context.set_framebuffer_state(&r300->context, &fb); + r300_decompress_zmask(r300); +} - /* Ignore non-depth textures. - * Also ignore reinterpreted depth textures, e.g. resource_copy. */ - if (!util_format_is_depth_or_stencil(tex->format)) - continue; +void r300_decompress_zmask_locked(struct r300_context *r300) +{ + struct pipe_framebuffer_state saved_fb = {0}; - for (level = 0; level <= tex->last_level; level++) - if (r300_texture(tex)->zmask_in_use[level]) { - /* We don't handle 3D textures and cubemaps yet. */ - r300_flush_depth_stencil(&r300->context, tex, level, 0); - } - } + util_copy_framebuffer_state(&saved_fb, r300->fb_state.state); + r300_decompress_zmask_locked_unsafe(r300); + r300->context.set_framebuffer_state(&r300->context, &saved_fb); + util_unreference_framebuffer_state(&saved_fb); } /* Copy a block of pixels from one surface to another using HW. */ @@ -393,8 +395,6 @@ static void r300_hw_copy_region(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); r300_blitter_begin(r300, R300_COPY); - - /* Do a copy */ util_blitter_copy_region(r300->blitter, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box, TRUE); r300_blitter_end(r300); @@ -409,56 +409,102 @@ static void r300_resource_copy_region(struct pipe_context *pipe, unsigned src_level, const struct pipe_box *src_box) { - enum pipe_format old_format = dst->format; - enum pipe_format new_format = old_format; - boolean is_depth; - - if (!pipe->screen->is_format_supported(pipe->screen, - old_format, src->target, - src->nr_samples, - PIPE_BIND_RENDER_TARGET | - PIPE_BIND_SAMPLER_VIEW, 0) && - util_format_is_plain(old_format)) { - switch (util_format_get_blocksize(old_format)) { + 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); + struct pipe_box box; + + if (r300->zmask_in_use && !r300->zmask_locked) { + if (fb->zsbuf->texture == src || + fb->zsbuf->texture == dst) { + r300_decompress_zmask(r300); + } else { + r300->zmask_locked = TRUE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); + } + } + + /* 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, 0) || + !pipe->screen->is_format_supported(pipe->screen, + dst->format, dst->target, + dst->nr_samples, + PIPE_BIND_RENDER_TARGET, 0))) { + switch (util_format_get_blocksize(old_dst.format)) { case 1: - new_format = PIPE_FORMAT_I8_UNORM; + new_dst.format = PIPE_FORMAT_I8_UNORM; break; case 2: - new_format = PIPE_FORMAT_B4G4R4A4_UNORM; + new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM; break; case 4: - new_format = PIPE_FORMAT_B8G8R8A8_UNORM; + new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM; break; case 8: - new_format = PIPE_FORMAT_R16G16B16A16_UNORM; + new_dst.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(old_format)); + util_format_short_name(dst->format)); } + new_src.format = new_dst.format; } - is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; - if (is_depth) { - r300_flush_depth_stencil(pipe, src, src_level, src_box->z); - } + /* Handle compressed formats. */ + if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { + switch (util_format_get_blocksize(old_dst.format)) { + case 8: + /* 1 pixel = 4 bits, + * we set 1 pixel = 2 bytes ===> 4 times larger pixels. */ + new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM; + break; + case 16: + /* 1 pixel = 8 bits, + * we set 1 pixel = 4 bytes ===> 4 times larger pixels. */ + new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + } - if (old_format != new_format) { - r300_texture_reinterpret_format(pipe->screen, - dst, new_format); - r300_texture_reinterpret_format(pipe->screen, - src, new_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; + dsty /= 4; + box = *src_box; + box.y /= 4; + box.height = (box.height + 3) / 4; + src_box = &box; } + if (old_src.format != new_src.format) + r300_resource_set_properties(pipe->screen, src, 0, &new_src); + if (old_dst.format != new_dst.format) + r300_resource_set_properties(pipe->screen, dst, 0, &new_dst); + r300_hw_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); - if (old_format != new_format) { - r300_texture_reinterpret_format(pipe->screen, - dst, old_format); - r300_texture_reinterpret_format(pipe->screen, - src, old_format); + if (old_src.format != new_src.format) + r300_resource_set_properties(pipe->screen, src, 0, &old_src); + if (old_dst.format != new_dst.format) + r300_resource_set_properties(pipe->screen, dst, 0, &old_dst); + + if (r300->zmask_locked) { + r300->zmask_locked = FALSE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); } } diff --git a/src/gallium/drivers/r300/r300_cb.h b/src/gallium/drivers/r300/r300_cb.h index 9d3d4fc1b19..b373937a1f9 100644 --- a/src/gallium/drivers/r300/r300_cb.h +++ b/src/gallium/drivers/r300/r300_cb.h @@ -61,40 +61,52 @@ * that they neatly hide away, and don't have the cost of function setup, so * we're going to use them. */ -#ifdef DEBUG -#define CB_DEBUG(x) x -#else -#define CB_DEBUG(x) -#endif - - /** * Command buffer setup. */ +#ifdef DEBUG + #define CB_LOCALS \ - CB_DEBUG(int cs_count = 0;) \ + int cs_count = 0; \ uint32_t *cs_ptr = NULL; \ - CB_DEBUG((void) cs_count;) (void) cs_ptr; + (void) cs_count; (void) cs_ptr -#define NEW_CB(ptr, size) do { \ - assert(sizeof(*ptr) == sizeof(uint32_t)); \ - cs_ptr = (ptr) = (uint32_t*)malloc((size) * sizeof(uint32_t)); \ - CB_DEBUG(cs_count = size;) \ +#define BEGIN_CB(ptr, size) do { \ + assert(sizeof(*(ptr)) == sizeof(uint32_t)); \ + cs_count = (size); \ + cs_ptr = (ptr); \ } while (0) -#define BEGIN_CB(ptr, size) do { \ - assert(sizeof(*ptr) == sizeof(uint32_t)); \ - cs_ptr = ptr; \ - CB_DEBUG(cs_count = size;) \ +#define NEW_CB(ptr, size) \ + do { \ + assert(sizeof(*(ptr)) == sizeof(uint32_t)); \ + cs_count = (size); \ + cs_ptr = (ptr) = (uint32_t*)malloc((size) * sizeof(uint32_t)); \ } while (0) #define END_CB do { \ - CB_DEBUG(if (cs_count != 0) \ + if (cs_count != 0) \ debug_printf("r300: Warning: cs_count off by %d at (%s, %s:%i)\n", \ - cs_count, __FUNCTION__, __FILE__, __LINE__);) \ + cs_count, __FUNCTION__, __FILE__, __LINE__); \ } while (0) +#define CB_USED_DW(x) cs_count -= x + +#else + +#define CB_LOCALS \ + uint32_t *cs_ptr = NULL; (void) cs_ptr + +#define NEW_CB(ptr, size) \ + cs_ptr = (ptr) = (uint32_t*)malloc((size) * sizeof(uint32_t)) + +#define BEGIN_CB(ptr, size) cs_ptr = (ptr) +#define END_CB +#define CB_USED_DW(x) + +#endif + /** * Storing pure DWORDs. @@ -103,13 +115,13 @@ #define OUT_CB(value) do { \ *cs_ptr = (value); \ cs_ptr++; \ - CB_DEBUG(cs_count--;) \ + CB_USED_DW(1); \ } while (0) #define OUT_CB_TABLE(values, count) do { \ memcpy(cs_ptr, values, count * sizeof(uint32_t)); \ cs_ptr += count; \ - CB_DEBUG(cs_count -= count;) \ + CB_USED_DW(count); \ } while (0) #define OUT_CB_32F(value) \ diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 2b183f62c56..1968d0feb35 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -241,7 +241,6 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x5A42: caps->family = CHIP_FAMILY_RS400; caps->has_tcl = FALSE; - caps->zmask_ram = RV3xx_ZMASK_SIZE; break; case 0x5A61: @@ -424,5 +423,6 @@ void r300_parse_chipset(struct r300_capabilities* caps) } caps->is_rv350 = caps->family >= CHIP_FAMILY_RV350; + caps->z_compress = caps->is_rv350 ? R300_ZCOMP_8X8 : R300_ZCOMP_4X4; caps->dxtc_swizzle = caps->is_r400 || caps->is_r500; } diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index f2035d20092..0be161fa07a 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -33,6 +33,13 @@ #define PIPE_ZMASK_SIZE 4096 #define RV3xx_ZMASK_SIZE 5120 +/* The size of a compressed tile. Each compressed tile takes 2 bits + * in the ZMASK RAM, so there is always 16 tiles per one dword. */ +enum r300_zmask_compression { + R300_ZCOMP_4X4 = 4, + R300_ZCOMP_8X8 = 8 +}; + /* Structure containing all the possible information about a specific Radeon * in the R3xx, R4xx, and R5xx families. */ struct r300_capabilities { @@ -50,10 +57,12 @@ struct r300_capabilities { unsigned num_tex_units; /* Whether or not TCL is physically present */ boolean has_tcl; - /* Some chipsets do not have HiZ RAM - other have varying amounts . */ + /* Some chipsets do not have HiZ RAM - other have varying amounts. */ int hiz_ram; - /* some chipsets have zmask ram per pipe some don't */ + /* Some chipsets have zmask ram per pipe some don't. */ int zmask_ram; + /* Compression mode for ZMASK. */ + enum r300_zmask_compression z_compress; /* Whether or not this is RV350 or newer, including all r400 and r500 * chipsets. The differences compared to the oldest r300 chips are: * - Blend LTE/GTE thresholds diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 91263ad7bcd..9f85bd4ce5f 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -35,26 +35,24 @@ #include "r300_screen_buffer.h" #include "r300_winsys.h" -#ifdef HAVE_LLVM -#include "gallivm/lp_bld_init.h" -#endif - static void r300_update_num_contexts(struct r300_screen *r300screen, int diff) { + pipe_mutex_lock(r300screen->num_contexts_mutex); if (diff > 0) { - p_atomic_inc(&r300screen->num_contexts); + r300screen->num_contexts++; if (r300screen->num_contexts > 1) util_slab_set_thread_safety(&r300screen->pool_buffers, UTIL_SLAB_MULTITHREADED); } else { - p_atomic_dec(&r300screen->num_contexts); + r300screen->num_contexts--; if (r300screen->num_contexts <= 1) util_slab_set_thread_safety(&r300screen->pool_buffers, UTIL_SLAB_SINGLETHREADED); } + pipe_mutex_unlock(r300screen->num_contexts_mutex); } static void r300_release_referenced_objects(struct r300_context *r300) @@ -87,17 +85,14 @@ static void r300_release_referenced_objects(struct r300_context *r300) /* The SWTCL VBO. */ pipe_resource_reference(&r300->vbo, NULL); - /* Vertex buffers. */ - for (i = 0; i < r300->vertex_buffer_count; i++) { - pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); - pipe_resource_reference(&r300->valid_vertex_buffer[i], NULL); - } - /* If there are any queries pending or not destroyed, remove them now. */ foreach_s(query, temp, &r300->query_list) { remove_from_list(query); FREE(query); } + + r300->context.delete_depth_stencil_alpha_state(&r300->context, + r300->dsa_decompress_zmask); } static void r300_destroy_context(struct pipe_context* context) @@ -106,28 +101,15 @@ static void r300_destroy_context(struct pipe_context* context) if (r300->blitter) util_blitter_destroy(r300->blitter); - if (r300->draw) { + if (r300->draw) draw_destroy(r300->draw); -#ifdef HAVE_LLVM - gallivm_destroy(r300->gallivm); -#endif - } - - if (r300->upload_vb) - u_upload_destroy(r300->upload_vb); - if (r300->upload_ib) - u_upload_destroy(r300->upload_ib); - - if (r300->tran.translate_cache) - translate_cache_destroy(r300->tran.translate_cache); + if (r300->vbuf_mgr) + u_vbuf_mgr_destroy(r300->vbuf_mgr); /* XXX: This function assumes r300->query_list was initialized */ r300_release_referenced_objects(r300); - if (r300->zmask_mm) - r300_hyperz_destroy_mm(r300); - if (r300->cs) r300->rws->cs_destroy(r300->cs); @@ -247,7 +229,7 @@ static boolean r300_setup_atoms(struct r300_context* r300) if (has_hiz_ram) R300_INIT_ATOM(hiz_clear, 0); /* zmask clear */ - R300_INIT_ATOM(zmask_clear, 0); + R300_INIT_ATOM(zmask_clear, 4); } /* ZB (unpipelined), SU. */ R300_INIT_ATOM(query_start, 4); @@ -432,12 +414,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, if (!r300screen->caps.has_tcl) { /* Create a Draw. This is used for SW TCL. */ -#ifdef HAVE_LLVM - r300->gallivm = gallivm_create(); - r300->draw = draw_create_gallivm(&r300->context, r300->gallivm); -#else r300->draw = draw_create(&r300->context); -#endif if (r300->draw == NULL) goto fail; /* Enable our renderer. */ @@ -456,6 +433,13 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300_init_state_functions(r300); r300_init_resource_functions(r300); + r300->vbuf_mgr = u_vbuf_mgr_create(&r300->context, 1024 * 1024, 16, + PIPE_BIND_VERTEX_BUFFER | + PIPE_BIND_INDEX_BUFFER, + U_VERTEX_FETCH_DWORD_ALIGNED); + if (!r300->vbuf_mgr) + goto fail; + r300->blitter = util_blitter_create(&r300->context); if (r300->blitter == NULL) goto fail; @@ -470,23 +454,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, if (!r300_hyperz_init_mm(r300)) goto fail; - r300->upload_ib = u_upload_create(&r300->context, - 64 * 1024, 16, - PIPE_BIND_INDEX_BUFFER); - - if (r300->upload_ib == NULL) - goto fail; - - r300->upload_vb = u_upload_create(&r300->context, - 1024 * 1024, 16, - PIPE_BIND_VERTEX_BUFFER); - if (r300->upload_vb == NULL) - goto fail; - - r300->tran.translate_cache = translate_cache_create(); - if (r300->tran.translate_cache == NULL) - goto fail; - r300_init_states(&r300->context); /* The KIL opcode needs the first texture unit to be enabled @@ -515,7 +482,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, } { - struct pipe_resource vb = {}; + struct pipe_resource vb; + memset(&vb, 0, sizeof(vb)); vb.target = PIPE_BUFFER; vb.format = PIPE_FORMAT_R8_UNORM; vb.bind = PIPE_BIND_VERTEX_BUFFER; @@ -527,36 +495,44 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->dummy_vb = screen->resource_create(screen, &vb); } + { + struct pipe_depth_stencil_alpha_state dsa; + memset(&dsa, 0, sizeof(dsa)); + dsa.depth.writemask = 1; + + r300->dsa_decompress_zmask = + r300->context.create_depth_stencil_alpha_state(&r300->context, + &dsa); + } + + /* Print driver info. */ +#ifdef NDEBUG + if (DBG_ON(r300, DBG_INFO)) { +#else + { +#endif + fprintf(stderr, + "r300: DRM version: %d.%d.%d, Name: %s, ID: 0x%04x, GB: %d, Z: %d\n" + "r300: GART size: %d MB, VRAM size: %d MB\n" + "r300: AA compression: %s, Z compression: %s, HiZ: %s\n", + rws->get_value(rws, R300_VID_DRM_MAJOR), + rws->get_value(rws, R300_VID_DRM_MINOR), + rws->get_value(rws, R300_VID_DRM_PATCHLEVEL), + screen->get_name(screen), + rws->get_value(rws, R300_VID_PCI_ID), + rws->get_value(rws, R300_VID_GB_PIPES), + rws->get_value(rws, R300_VID_Z_PIPES), + rws->get_value(rws, R300_VID_GART_SIZE) >> 20, + rws->get_value(rws, R300_VID_VRAM_SIZE) >> 20, + rws->get_value(rws, R300_CAN_AACOMPRESS) ? "YES" : "NO", + rws->get_value(rws, R300_CAN_HYPERZ) ? "YES" : "NO", + rws->get_value(rws, R300_CAN_HYPERZ) && + r300->screen->caps.hiz_ram ? "YES" : "NO"); + } + return &r300->context; - fail: +fail: r300_destroy_context(&r300->context); return NULL; } - -void r300_finish(struct r300_context *r300) -{ - struct pipe_framebuffer_state *fb; - unsigned i; - - /* This is a preliminary implementation of glFinish. - * - * The ideal implementation should use something like EmitIrqLocked and - * WaitIrq, or better, real fences. - */ - if (r300->fb_state.state) { - fb = r300->fb_state.state; - - for (i = 0; i < fb->nr_cbufs; i++) { - if (fb->cbufs[i]->texture) { - r300->rws->buffer_wait(r300->rws, - r300_texture(fb->cbufs[i]->texture)->buffer); - return; - } - } - if (fb->zsbuf && fb->zsbuf->texture) { - r300->rws->buffer_wait(r300->rws, - r300_texture(fb->zsbuf->texture)->buffer); - } - } -} diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index e09cf87f733..30073759476 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -30,11 +30,11 @@ #include "pipe/p_context.h" #include "util/u_inlines.h" #include "util/u_transfer.h" - -#include "translate/translate_cache.h" +#include "util/u_vbuf_mgr.h" #include "r300_defines.h" #include "r300_screen.h" +#include "r300_winsys.h" struct u_upload_mgr; struct r300_context; @@ -189,11 +189,6 @@ struct r300_sampler_view { uint32_t texcache_region; }; -struct r300_texture_fb_state { - uint32_t pitch[R300_MAX_TEXTURE_LEVELS]; /* COLORPITCH or DEPTHPITCH. */ - uint32_t format; /* US_OUT_FMT or R300_ZB_FORMAT */ -}; - struct r300_texture_sampler_state { struct r300_texture_format_state format; uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */ @@ -273,14 +268,12 @@ struct r300_query { /* How many results have been written, in dwords. It's incremented * after end_query and flush. */ unsigned num_results; - /* if we've flushed the query */ - boolean flushed; /* if begin has been emitted */ boolean begin_emitted; /* The buffer where query results are stored. */ - struct r300_winsys_buffer *buffer; - struct r300_winsys_cs_buffer *cs_buffer; + struct r300_winsys_bo *buf; + struct r300_winsys_cs_handle *cs_buf; /* The size of the buffer. */ unsigned buffer_size; /* The domain of the buffer. */ @@ -291,28 +284,12 @@ struct r300_query { struct r300_query* next; }; -/* Fence object. - * - * This is a fake fence. Instead of syncing with the fence, we sync - * with the context, which is inefficient but compliant. - * - * This is not a subclass of pipe_fence_handle because pipe_fence_handle is - * never actually fully defined. So, rather than have it as a member, and do - * subclass-style casting, we treat pipe_fence_handle as an opaque, and just - * trust that our state tracker does not ever mess up fence objects. - */ -struct r300_fence { - struct pipe_reference reference; - struct r300_context *ctx; - boolean signalled; -}; - struct r300_surface { struct pipe_surface base; /* Winsys buffer backing the texture. */ - struct r300_winsys_buffer *buffer; - struct r300_winsys_cs_buffer *cs_buffer; + struct r300_winsys_bo *buf; + struct r300_winsys_cs_handle *cs_buf; enum r300_buffer_domain domain; @@ -329,13 +306,9 @@ struct r300_surface { /* Whether the CBZB clear is allowed on the surface. */ boolean cbzb_allowed; - }; struct r300_texture_desc { - /* Parent class. */ - struct u_resource b; - /* Width, height, and depth. * Most of the time, these are equal to pipe_texture::width0, height0, * and depth0. However, NPOT 3D textures must have dimensions aligned @@ -387,27 +360,38 @@ struct r300_texture_desc { /* Whether CBZB fast color clear is allowed on the miplevel. */ boolean cbzb_allowed[R300_MAX_TEXTURE_LEVELS]; + + /* Zbuffer compression info for each miplevel. */ + boolean zcomp8x8[R300_MAX_TEXTURE_LEVELS]; + /* If zero, then disable compression. */ + unsigned zmask_dwords[R300_MAX_TEXTURE_LEVELS]; }; -struct r300_texture { - struct r300_texture_desc desc; +struct r300_resource +{ + struct u_vbuf_resource b; + /* Winsys buffer backing this resource. */ + struct r300_winsys_bo *buf; + struct r300_winsys_cs_handle *cs_buf; enum r300_buffer_domain domain; + unsigned buf_size; + + /* Constant buffers are in user memory. */ + uint8_t *constant_buffer; - /* Pipe buffer backing this texture. */ - struct r300_winsys_buffer *buffer; - struct r300_winsys_cs_buffer *cs_buffer; + /* 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; - /* All bits should be filled in. */ - struct r300_texture_fb_state fb_state; - /* hyper-z memory allocs */ + /* Where the texture starts in the buffer. */ + unsigned tex_offset; + + /* HiZ memory allocations. */ struct mem_block *hiz_mem[R300_MAX_TEXTURE_LEVELS]; - struct mem_block *zmask_mem[R300_MAX_TEXTURE_LEVELS]; - boolean zmask_in_use[R300_MAX_TEXTURE_LEVELS]; boolean hiz_in_use[R300_MAX_TEXTURE_LEVELS]; /* This is the level tiling flags were last time set for. @@ -418,32 +402,16 @@ struct r300_texture { struct r300_vertex_element_state { unsigned count; struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; + unsigned format_size[PIPE_MAX_ATTRIBS]; - /* If (velem[i].src_format != hw_format[i]), the vertex buffer - * referenced by this vertex element cannot be used for rendering and - * its vertex data must be translated to hw_format[i]. */ - enum pipe_format hw_format[PIPE_MAX_ATTRIBS]; - unsigned hw_format_size[PIPE_MAX_ATTRIBS]; + struct u_vbuf_mgr_elements *vmgr_elements; /* The size of the vertex, in dwords. */ unsigned vertex_size_dwords; - /* This might mean two things: - * - src_format != hw_format, as discussed above. - * - src_offset % 4 != 0. */ - boolean incompatible_layout; - struct r300_vertex_stream_state vertex_stream; }; -struct r300_translate_context { - /* Translate cache for incompatible vertex offset/stride/format fallback. */ - struct translate_cache *translate_cache; - - /* Saved and new vertex element state. */ - void *saved_velems, *new_velems; -}; - struct r300_context { /* Parent class */ struct pipe_context context; @@ -456,7 +424,6 @@ struct r300_context { struct r300_screen *screen; /* Draw module. Used mostly for SW TCL. */ - struct gallivm_state *gallivm; struct draw_context* draw; /* Vertex buffer for SW TCL. */ struct pipe_resource* vbo; @@ -471,8 +438,6 @@ struct r300_context { struct blitter_context* blitter; /* Stencil two-sided reference value fallback. */ struct r300_stencilref_context *stencilref_fallback; - /* For translating vertex buffers having incompatible vertex layout. */ - struct r300_translate_context tran; /* The KIL opcode needs the first texture unit to be enabled * on r3xx-r4xx. In order to calm down the CS checker, we bind this @@ -554,14 +519,6 @@ struct r300_context { /* The pointers to the first and the last atom. */ struct r300_atom *first_dirty, *last_dirty; - /* Vertex buffers for Gallium. */ - /* May contain user buffers. */ - struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; - /* Contains only non-user buffers. */ - struct pipe_resource *valid_vertex_buffer[PIPE_MAX_ATTRIBS]; - int vertex_buffer_count; - int vertex_buffer_max_index; - boolean any_user_vbs; /* Vertex elements for Gallium. */ struct r300_vertex_element_state *velems; @@ -588,21 +545,23 @@ struct r300_context { int sprite_coord_enable; /* Whether two-sided color selection is enabled (AKA light_twoside). */ boolean two_sided_color; - /* Incompatible vertex buffer layout? (misaligned stride or buffer_offset) */ - boolean incompatible_vb_layout; -#define R300_Z_COMPRESS_44 1 -#define RV350_Z_COMPRESS_88 2 - int z_compression; + boolean cbzb_clear; - boolean z_decomp_rd; + /* Whether ZMASK is enabled. */ + boolean zmask_in_use; + /* Whether ZMASK is being decompressed. */ + boolean zmask_decompress; + /* Whether ZMASK is locked, i.e. should be disabled and cannot be taken over. */ + boolean zmask_locked; + /* The zbuffer the ZMASK of which is locked. */ + struct pipe_surface *locked_zbuffer; + + void *dsa_decompress_zmask; /* two mem block managers for hiz/zmask ram space */ struct mem_block *hiz_mm; - struct mem_block *zmask_mm; - /* upload managers */ - struct u_upload_mgr *upload_vb; - struct u_upload_mgr *upload_ib; + struct u_vbuf_mgr *vbuf_mgr; struct util_slab_mempool pool_transfers; @@ -612,16 +571,10 @@ struct r300_context { /* const tracking for VS */ int vs_const_base; - /* AOS (PACKET3_3D_LOAD_VBPNTR) command buffer for the case offset=0. */ - uint32_t vertex_arrays_cb[(16 * 3 + 1) / 2]; + /* Vertex array state info */ boolean vertex_arrays_dirty; - - /* Whether any buffer (FB, textures, VBOs) has been set, but buffers - * haven't been validated yet. */ - boolean validate_buffers; - /* Whether user buffers have been validated. */ - boolean upload_vb_validated; - boolean upload_ib_validated; + boolean vertex_arrays_indexed; + int vertex_arrays_offset; }; #define foreach_atom(r300, atom) \ @@ -641,9 +594,9 @@ static INLINE struct r300_surface* r300_surface(struct pipe_surface* surf) return (struct r300_surface*)surf; } -static INLINE struct r300_texture* r300_texture(struct pipe_resource* tex) +static INLINE struct r300_resource* r300_resource(struct pipe_resource* tex) { - return (struct r300_texture*)tex; + return (struct r300_resource*)tex; } static INLINE struct r300_context* r300_context(struct pipe_context* context) @@ -675,7 +628,6 @@ static INLINE void r300_mark_atom_dirty(struct r300_context *r300, struct pipe_context* r300_create_context(struct pipe_screen* screen, void *priv); -void r300_finish(struct r300_context *r300); void r300_flush_cb(void *data); /* Context initialization. */ @@ -688,7 +640,9 @@ void r300_init_state_functions(struct r300_context* r300); void r300_init_resource_functions(struct r300_context* r300); /* r300_blit.c */ -void r300_flush_depth_textures(struct r300_context *r300); +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); /* r300_query.c */ void r300_resume_query(struct r300_context *r300, @@ -696,9 +650,6 @@ void r300_resume_query(struct r300_context *r300, void r300_stop_query(struct r300_context *r300); /* r300_render_translate.c */ -void r300_begin_vertex_translate(struct r300_context *r300, - int min_index, int max_index); -void r300_end_vertex_translate(struct r300_context *r300); void r300_translate_index_buffer(struct r300_context *r300, struct pipe_resource **index_buffer, unsigned *index_size, unsigned index_offset, @@ -714,8 +665,7 @@ void r500_emit_index_bias(struct r300_context *r300, int index_bias); /* r300_state.c */ enum r300_fb_state_change { R300_CHANGED_FB_STATE = 0, - R300_CHANGED_CBZB_FLAG, - R300_CHANGED_ZCLEAR_FLAG, + R300_CHANGED_HYPERZ_FLAG, R300_CHANGED_MULTIWRITE }; diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h index 6726f100e1b..2e52dfa43c6 100644 --- a/src/gallium/drivers/r300/r300_cs.h +++ b/src/gallium/drivers/r300/r300_cs.h @@ -35,12 +35,6 @@ * that they neatly hide away, and don't have the cost of function setup,so * we're going to use them. */ -#ifdef DEBUG -#define CS_DEBUG(x) x -#else -#define CS_DEBUG(x) -#endif - /** * Command submission setup. */ @@ -50,22 +44,29 @@ struct r300_winsys_screen *cs_winsys = (context)->rws; \ int cs_count = 0; (void) cs_count; (void) cs_winsys; +#ifdef DEBUG + #define BEGIN_CS(size) do { \ assert(size <= (R300_MAX_CMDBUF_DWORDS - cs_copy->cdw)); \ - CS_DEBUG(cs_count = size;) \ + cs_count = size; \ } while (0) -#ifdef DEBUG #define END_CS do { \ if (cs_count != 0) \ debug_printf("r300: Warning: cs_count off by %d at (%s, %s:%i)\n", \ cs_count, __FUNCTION__, __FILE__, __LINE__); \ cs_count = 0; \ } while (0) + +#define CS_USED_DW(x) cs_count -= (x) + #else + +#define BEGIN_CS(size) #define END_CS -#endif +#define CS_USED_DW(x) +#endif /** * Writing pure DWORDs. @@ -73,7 +74,7 @@ #define OUT_CS(value) do { \ cs_copy->buf[cs_copy->cdw++] = (value); \ - CS_DEBUG(cs_count--;) \ + CS_USED_DW(1); \ } while (0) #define OUT_CS_32F(value) \ @@ -98,7 +99,7 @@ #define OUT_CS_TABLE(values, count) do { \ memcpy(cs_copy->buf + cs_copy->cdw, values, count * 4); \ cs_copy->cdw += count; \ - CS_DEBUG(cs_count -= count;) \ + CS_USED_DW(count); \ } while (0) @@ -106,27 +107,11 @@ * Writing relocations. */ -#define OUT_CS_RELOC(bo, offset) do { \ - assert(bo); \ - OUT_CS(offset); \ - cs_winsys->cs_write_reloc(cs_copy, bo); \ - CS_DEBUG(cs_count -= 2;) \ -} while (0) - -#define OUT_CS_BUF_RELOC(bo, offset) do { \ - assert(bo); \ - OUT_CS_RELOC(r300_buffer(bo)->cs_buf, offset); \ -} while (0) - -#define OUT_CS_TEX_RELOC(tex, offset) do { \ - assert(tex); \ - OUT_CS_RELOC(tex->cs_buffer, offset); \ -} while (0) - -#define OUT_CS_BUF_RELOC_NO_OFFSET(bo) do { \ - assert(bo); \ - cs_winsys->cs_write_reloc(cs_copy, r300_buffer(bo)->cs_buf); \ - CS_DEBUG(cs_count -= 2;) \ +#define OUT_CS_RELOC(r) do { \ + assert((r)); \ + assert((r)->cs_buf); \ + cs_winsys->cs_write_reloc(cs_copy, (r)->cs_buf); \ + CS_USED_DW(2); \ } while (0) @@ -135,7 +120,7 @@ */ #define WRITE_CS_TABLE(values, count) do { \ - CS_DEBUG(assert(cs_count == 0);) \ + assert(cs_count == 0); \ memcpy(cs_copy->buf + cs_copy->cdw, (values), (count) * 4); \ cs_copy->cdw += (count); \ } while (0) diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c index d6aa90bd053..b60cfd1f248 100644 --- a/src/gallium/drivers/r300/r300_debug.c +++ b/src/gallium/drivers/r300/r300_debug.c @@ -27,6 +27,7 @@ #include <stdio.h> static const struct debug_named_value debug_options[] = { + { "info", DBG_INFO, "Print hardware info"}, { "fp", DBG_FP, "Log fragment program compilation" }, { "vp", DBG_VP, "Log vertex program compilation" }, { "pstat", DBG_P_STAT, "Log vertex/fragment program stats" }, @@ -49,6 +50,8 @@ static const struct debug_named_value debug_options[] = { { "noimmd", DBG_NO_IMMD, "Disable immediate mode" }, { "noopt", DBG_NO_OPT, "Disable shader optimizations" }, { "nocbzb", DBG_NO_CBZB, "Disable fast color clear" }, + { "nozmask", DBG_NO_ZMASK, "Disable zbuffer compression" }, + { "nohiz", DBG_NO_HIZ, "Disable hierarchical zbuffer" }, /* must be last */ DEBUG_NAMED_VALUE_END diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index d14cdcbbaf0..e2e4719ec82 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -89,7 +89,7 @@ static void get_rc_constant_state( struct rc_constant * constant) { struct r300_textures_state* texstate = r300->textures_state.state; - struct r300_texture *tex; + struct r300_resource *tex; assert(constant->Type == RC_CONSTANT_STATE); @@ -101,19 +101,19 @@ static void get_rc_constant_state( /* Factor for converting rectangle coords to * normalized coords. Should only show up on non-r500. */ case RC_STATE_R300_TEXRECT_FACTOR: - tex = r300_texture(texstate->sampler_views[constant->u.State[1]]->base.texture); - vec[0] = 1.0 / tex->desc.width0; - vec[1] = 1.0 / tex->desc.height0; + tex = r300_resource(texstate->sampler_views[constant->u.State[1]]->base.texture); + vec[0] = 1.0 / tex->tex.width0; + vec[1] = 1.0 / tex->tex.height0; vec[2] = 0; vec[3] = 1; break; case RC_STATE_R300_TEXSCALE_FACTOR: - tex = r300_texture(texstate->sampler_views[constant->u.State[1]]->base.texture); + tex = r300_resource(texstate->sampler_views[constant->u.State[1]]->base.texture); /* Add a small number to the texture size to work around rounding errors in hw. */ - vec[0] = tex->desc.b.b.width0 / (tex->desc.width0 + 0.001f); - vec[1] = tex->desc.b.b.height0 / (tex->desc.height0 + 0.001f); - vec[2] = tex->desc.b.b.depth0 / (tex->desc.depth0 + 0.001f); + vec[0] = tex->b.b.b.width0 / (tex->tex.width0 + 0.001f); + vec[1] = tex->b.b.b.height0 / (tex->tex.height0 + 0.001f); + vec[2] = tex->b.b.b.depth0 / (tex->tex.depth0 + 0.001f); vec[3] = 1; break; @@ -352,11 +352,9 @@ void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state) OUT_CS_REG(R300_GB_AA_CONFIG, aa->aa_config); if (aa->dest) { - OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_OFFSET, 1); - OUT_CS_RELOC(aa->dest->cs_buffer, aa->dest->offset); - - OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_PITCH, 1); - OUT_CS_RELOC(aa->dest->cs_buffer, aa->dest->pitch); + OUT_CS_REG(R300_RB3D_AARESOLVE_OFFSET, aa->dest->offset); + OUT_CS_RELOC(aa->dest); + OUT_CS_REG(R300_RB3D_AARESOLVE_PITCH, aa->dest->pitch); } OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, aa->aaresolve_ctl); @@ -391,11 +389,11 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) for (i = 0; i < fb->nr_cbufs; i++) { surf = r300_surface(fb->cbufs[i]); - OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1); - OUT_CS_RELOC(surf->cs_buffer, surf->offset); + OUT_CS_REG(R300_RB3D_COLOROFFSET0 + (4 * i), surf->offset); + OUT_CS_RELOC(surf); - OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1); - OUT_CS_RELOC(surf->cs_buffer, surf->pitch); + OUT_CS_REG(R300_RB3D_COLORPITCH0 + (4 * i), surf->pitch); + OUT_CS_RELOC(surf); } /* Set up the ZB part of the CBZB clear. */ @@ -404,11 +402,11 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_ZB_FORMAT, surf->cbzb_format); - OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); - OUT_CS_RELOC(surf->cs_buffer, surf->cbzb_midpoint_offset); + OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->cbzb_midpoint_offset); + OUT_CS_RELOC(surf); - OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); - OUT_CS_RELOC(surf->cs_buffer, surf->cbzb_pitch); + OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->cbzb_pitch); + OUT_CS_RELOC(surf); DBG(r300, DBG_CBZB, "CBZB clearing cbuf %08x %08x\n", surf->cbzb_format, @@ -420,19 +418,20 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_ZB_FORMAT, surf->format); - OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); - OUT_CS_RELOC(surf->cs_buffer, surf->offset); + OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->offset); + OUT_CS_RELOC(surf); - OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); - OUT_CS_RELOC(surf->cs_buffer, surf->pitch); + OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->pitch); + OUT_CS_RELOC(surf); if (can_hyperz) { uint32_t surf_pitch; - struct r300_texture *tex; + struct r300_resource *tex; int level = surf->base.u.tex.level; - tex = r300_texture(surf->base.texture); + tex = r300_resource(surf->base.texture); surf_pitch = surf->pitch & R300_DEPTHPITCH_MASK; + /* HiZ RAM. */ if (r300->screen->caps.hiz_ram) { if (tex->hiz_mem[level]) { @@ -443,14 +442,10 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_ZB_HIZ_PITCH, 0); } } + /* Z Mask RAM. (compressed zbuffer) */ - if (tex->zmask_mem[level]) { - OUT_CS_REG(R300_ZB_ZMASK_OFFSET, tex->zmask_mem[level]->ofs << 2); - OUT_CS_REG(R300_ZB_ZMASK_PITCH, surf_pitch); - } else { - OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0); - OUT_CS_REG(R300_ZB_ZMASK_PITCH, 0); - } + OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0); + OUT_CS_REG(R300_ZB_ZMASK_PITCH, surf_pitch); } } @@ -462,6 +457,7 @@ void r300_emit_hyperz_state(struct r300_context *r300, { struct r300_hyperz_state *z = state; CS_LOCALS(r300); + if (z->flush) WRITE_CS_TABLE(&z->cb_flush_begin, size); else @@ -563,14 +559,12 @@ void r300_emit_query_start(struct r300_context *r300, unsigned size, void*state) OUT_CS_REG(R300_ZB_ZPASS_DATA, 0); END_CS; query->begin_emitted = TRUE; - query->flushed = FALSE; } static void r300_emit_query_end_frag_pipes(struct r300_context *r300, struct r300_query *query) { struct r300_capabilities* caps = &r300->screen->caps; - struct r300_winsys_cs_buffer *buf = r300->query_current->cs_buffer; CS_LOCALS(r300); assert(caps->num_frag_pipes); @@ -588,25 +582,25 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300, case 4: /* pipe 3 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 3); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, (query->num_results + 3) * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 3) * 4); + OUT_CS_RELOC(r300->query_current); case 3: /* pipe 2 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 2); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, (query->num_results + 2) * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 2) * 4); + OUT_CS_RELOC(r300->query_current); case 2: /* pipe 1 only */ /* As mentioned above, accomodate RV380 and older. */ OUT_CS_REG(R300_SU_REG_DEST, 1 << (caps->high_second_pipe ? 3 : 1)); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, (query->num_results + 1) * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 1) * 4); + OUT_CS_RELOC(r300->query_current); case 1: /* pipe 0 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 0); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, (query->num_results + 0) * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 0) * 4); + OUT_CS_RELOC(r300->query_current); break; default: fprintf(stderr, "r300: Implementation error: Chipset reports %d" @@ -622,13 +616,12 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300, static void rv530_emit_query_end_single_z(struct r300_context *r300, struct r300_query *query) { - struct r300_winsys_cs_buffer *buf = r300->query_current->cs_buffer; CS_LOCALS(r300); BEGIN_CS(8); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, query->num_results * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, query->num_results * 4); + OUT_CS_RELOC(r300->query_current); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); END_CS; } @@ -636,16 +629,15 @@ static void rv530_emit_query_end_single_z(struct r300_context *r300, static void rv530_emit_query_end_double_z(struct r300_context *r300, struct r300_query *query) { - struct r300_winsys_cs_buffer *buf = r300->query_current->cs_buffer; CS_LOCALS(r300); BEGIN_CS(14); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, (query->num_results + 0) * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 0) * 4); + OUT_CS_RELOC(r300->query_current); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1); - OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_RELOC(buf, (query->num_results + 1) * 4); + OUT_CS_REG(R300_ZB_ZPASS_ADDR, (query->num_results + 1) * 4); + OUT_CS_RELOC(r300->query_current); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); END_CS; } @@ -784,7 +776,7 @@ void r300_emit_textures_state(struct r300_context *r300, { struct r300_textures_state *allstate = (struct r300_textures_state*)state; struct r300_texture_sampler_state *texstate; - struct r300_texture *tex; + struct r300_resource *tex; unsigned i; CS_LOCALS(r300); @@ -794,7 +786,7 @@ void r300_emit_textures_state(struct r300_context *r300, for (i = 0; i < allstate->count; i++) { if ((1 << i) & allstate->tx_enable) { texstate = &allstate->regs[i]; - tex = r300_texture(allstate->sampler_views[i]->base.texture); + tex = r300_resource(allstate->sampler_views[i]->base.texture); OUT_CS_REG(R300_TX_FILTER0_0 + (i * 4), texstate->filter0); OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter1); @@ -805,96 +797,56 @@ void r300_emit_textures_state(struct r300_context *r300, OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format.format1); OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format.format2); - OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1); - OUT_CS_TEX_RELOC(tex, texstate->format.tile_config); + OUT_CS_REG(R300_TX_OFFSET_0 + (i * 4), texstate->format.tile_config); + OUT_CS_RELOC(tex); } } END_CS; } -static void r300_update_vertex_arrays_cb(struct r300_context *r300, unsigned packet_size) +void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean indexed) { - struct pipe_vertex_buffer *vb1, *vb2, *vbuf = r300->vertex_buffer; + struct pipe_vertex_buffer *vbuf = r300->vbuf_mgr->vertex_buffer; + struct pipe_resource **valid_vbuf = r300->vbuf_mgr->real_vertex_buffer; struct pipe_vertex_element *velem = r300->velems->velem; - unsigned *hw_format_size = r300->velems->hw_format_size; - unsigned size1, size2, vertex_array_count = r300->velems->count; + struct r300_resource *buf; int i; - CB_LOCALS; + unsigned vertex_array_count = r300->velems->count; + unsigned packet_size = (vertex_array_count * 3 + 1) / 2; + struct pipe_vertex_buffer *vb1, *vb2; + unsigned *hw_format_size; + unsigned size1, size2; + CS_LOCALS(r300); + + BEGIN_CS(2 + packet_size + vertex_array_count * 2); + OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); + OUT_CS(vertex_array_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); + + hw_format_size = r300->velems->format_size; - BEGIN_CB(r300->vertex_arrays_cb, packet_size); for (i = 0; i < vertex_array_count - 1; i += 2) { vb1 = &vbuf[velem[i].vertex_buffer_index]; vb2 = &vbuf[velem[i+1].vertex_buffer_index]; size1 = hw_format_size[i]; size2 = hw_format_size[i+1]; - OUT_CB(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | + OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); - OUT_CB(vb1->buffer_offset + velem[i].src_offset); - OUT_CB(vb2->buffer_offset + velem[i+1].src_offset); + OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); + OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride); } if (vertex_array_count & 1) { vb1 = &vbuf[velem[i].vertex_buffer_index]; size1 = hw_format_size[i]; - OUT_CB(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); - OUT_CB(vb1->buffer_offset + velem[i].src_offset); - } - END_CB; - - r300->vertex_arrays_dirty = FALSE; -} - -void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean indexed) -{ - struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; - struct pipe_resource **valid_vbuf = r300->valid_vertex_buffer; - struct pipe_vertex_element *velem = r300->velems->velem; - struct r300_buffer *buf; - int i; - unsigned vertex_array_count = r300->velems->count; - unsigned packet_size = (vertex_array_count * 3 + 1) / 2; - CS_LOCALS(r300); - - BEGIN_CS(2 + packet_size + vertex_array_count * 2); - OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); - OUT_CS(vertex_array_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); - - if (!offset) { - if (r300->vertex_arrays_dirty) { - r300_update_vertex_arrays_cb(r300, packet_size); - } - OUT_CS_TABLE(r300->vertex_arrays_cb, packet_size); - } else { - struct pipe_vertex_buffer *vb1, *vb2; - unsigned *hw_format_size = r300->velems->hw_format_size; - unsigned size1, size2; - - for (i = 0; i < vertex_array_count - 1; i += 2) { - vb1 = &vbuf[velem[i].vertex_buffer_index]; - vb2 = &vbuf[velem[i+1].vertex_buffer_index]; - size1 = hw_format_size[i]; - size2 = hw_format_size[i+1]; - - OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | - R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); - OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); - OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride); - } - - if (vertex_array_count & 1) { - vb1 = &vbuf[velem[i].vertex_buffer_index]; - size1 = hw_format_size[i]; - - OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); - OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); - } + OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); + OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); } for (i = 0; i < vertex_array_count; i++) { - buf = r300_buffer(valid_vbuf[velem[i].vertex_buffer_index]); - OUT_CS_BUF_RELOC_NO_OFFSET(&buf->b.b); + buf = r300_resource(valid_vbuf[velem[i].vertex_buffer_index]); + OUT_CS_RELOC(buf); } END_CS; } @@ -919,7 +871,8 @@ void r300_emit_vertex_arrays_swtcl(struct r300_context *r300, boolean indexed) OUT_CS(r300->vertex_info.size | (r300->vertex_info.size << 8)); OUT_CS(r300->draw_vbo_offset); - OUT_CS_BUF_RELOC(r300->vbo, 0); + OUT_CS(0); + OUT_CS_RELOC(r300_resource(r300->vbo)); END_CS; } @@ -1097,17 +1050,6 @@ static void r300_emit_hiz_line_clear(struct r300_context *r300, int start, uint1 END_CS; } -static void r300_emit_zmask_line_clear(struct r300_context *r300, int start, uint16_t count, uint32_t val) -{ - CS_LOCALS(r300); - BEGIN_CS(4); - OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_ZMASK, 2); - OUT_CS(start); - OUT_CS(count); - OUT_CS(val); - END_CS; -} - #define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y)) void r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state) @@ -1118,13 +1060,13 @@ void r300_emit_hiz_clear(struct r300_context *r300, unsigned size, void *state) (struct r300_hyperz_state*)r300->hyperz_state.state; struct r300_screen* r300screen = r300->screen; uint32_t stride, offset = 0, height, offset_shift; - struct r300_texture* tex; + struct r300_resource* tex; int i; - tex = r300_texture(fb->zsbuf->texture); + tex = r300_resource(fb->zsbuf->texture); offset = tex->hiz_mem[fb->zsbuf->u.tex.level]->ofs; - stride = tex->desc.stride_in_pixels[fb->zsbuf->u.tex.level]; + stride = tex->tex.stride_in_pixels[fb->zsbuf->u.tex.level]; /* convert from pixels to 4x4 blocks */ stride = ALIGN_DIVUP(stride, 4); @@ -1153,42 +1095,21 @@ void r300_emit_zmask_clear(struct r300_context *r300, unsigned size, void *state { struct pipe_framebuffer_state *fb = (struct pipe_framebuffer_state*)r300->fb_state.state; - struct r300_screen* r300screen = r300->screen; - uint32_t stride, offset = 0; - struct r300_texture* tex; - uint32_t i, height; - int mult, offset_shift; - - tex = r300_texture(fb->zsbuf->texture); - stride = tex->desc.stride_in_pixels[fb->zsbuf->u.tex.level]; - - offset = tex->zmask_mem[fb->zsbuf->u.tex.level]->ofs; - - if (r300->z_compression == RV350_Z_COMPRESS_88) - mult = 8; - else - mult = 4; - - height = ALIGN_DIVUP(fb->zsbuf->height, mult); - - offset_shift = 4; - offset_shift += (r300screen->caps.num_frag_pipes / 2); - stride = ALIGN_DIVUP(stride, r300screen->caps.num_frag_pipes); + struct r300_resource *tex; + CS_LOCALS(r300); - /* okay have width in pixels - divide by block width */ - stride = ALIGN_DIVUP(stride, mult); - /* have width in blocks - divide by number of fragment pipes screen width */ - /* 16 blocks per dword */ - stride = ALIGN_DIVUP(stride, 16); + tex = r300_resource(fb->zsbuf->texture); - for (i = 0; i < height; i++) { - offset = i * stride; - offset <<= offset_shift; - r300_emit_zmask_line_clear(r300, offset, stride, 0x0);//0xffffffff); - } + BEGIN_CS(size); + OUT_CS_PKT3(R300_PACKET3_3D_CLEAR_ZMASK, 2); + OUT_CS(0); + OUT_CS(tex->tex.zmask_dwords[fb->zsbuf->u.tex.level]); + OUT_CS(0); + END_CS; /* Mark the current zbuffer's zmask as in use. */ - tex->zmask_in_use[fb->zsbuf->u.tex.level] = TRUE; + r300->zmask_in_use = TRUE; + r300_mark_atom_dirty(r300, &r300->hyperz_state); } void r300_emit_ztop_state(struct r300_context* r300, @@ -1219,7 +1140,7 @@ boolean r300_emit_buffer_validate(struct r300_context *r300, (struct pipe_framebuffer_state*)r300->fb_state.state; struct r300_textures_state *texstate = (struct r300_textures_state*)r300->textures_state.state; - struct r300_texture *tex; + struct r300_resource *tex; unsigned i; boolean flushed = FALSE; @@ -1227,16 +1148,16 @@ validate: if (r300->fb_state.dirty) { /* Color buffers... */ for (i = 0; i < fb->nr_cbufs; i++) { - tex = r300_texture(fb->cbufs[i]->texture); - assert(tex && tex->buffer && "cbuf is marked, but NULL!"); - r300->rws->cs_add_reloc(r300->cs, tex->cs_buffer, 0, + tex = r300_resource(fb->cbufs[i]->texture); + assert(tex && tex->buf && "cbuf is marked, but NULL!"); + r300->rws->cs_add_reloc(r300->cs, tex->cs_buf, 0, r300_surface(fb->cbufs[i])->domain); } /* ...depth buffer... */ if (fb->zsbuf) { - tex = r300_texture(fb->zsbuf->texture); - assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); - r300->rws->cs_add_reloc(r300->cs, tex->cs_buffer, 0, + tex = r300_resource(fb->zsbuf->texture); + assert(tex && tex->buf && "zsbuf is marked, but NULL!"); + r300->rws->cs_add_reloc(r300->cs, tex->cs_buf, 0, r300_surface(fb->zsbuf)->domain); } } @@ -1247,35 +1168,35 @@ validate: continue; } - tex = r300_texture(texstate->sampler_views[i]->base.texture); - r300->rws->cs_add_reloc(r300->cs, tex->cs_buffer, tex->domain, 0); + tex = r300_resource(texstate->sampler_views[i]->base.texture); + r300->rws->cs_add_reloc(r300->cs, tex->cs_buf, tex->domain, 0); } } /* ...occlusion query buffer... */ if (r300->query_current) - r300->rws->cs_add_reloc(r300->cs, r300->query_current->cs_buffer, + r300->rws->cs_add_reloc(r300->cs, r300->query_current->cs_buf, 0, r300->query_current->domain); /* ...vertex buffer for SWTCL path... */ if (r300->vbo) - r300->rws->cs_add_reloc(r300->cs, r300_buffer(r300->vbo)->cs_buf, - r300_buffer(r300->vbo)->domain, 0); + r300->rws->cs_add_reloc(r300->cs, r300_resource(r300->vbo)->cs_buf, + r300_resource(r300->vbo)->domain, 0); /* ...vertex buffers for HWTCL path... */ - if (do_validate_vertex_buffers) { - struct pipe_resource **buf = r300->valid_vertex_buffer; - struct pipe_resource **last = r300->valid_vertex_buffer + - r300->vertex_buffer_count; + if (do_validate_vertex_buffers && r300->vertex_arrays_dirty) { + struct pipe_resource **buf = r300->vbuf_mgr->real_vertex_buffer; + struct pipe_resource **last = r300->vbuf_mgr->real_vertex_buffer + + r300->vbuf_mgr->nr_real_vertex_buffers; for (; buf != last; buf++) { if (!*buf) continue; - r300->rws->cs_add_reloc(r300->cs, r300_buffer(*buf)->cs_buf, - r300_buffer(*buf)->domain, 0); + r300->rws->cs_add_reloc(r300->cs, r300_resource(*buf)->cs_buf, + r300_resource(*buf)->domain, 0); } } /* ...and index buffer for HWTCL path. */ if (index_buffer) - r300->rws->cs_add_reloc(r300->cs, r300_buffer(index_buffer)->cs_buf, - r300_buffer(index_buffer)->domain, 0); + r300->rws->cs_add_reloc(r300->cs, r300_resource(index_buffer)->cs_buf, + r300_resource(index_buffer)->domain, 0); /* Now do the validation. */ if (!r300->rws->cs_validate(r300->cs)) { diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index b250532ba92..c77cc08539d 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -36,16 +36,24 @@ static void r300_flush(struct pipe_context* pipe, struct pipe_fence_handle** fence) { struct r300_context *r300 = r300_context(pipe); - struct r300_query *query; struct r300_atom *atom; - struct r300_fence **rfence = (struct r300_fence**)fence; - - u_upload_flush(r300->upload_vb); - u_upload_flush(r300->upload_ib); + struct r300_winsys_bo **rfence = (struct r300_winsys_bo**)fence; if (r300->draw && !r300->draw_vbo_locked) r300_draw_flush_vbuf(r300); + if (rfence) { + /* Create a fence, which is a dummy BO. */ + *rfence = r300->rws->buffer_create(r300->rws, 1, 1, + PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STATIC, + R300_DOMAIN_GTT); + /* Add the fence as a dummy relocation. */ + r300->rws->cs_add_reloc(r300->cs, + r300->rws->buffer_get_cs_handle(*rfence), + R300_DOMAIN_GTT, R300_DOMAIN_GTT); + } + if (r300->dirty_hw) { r300_emit_hyperz_end(r300); r300_emit_query_end(r300); @@ -62,32 +70,29 @@ static void r300_flush(struct pipe_context* pipe, r300_mark_atom_dirty(r300, atom); } } + r300->vertex_arrays_dirty = TRUE; /* Unmark HWTCL state for SWTCL. */ if (!r300->screen->caps.has_tcl) { r300->vs_state.dirty = FALSE; r300->vs_constants.dirty = FALSE; } - - r300->validate_buffers = TRUE; - r300->upload_vb_validated = FALSE; - r300->upload_ib_validated = FALSE; } else { - /* Even if hw is not dirty, we should at least reset the CS in case - * the space checking failed for the first draw operation. */ - r300->rws->cs_flush(r300->cs); - } - - /* reset flushed query */ - foreach(query, &r300->query_list) { - query->flushed = TRUE; + if (rfence) { + /* We have to create a fence object, but the command stream is empty + * and we cannot emit an empty CS. We must write some regs then. */ + CS_LOCALS(r300); + OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0); + r300->rws->cs_flush(r300->cs); + } else { + /* Even if hw is not dirty, we should at least reset the CS in case + * the space checking failed for the first draw operation. */ + r300->rws->cs_flush(r300->cs); + } } - /* Create a new fence. */ - if (rfence) { - *rfence = CALLOC_STRUCT(r300_fence); - pipe_reference_init(&(*rfence)->reference, 1); - (*rfence)->ctx = r300; + if (flags & PIPE_FLUSH_FRAME) { + r300->rws->cs_sync_flush(r300->cs); } } diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index 6d4091dc87d..cec7473009a 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -152,13 +152,13 @@ static void get_external_state( for (i = 0; i < texstate->sampler_state_count; i++) { struct r300_sampler_state *s = texstate->sampler_states[i]; struct r300_sampler_view *v = texstate->sampler_views[i]; - struct r300_texture *t; + struct r300_resource *t; if (!s || !v) { continue; } - t = r300_texture(texstate->sampler_views[i]->base.texture); + t = r300_resource(texstate->sampler_views[i]->base.texture); if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { state->unit[i].compare_mode_enabled = 1; @@ -181,7 +181,7 @@ static void get_external_state( state->unit[i].non_normalized_coords = !s->state.normalized_coords; /* XXX this should probably take into account STR, not just S. */ - if (t->desc.is_npot) { + if (t->tex.is_npot) { switch (s->state.wrap_s) { case PIPE_TEX_WRAP_REPEAT: state->unit[i].wrap_mode = RC_WRAP_REPEAT; @@ -201,7 +201,7 @@ static void get_external_state( state->unit[i].wrap_mode = RC_WRAP_NONE; } - if (t->desc.b.b.target == PIPE_TEXTURE_3D) + if (t->b.b.b.target == PIPE_TEXTURE_3D) state->unit[i].clamp_and_scale_before_fetch = TRUE; } } @@ -298,44 +298,98 @@ static void r300_emit_fs_code_to_buffer( } } else { /* r300 */ struct r300_fragment_program_code *code = &generic_code->code.r300; - - shader->cb_code_size = 19 + - (r300->screen->caps.is_r400 ? 2 : 0) + - code->alu.length * 4 + - (code->tex.length ? (1 + code->tex.length) : 0) + - imm_count * 5; + unsigned int alu_length = code->alu.length; + unsigned int alu_iterations = ((alu_length - 1) / 64) + 1; + unsigned int tex_length = code->tex.length; + unsigned int tex_iterations = + tex_length > 0 ? ((tex_length - 1) / 32) + 1 : 0; + unsigned int iterations = + alu_iterations > tex_iterations ? alu_iterations : tex_iterations; + unsigned int bank = 0; + + shader->cb_code_size = 15 + + /* R400_US_CODE_BANK */ + (r300->screen->caps.is_r400 ? 2 * (iterations + 1): 0) + + /* R400_US_CODE_EXT */ + (r300->screen->caps.is_r400 ? 2 : 0) + + /* R300_US_ALU_{RGB,ALPHA}_{INST,ADDR}_0, R400_US_ALU_EXT_ADDR_0 */ + (code->r390_mode ? (5 * alu_iterations) : 4) + + /* R400_US_ALU_EXT_ADDR_[0-63] */ + (code->r390_mode ? (code->alu.length) : 0) + + /* R300_US_ALU_{RGB,ALPHA}_{INST,ADDR}_0 */ + code->alu.length * 4 + + /* R300_US_TEX_INST_0, R300_US_TEX_INST_[0-31] */ + (code->tex.length > 0 ? code->tex.length + tex_iterations : 0) + + imm_count * 5; NEW_CB(shader->cb_code, shader->cb_code_size); - if (r300->screen->caps.is_r400) - OUT_CB_REG(R400_US_CODE_BANK, 0); - OUT_CB_REG(R300_US_CONFIG, code->config); OUT_CB_REG(R300_US_PIXSIZE, code->pixsize); OUT_CB_REG(R300_US_CODE_OFFSET, code->code_offset); + if (code->r390_mode) { + OUT_CB_REG(R400_US_CODE_EXT, code->r400_code_offset_ext); + } else if (r300->screen->caps.is_r400) { + /* This register appears to affect shaders even if r390_mode is + * disabled, so it needs to be set to 0 for shaders that + * don't use r390_mode. */ + OUT_CB_REG(R400_US_CODE_EXT, 0); + } + OUT_CB_REG_SEQ(R300_US_CODE_ADDR_0, 4); OUT_CB_TABLE(code->code_addr, 4); - OUT_CB_REG_SEQ(R300_US_ALU_RGB_INST_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) - OUT_CB(code->alu.inst[i].rgb_inst); + do { + unsigned int bank_alu_length = (alu_length < 64 ? alu_length : 64); + unsigned int bank_alu_offset = bank * 64; + unsigned int bank_tex_length = (tex_length < 32 ? tex_length : 32); + unsigned int bank_tex_offset = bank * 32; + + if (r300->screen->caps.is_r400) { + OUT_CB_REG(R400_US_CODE_BANK, code->r390_mode ? + (bank << R400_BANK_SHIFT) | R400_R390_MODE_ENABLE : 0);//2 + } + + if (bank_alu_length > 0) { + OUT_CB_REG_SEQ(R300_US_ALU_RGB_INST_0, bank_alu_length); + for (i = 0; i < bank_alu_length; i++) + OUT_CB(code->alu.inst[i + bank_alu_offset].rgb_inst); + + OUT_CB_REG_SEQ(R300_US_ALU_RGB_ADDR_0, bank_alu_length); + for (i = 0; i < bank_alu_length; i++) + OUT_CB(code->alu.inst[i + bank_alu_offset].rgb_addr); - OUT_CB_REG_SEQ(R300_US_ALU_RGB_ADDR_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) - OUT_CB(code->alu.inst[i].rgb_addr); + OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_INST_0, bank_alu_length); + for (i = 0; i < bank_alu_length; i++) + OUT_CB(code->alu.inst[i + bank_alu_offset].alpha_inst); - OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_INST_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) - OUT_CB(code->alu.inst[i].alpha_inst); + OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, bank_alu_length); + for (i = 0; i < bank_alu_length; i++) + OUT_CB(code->alu.inst[i + bank_alu_offset].alpha_addr); - OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) - OUT_CB(code->alu.inst[i].alpha_addr); + if (code->r390_mode) { + OUT_CB_REG_SEQ(R400_US_ALU_EXT_ADDR_0, bank_alu_length); + for (i = 0; i < bank_alu_length; i++) + OUT_CB(code->alu.inst[i + bank_alu_offset].r400_ext_addr); + } + } + + if (bank_tex_length > 0) { + OUT_CB_REG_SEQ(R300_US_TEX_INST_0, bank_tex_length); + OUT_CB_TABLE(code->tex.inst + bank_tex_offset, bank_tex_length); + } + + alu_length -= bank_alu_length; + tex_length -= bank_tex_length; + bank++; + } while(code->r390_mode && (alu_length > 0 || tex_length > 0)); - if (code->tex.length) { - OUT_CB_REG_SEQ(R300_US_TEX_INST_0, code->tex.length); - OUT_CB_TABLE(code->tex.inst, code->tex.length); + /* R400_US_CODE_BANK needs to be reset to 0, otherwise some shaders + * will be rendered incorrectly. */ + if (r300->screen->caps.is_r400) { + OUT_CB_REG(R400_US_CODE_BANK, + code->r390_mode ? R400_R390_MODE_ENABLE : 0); } /* Emit immediates. */ @@ -384,12 +438,17 @@ static void r300_translate_fragment_shader( compiler.code = &shader->code; compiler.state = shader->compare_state; compiler.Base.is_r500 = r300->screen->caps.is_r500; + compiler.Base.is_r400 = r300->screen->caps.is_r400; compiler.Base.disable_optimizations = DBG_ON(r300, DBG_NO_OPT); compiler.Base.has_half_swizzles = TRUE; compiler.Base.has_presub = TRUE; - compiler.Base.max_temp_regs = compiler.Base.is_r500 ? 128 : 32; + compiler.Base.max_temp_regs = + compiler.Base.is_r500 ? 128 : (compiler.Base.is_r400 ? 64 : 32); compiler.Base.max_constants = compiler.Base.is_r500 ? 256 : 32; - compiler.Base.max_alu_insts = compiler.Base.is_r500 ? 512 : 64; + compiler.Base.max_alu_insts = + (compiler.Base.is_r500 || compiler.Base.is_r400) ? 512 : 64; + compiler.Base.max_tex_insts = + (compiler.Base.is_r500 || compiler.Base.is_r400) ? 512 : 32; compiler.AllocateHwInputs = &allocate_hardware_inputs; compiler.UserData = &shader->inputs; @@ -414,6 +473,13 @@ static void r300_translate_fragment_shader( r300_tgsi_to_rc(&ttr, tokens); + if (ttr.error) { + fprintf(stderr, "r300 FP: Cannot translate a shader. " + "Using a dummy shader instead.\n"); + r300_dummy_fragment_shader(r300, shader); + return; + } + if (!r300->screen->caps.is_r500 || compiler.Base.Program.Constants.Count > 200) { compiler.Base.remove_unused_constants = TRUE; diff --git a/src/gallium/drivers/r300/r300_hyperz.c b/src/gallium/drivers/r300/r300_hyperz.c index c22e307c679..873e0209d42 100644 --- a/src/gallium/drivers/r300/r300_hyperz.c +++ b/src/gallium/drivers/r300/r300_hyperz.c @@ -127,7 +127,7 @@ static boolean r300_can_hiz(struct r300_context *r300) z->current_func, dsa_state->z_stencil_control); return FALSE; } - } + } return TRUE; } @@ -137,9 +137,8 @@ static void r300_update_hyperz(struct r300_context* r300) (struct r300_hyperz_state*)r300->hyperz_state.state; struct pipe_framebuffer_state *fb = (struct pipe_framebuffer_state*)r300->fb_state.state; - struct r300_texture *zstex = - fb->zsbuf ? r300_texture(fb->zsbuf->texture) : NULL; - boolean zmask_in_use = FALSE; + struct r300_resource *zstex = + fb->zsbuf ? r300_resource(fb->zsbuf->texture) : NULL; boolean hiz_in_use = FALSE; z->gb_z_peq_config = 0; @@ -158,42 +157,40 @@ static void r300_update_hyperz(struct r300_context* r300) if (!r300->rws->get_value(r300->rws, R300_CAN_HYPERZ)) return; - zmask_in_use = zstex->zmask_in_use[fb->zsbuf->u.tex.level]; hiz_in_use = zstex->hiz_in_use[fb->zsbuf->u.tex.level]; - /* Z fastfill. */ - if (zmask_in_use) { - z->zb_bw_cntl |= R300_FAST_FILL_ENABLE; /* | R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE;*/ - } - /* Zbuffer compression. */ - if (zmask_in_use && r300->z_compression) { - z->zb_bw_cntl |= R300_RD_COMP_ENABLE; - if (r300->z_decomp_rd == false) + if (r300->zmask_in_use && !r300->zmask_locked) { + z->zb_bw_cntl |= R300_FAST_FILL_ENABLE | + /*R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE |*/ + R300_RD_COMP_ENABLE; + + if (!r300->zmask_decompress) { z->zb_bw_cntl |= R300_WR_COMP_ENABLE; + } } - /* RV350 and up optimizations. */ - /* The section 10.4.9 in the docs is a lie. */ - if (r300->z_compression == RV350_Z_COMPRESS_88) + + if (zstex->tex.zcomp8x8[fb->zsbuf->u.tex.level]) { z->gb_z_peq_config |= R300_GB_Z_PEQ_CONFIG_Z_PEQ_SIZE_8_8; + } + + if (hiz_in_use && r300_can_hiz(r300)) { + z->zb_bw_cntl |= R300_HIZ_ENABLE | + r300_get_hiz_min(r300); - if (hiz_in_use) { - bool can_hiz = r300_can_hiz(r300); - if (can_hiz) { - z->zb_bw_cntl |= R300_HIZ_ENABLE; - z->sc_hyperz |= R300_SC_HYPERZ_ENABLE; - z->sc_hyperz |= r300_get_sc_hz_max(r300); - z->zb_bw_cntl |= r300_get_hiz_min(r300); + z->sc_hyperz |= R300_SC_HYPERZ_ENABLE | + r300_get_sc_hz_max(r300); + + if (r300->screen->caps.is_r500) { + z->zb_bw_cntl |= R500_HIZ_FP_EXP_BITS_3 | + R500_HIZ_EQUAL_REJECT_ENABLE; } } /* R500-specific features and optimizations. */ if (r300->screen->caps.is_r500) { - z->zb_bw_cntl |= R500_HIZ_FP_EXP_BITS_3; - z->zb_bw_cntl |= - R500_HIZ_EQUAL_REJECT_ENABLE | - R500_PEQ_PACKING_ENABLE | - R500_COVERED_PTR_MASKING_ENABLE; + z->zb_bw_cntl |= R500_PEQ_PACKING_ENABLE | + R500_COVERED_PTR_MASKING_ENABLE; } } @@ -297,26 +294,10 @@ static void r300_update_hiz_clear(struct r300_context *r300) r300->hiz_clear.size = height * 4; } -static void r300_update_zmask_clear(struct r300_context *r300) -{ - struct pipe_framebuffer_state *fb = - (struct pipe_framebuffer_state*)r300->fb_state.state; - uint32_t height; - int mult; - - if (r300->z_compression == RV350_Z_COMPRESS_88) - mult = 8; - else - mult = 4; - - height = ALIGN_DIVUP(fb->zsbuf->height, mult); - - r300->zmask_clear.size = height * 4; -} - void r300_update_hyperz_state(struct r300_context* r300) { r300_update_ztop(r300); + if (r300->hyperz_state.dirty) { r300_update_hyperz(r300); } @@ -324,64 +305,24 @@ void r300_update_hyperz_state(struct r300_context* r300) if (r300->hiz_clear.dirty) { r300_update_hiz_clear(r300); } - if (r300->zmask_clear.dirty) { - r300_update_zmask_clear(r300); - } } void r300_hiz_alloc_block(struct r300_context *r300, struct r300_surface *surf) { - struct r300_texture *tex; + struct r300_resource *tex; uint32_t zsize, ndw; int level = surf->base.u.tex.level; - tex = r300_texture(surf->base.texture); + tex = r300_resource(surf->base.texture); if (tex->hiz_mem[level]) return; - zsize = tex->desc.layer_size_in_bytes[level]; - zsize /= util_format_get_blocksize(tex->desc.b.b.format); + zsize = tex->tex.layer_size_in_bytes[level]; + zsize /= util_format_get_blocksize(tex->b.b.b.format); ndw = ALIGN_DIVUP(zsize, 64); tex->hiz_mem[level] = u_mmAllocMem(r300->hiz_mm, ndw, 0, 0); - return; -} - -void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf, int compress) -{ - int bsize = 256; - uint32_t zsize, ndw; - int level = surf->base.u.tex.level; - struct r300_texture *tex; - - tex = r300_texture(surf->base.texture); - - /* We currently don't handle decompression for 3D textures and cubemaps - * correctly. */ - if (tex->desc.b.b.target != PIPE_TEXTURE_1D && - tex->desc.b.b.target != PIPE_TEXTURE_2D && - tex->desc.b.b.target != PIPE_TEXTURE_RECT) - return; - - /* Cannot flush zmask of 16-bit zbuffers. */ - if (util_format_get_blocksizebits(tex->desc.b.b.format) == 16) - return; - - if (tex->zmask_mem[level]) - return; - - zsize = tex->desc.layer_size_in_bytes[level]; - zsize /= util_format_get_blocksize(tex->desc.b.b.format); - - /* each zmask dword represents 16 4x4 blocks - which is 256 pixels - or 16 8x8 depending on the gb peq flag = 1024 pixels */ - if (compress == RV350_Z_COMPRESS_88) - bsize = 1024; - - ndw = ALIGN_DIVUP(zsize, bsize); - tex->zmask_mem[level] = u_mmAllocMem(r300->zmask_mm, ndw, 0, 0); - return; } boolean r300_hyperz_init_mm(struct r300_context *r300) @@ -389,15 +330,9 @@ boolean r300_hyperz_init_mm(struct r300_context *r300) struct r300_screen* r300screen = r300->screen; int frag_pipes = r300screen->caps.num_frag_pipes; - r300->zmask_mm = u_mmInit(0, r300screen->caps.zmask_ram * frag_pipes); - if (!r300->zmask_mm) - return FALSE; - if (r300screen->caps.hiz_ram) { r300->hiz_mm = u_mmInit(0, r300screen->caps.hiz_ram * frag_pipes); if (!r300->hiz_mm) { - u_mmDestroy(r300->zmask_mm); - r300->zmask_mm = NULL; return FALSE; } } @@ -413,7 +348,4 @@ void r300_hyperz_destroy_mm(struct r300_context *r300) u_mmDestroy(r300->hiz_mm); r300->hiz_mm = NULL; } - - u_mmDestroy(r300->zmask_mm); - r300->zmask_mm = NULL; } diff --git a/src/gallium/drivers/r300/r300_hyperz.h b/src/gallium/drivers/r300/r300_hyperz.h index 30a23ec6493..d4c8e7c60a9 100644 --- a/src/gallium/drivers/r300/r300_hyperz.h +++ b/src/gallium/drivers/r300/r300_hyperz.h @@ -28,8 +28,8 @@ struct r300_context; void r300_update_hyperz_state(struct r300_context* r300); void r300_hiz_alloc_block(struct r300_context *r300, struct r300_surface *surf); -void r300_zmask_alloc_block(struct r300_context *r300, struct r300_surface *surf, int compress); boolean r300_hyperz_init_mm(struct r300_context *r300); void r300_hyperz_destroy_mm(struct r300_context *r300); + #endif diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 6223e043210..717485f43cb 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -57,10 +57,10 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, insert_at_tail(&r300->query_list, q); /* Open up the occlusion query buffer. */ - q->buffer = r300->rws->buffer_create(r300->rws, q->buffer_size, 4096, + q->buf = r300->rws->buffer_create(r300->rws, q->buffer_size, 4096, PIPE_BIND_CUSTOM, PIPE_USAGE_STREAM, q->domain); - q->cs_buffer = r300->rws->buffer_get_cs_handle(r300->rws, q->buffer); + q->cs_buf = r300->rws->buffer_get_cs_handle(q->buf); return (struct pipe_query*)q; } @@ -68,10 +68,9 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, static void r300_destroy_query(struct pipe_context* pipe, struct pipe_query* query) { - struct r300_context *r300 = r300_context(pipe); struct r300_query* q = r300_query(query); - r300->rws->buffer_reference(r300->rws, &q->buffer, NULL); + r300_winsys_bo_reference(&q->buf, NULL); remove_from_list(q); FREE(query); } @@ -128,16 +127,12 @@ static boolean r300_get_query_result(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); struct r300_query *q = r300_query(query); - unsigned flags, i; + unsigned i; uint32_t temp, *map; - uint64_t *result = (uint64_t*)vresult; - - if (!q->flushed) - pipe->flush(pipe, 0, NULL); - - flags = PIPE_TRANSFER_READ | (!wait ? PIPE_TRANSFER_DONTBLOCK : 0); - map = r300->rws->buffer_map(r300->rws, q->buffer, r300->cs, flags); + map = r300->rws->buffer_map(q->buf, r300->cs, + PIPE_TRANSFER_READ | + (!wait ? PIPE_TRANSFER_DONTBLOCK : 0)); if (!map) return FALSE; @@ -148,9 +143,9 @@ static boolean r300_get_query_result(struct pipe_context* pipe, map++; } - r300->rws->buffer_unmap(r300->rws, q->buffer); + r300->rws->buffer_unmap(q->buf); - *result = temp; + *((uint64_t*)vresult) = temp; return TRUE; } diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index d1154dee40a..1d93dab2ca2 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -2162,14 +2162,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* R4xx extended fragment shader registers. */ #define R400_US_ALU_EXT_ADDR_0 0x4ac0 /* up to 63 (0x4bbc) */ -# define R400_ADDR0_EXT_RGB_MSB_BIT 0x01 -# define R400_ADDR1_EXT_RGB_MSB_BIT 0x02 -# define R400_ADDR2_EXT_RGB_MSB_BIT 0x04 +# define R400_ADDR_EXT_RGB_MSB_BIT(x) (1 << (x)) # define R400_ADDRD_EXT_RGB_MSB_BIT 0x08 -# define R400_ADDR0_EXT_A_MSB_BIT 0x10 -# define R400_ADDR1_EXT_A_MSB_BIT 0x20 -# define R400_ADDR2_EXT_A_MSB_BIT 0x40 +# define R400_ADDR_EXT_A_MSB_BIT(x) (1 << ((x) + 4)) # define R400_ADDRD_EXT_A_MSB_BIT 0x80 + #define R400_US_CODE_BANK 0x46b8 # define R400_BANK_SHIFT 0 # define R400_BANK_MASK 0xf diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index b35822c82f8..2ead8667bda 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -127,6 +127,20 @@ void r500_emit_index_bias(struct r300_context *r300, int index_bias) END_CS; } +static void r300_emit_draw_init(struct r300_context *r300, unsigned mode, + unsigned min_index, unsigned max_index) +{ + CS_LOCALS(r300); + + BEGIN_CS(5); + OUT_CS_REG(R300_GA_COLOR_CONTROL, + r300_provoking_vertex_fixes(r300, mode)); + OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); + OUT_CS(max_index); + OUT_CS(min_index); + END_CS; +} + /* This function splits the index bias value into two parts: * - buffer_offset: the value that can be safely added to buffer offsets * in r300_emit_vertex_arrays (it must yield a positive offset when added to @@ -136,7 +150,7 @@ void r500_emit_index_bias(struct r300_context *r300, int index_bias) static void r300_split_index_bias(struct r300_context *r300, int index_bias, int *buffer_offset, int *index_offset) { - struct pipe_vertex_buffer *vb, *vbufs = r300->vertex_buffer; + struct pipe_vertex_buffer *vb, *vbufs = r300->vbuf_mgr->vertex_buffer; struct pipe_vertex_element *velem = r300->velems->velem; unsigned i, size; int max_neg_bias; @@ -235,24 +249,11 @@ static boolean r300_emit_states(struct r300_context *r300, /* Validate buffers and emit dirty state if needed. */ if (first_draw) { - if (r300->validate_buffers) { - if (!r300_emit_buffer_validate(r300, validate_vbos, - index_buffer)) { - fprintf(stderr, "r300: CS space validation failed. " - "(not enough memory?) Skipping rendering.\n"); - return FALSE; - } - - /* Consider the validation done only if everything was validated. */ - if (validate_vbos) { - r300->validate_buffers = FALSE; - if (r300->any_user_vbs) - r300->upload_vb_validated = TRUE; - if (r300->index_buffer.buffer && - r300_is_user_buffer(r300->index_buffer.buffer)) { - r300->upload_ib_validated = TRUE; - } - } + if (!r300_emit_buffer_validate(r300, validate_vbos, + index_buffer)) { + fprintf(stderr, "r300: CS space validation failed. " + "(not enough memory?) Skipping rendering.\n"); + return FALSE; } r300_emit_dirty_state(r300); @@ -263,9 +264,17 @@ static boolean r300_emit_states(struct r300_context *r300, r500_emit_index_bias(r300, 0); } - if (emit_vertex_arrays) + if (emit_vertex_arrays && + (r300->vertex_arrays_dirty || + r300->vertex_arrays_indexed != indexed || + r300->vertex_arrays_offset != buffer_offset)) { r300_emit_vertex_arrays(r300, buffer_offset, indexed); + r300->vertex_arrays_dirty = FALSE; + r300->vertex_arrays_indexed = indexed; + r300->vertex_arrays_offset = buffer_offset; + } + if (emit_vertex_arrays_swtcl) r300_emit_vertex_arrays_swtcl(r300, indexed); } @@ -294,7 +303,8 @@ static boolean r300_prepare_for_rendering(struct r300_context *r300, if (r300_reserve_cs_dwords(r300, flags, cs_dwords)) flags |= PREP_FIRST_DRAW; - return r300_emit_states(r300, flags, index_buffer, buffer_offset, index_bias); + return r300_emit_states(r300, flags, index_buffer, buffer_offset, + index_bias); } static boolean immd_is_good_idea(struct r300_context *r300, @@ -325,17 +335,12 @@ static boolean immd_is_good_idea(struct r300_context *r300, vbi = velem->vertex_buffer_index; if (!checked[vbi]) { - buf = r300->valid_vertex_buffer[vbi]; + buf = r300->vbuf_mgr->real_vertex_buffer[vbi]; - if (!(r300_buffer(buf)->domain & R300_DOMAIN_GTT)) { + if ((r300_resource(buf)->domain != R300_DOMAIN_GTT)) { return FALSE; } - if (r300_buffer_is_referenced(&r300->context, buf, - R300_REF_CS | R300_REF_HW)) { - /* It's a very bad idea to map it... */ - return FALSE; - } checked[vbi] = TRUE; } } @@ -346,10 +351,9 @@ static boolean immd_is_good_idea(struct r300_context *r300, * The HWTCL draw functions. * ****************************************************************************/ -static void r300_emit_draw_arrays_immediate(struct r300_context *r300, - unsigned mode, - unsigned start, - unsigned count) +static void r300_draw_arrays_immediate(struct r300_context *r300, + unsigned mode, unsigned start, + unsigned count) { struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; @@ -360,7 +364,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, unsigned vertex_size = r300->velems->vertex_size_dwords; /* The number of dwords for this draw operation. */ - unsigned dwords = 9 + count * vertex_size; + unsigned dwords = 4 + count * vertex_size; /* Size of the vertex element, in dwords. */ unsigned size[PIPE_MAX_ATTRIBS]; @@ -370,9 +374,8 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, unsigned stride[PIPE_MAX_ATTRIBS]; /* Mapped vertex buffers. */ - uint32_t* map[PIPE_MAX_ATTRIBS]; + uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; uint32_t* mapelem[PIPE_MAX_ATTRIBS]; - struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {0}; CS_LOCALS(r300); @@ -382,29 +385,25 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ for (i = 0; i < vertex_element_count; i++) { velem = &r300->velems->velem[i]; - size[i] = r300->velems->hw_format_size[i] / 4; + size[i] = r300->velems->format_size[i] / 4; vbi = velem->vertex_buffer_index; - vbuf = &r300->vertex_buffer[vbi]; + vbuf = &r300->vbuf_mgr->vertex_buffer[vbi]; stride[i] = vbuf->stride / 4; /* Map the buffer. */ - if (!transfer[vbi]) { - map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context, - r300->valid_vertex_buffer[vbi], - PIPE_TRANSFER_READ, - &transfer[vbi]); + if (!map[vbi]) { + map[vbi] = (uint32_t*)r300->rws->buffer_map( + r300_resource(r300->vbuf_mgr->real_vertex_buffer[vbi])->buf, + r300->cs, PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED); map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * start; } mapelem[i] = map[vbi] + (velem->src_offset / 4); } + r300_emit_draw_init(r300, mode, 0, count-1); + BEGIN_CS(dwords); - OUT_CS_REG(R300_GA_COLOR_CONTROL, - r300_provoking_vertex_fixes(r300, mode)); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); - OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); - OUT_CS(count - 1); - OUT_CS(0); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | r300_translate_primitive(mode)); @@ -421,9 +420,9 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, for (i = 0; i < vertex_element_count; i++) { vbi = r300->velems->velem[i].vertex_buffer_index; - if (transfer[vbi]) { - pipe_buffer_unmap(&r300->context, transfer[vbi]); - transfer[vbi] = NULL; + if (map[vbi]) { + r300->rws->buffer_unmap(r300_resource(r300->vbuf_mgr->real_vertex_buffer[vbi])->buf); + map[vbi] = NULL; } } } @@ -441,15 +440,12 @@ static void r300_emit_draw_arrays(struct r300_context *r300, return; } - BEGIN_CS(7 + (alt_num_verts ? 2 : 0)); + r300_emit_draw_init(r300, mode, 0, count-1); + + BEGIN_CS(2 + (alt_num_verts ? 2 : 0)); if (alt_num_verts) { OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); } - OUT_CS_REG(R300_GA_COLOR_CONTROL, - r300_provoking_vertex_fixes(r300, mode)); - OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); - OUT_CS(count - 1); - OUT_CS(0); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300_translate_primitive(mode) | @@ -471,22 +467,16 @@ static void r300_emit_draw_elements(struct r300_context *r300, boolean alt_num_verts = count > 65535; CS_LOCALS(r300); - if (count >= (1 << 24)) { + if (count >= (1 << 24) || maxIndex >= (1 << 24)) { fprintf(stderr, "r300: Got a huge number of vertices: %i, " - "refusing to render.\n", count); + "refusing to render (maxIndex: %i).\n", count, maxIndex); return; } DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n", count, minIndex, maxIndex); - BEGIN_CS(5); - OUT_CS_REG(R300_GA_COLOR_CONTROL, - r300_provoking_vertex_fixes(r300, mode)); - OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); - OUT_CS(maxIndex); - OUT_CS(minIndex); - END_CS; + r300_emit_draw_init(r300, mode, minIndex, maxIndex); /* If start is odd, render the first triangle with indices embedded * in the command stream. This will increase start by 3 and make it @@ -527,30 +517,105 @@ static void r300_emit_draw_elements(struct r300_context *r300, (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); } - /* INDX_BUFFER is a truly special packet3. - * Unlike most other packet3, where the offset is after the count, - * the order is reversed, so the relocation ends up carrying the - * size of the indexbuf instead of the offset. - */ OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | (0 << R300_INDX_BUFFER_SKIP_SHIFT)); OUT_CS(offset_dwords << 2); - OUT_CS_BUF_RELOC(indexBuffer, count_dwords); + OUT_CS(count_dwords); + OUT_CS_RELOC(r300_resource(indexBuffer)); + END_CS; +} + +static void r300_draw_elements_immediate(struct r300_context *r300, + int indexBias, unsigned minIndex, + unsigned maxIndex, unsigned mode, + unsigned start, unsigned count) +{ + uint8_t *ptr1; + uint16_t *ptr2; + uint32_t *ptr4; + unsigned index_size = r300->index_buffer.index_size; + unsigned i, count_dwords = index_size == 4 ? count : (count + 1) / 2; + CS_LOCALS(r300); + + /* 19 dwords for r300_draw_elements_immediate. Give up if the function fails. */ + if (!r300_prepare_for_rendering(r300, + PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | + PREP_INDEXED, NULL, 2+count_dwords, 0, indexBias)) + return; + r300_emit_draw_init(r300, mode, minIndex, maxIndex); + + BEGIN_CS(2 + count_dwords); + OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, count_dwords); + + switch (index_size) { + case 1: + ptr1 = r300_resource(r300->index_buffer.buffer)->b.user_ptr; + ptr1 += start; + + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | + r300_translate_primitive(mode)); + + if (indexBias && !r300->screen->caps.index_bias_supported) { + for (i = 0; i < count-1; i += 2) + OUT_CS(((ptr1[i+1] + indexBias) << 16) | + (ptr1[i] + indexBias)); + + if (count & 1) + OUT_CS(ptr1[i] + indexBias); + } else { + for (i = 0; i < count-1; i += 2) + OUT_CS(((ptr1[i+1]) << 16) | + (ptr1[i] )); + + if (count & 1) + OUT_CS(ptr1[i]); + } + break; + + case 2: + ptr2 = (uint16_t*)r300_resource(r300->index_buffer.buffer)->b.user_ptr; + ptr2 += start; + + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | + r300_translate_primitive(mode)); + + if (indexBias && !r300->screen->caps.index_bias_supported) { + for (i = 0; i < count-1; i += 2) + OUT_CS(((ptr2[i+1] + indexBias) << 16) | + (ptr2[i] + indexBias)); + + if (count & 1) + OUT_CS(ptr2[i] + indexBias); + } else { + OUT_CS_TABLE(ptr2, count_dwords); + } + break; + + case 4: + ptr4 = (uint32_t*)r300_resource(r300->index_buffer.buffer)->b.user_ptr; + ptr4 += start; + + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | + R300_VAP_VF_CNTL__INDEX_SIZE_32bit | + r300_translate_primitive(mode)); + + if (indexBias && !r300->screen->caps.index_bias_supported) { + for (i = 0; i < count; i++) + OUT_CS(ptr4[i] + indexBias); + } else { + OUT_CS_TABLE(ptr4, count_dwords); + } + break; + } END_CS; } -/* This is the fast-path drawing & emission for HW TCL. */ -static void r300_draw_range_elements(struct pipe_context* pipe, - int indexBias, - unsigned minIndex, - unsigned maxIndex, - unsigned mode, - unsigned start, - unsigned count) +static void r300_draw_elements(struct r300_context *r300, int indexBias, + unsigned minIndex, unsigned maxIndex, + unsigned mode, unsigned start, unsigned count) { - struct r300_context* r300 = r300_context(pipe); struct pipe_resource *indexBuffer = r300->index_buffer.buffer; unsigned indexSize = r300->index_buffer.index_size; struct pipe_resource* orgIndexBuffer = indexBuffer; @@ -570,30 +635,28 @@ static void r300_draw_range_elements(struct pipe_context* pipe, /* Fallback for misaligned ushort indices. */ if (indexSize == 2 && (start & 1) && - !r300_is_user_buffer(indexBuffer)) { - struct pipe_transfer *transfer; - struct pipe_resource *userbuf; - - uint16_t *ptr = pipe_buffer_map(pipe, indexBuffer, - PIPE_TRANSFER_READ, &transfer); + !r300_resource(indexBuffer)->b.user_ptr) { + /* If we got here, then orgIndexBuffer == indexBuffer. */ + uint16_t *ptr = r300->rws->buffer_map(r300_resource(orgIndexBuffer)->buf, + r300->cs, + PIPE_TRANSFER_READ | + PIPE_TRANSFER_UNSYNCHRONIZED); if (mode == PIPE_PRIM_TRIANGLES) { memcpy(indices3, ptr + start, 6); } else { /* Copy the mapped index buffer directly to the upload buffer. * The start index will be aligned simply from the fact that - * every sub-buffer in u_upload_mgr is aligned. */ - userbuf = pipe->screen->user_buffer_create(pipe->screen, - ptr, 0, - PIPE_BIND_INDEX_BUFFER); - indexBuffer = userbuf; - r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, count); - pipe_resource_reference(&userbuf, NULL); + * every sub-buffer in the upload buffer is aligned. */ + r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, + count, (uint8_t*)ptr); } - pipe_buffer_unmap(pipe, transfer); + r300->rws->buffer_unmap(r300_resource(orgIndexBuffer)->buf); } else { - if (r300_is_user_buffer(indexBuffer)) - r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, count); + if (r300_resource(indexBuffer)->b.user_ptr) + r300_upload_index_buffer(r300, &indexBuffer, indexSize, + &start, count, + r300_resource(indexBuffer)->b.user_ptr); } /* 19 dwords for emit_draw_elements. Give up if the function fails. */ @@ -607,7 +670,11 @@ static void r300_draw_range_elements(struct pipe_context* pipe, minIndex, maxIndex, mode, start, count, indices3); } else { do { - short_count = MIN2(count, 65534); + if (indexSize == 2 && (start & 1)) + short_count = MIN2(count, 65535); + else + short_count = MIN2(count, 65534); + r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, short_count, indices3); @@ -631,43 +698,38 @@ done: } } -static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, +static void r300_draw_arrays(struct r300_context *r300, unsigned mode, unsigned start, unsigned count) { - struct r300_context* r300 = r300_context(pipe); boolean alt_num_verts = r300->screen->caps.is_r500 && count > 65536 && r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); unsigned short_count; - if (immd_is_good_idea(r300, count)) { - r300_emit_draw_arrays_immediate(r300, mode, start, count); + /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ + if (!r300_prepare_for_rendering(r300, + PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS, + NULL, 9, start, 0)) + return; + + if (alt_num_verts || count <= 65535) { + r300_emit_draw_arrays(r300, mode, count); } else { - /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ - if (!r300_prepare_for_rendering(r300, - PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS, - NULL, 9, start, 0)) - return; + do { + short_count = MIN2(count, 65535); + r300_emit_draw_arrays(r300, mode, short_count); - if (alt_num_verts || count <= 65535) { - r300_emit_draw_arrays(r300, mode, count); - } else { - do { - short_count = MIN2(count, 65535); - r300_emit_draw_arrays(r300, mode, short_count); - - start += short_count; - count -= short_count; - - /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ - if (count) { - if (!r300_prepare_for_rendering(r300, - PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9, - start, 0)) - return; - } - } while (count); - } + start += short_count; + count -= short_count; + + /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ + if (count) { + if (!r300_prepare_for_rendering(r300, + PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9, + start, 0)) + return; + } + } while (count); } } @@ -676,83 +738,45 @@ static void r300_draw_vbo(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); unsigned count = info->count; - boolean translate = FALSE; + boolean buffers_updated, uploader_flushed; boolean indexed = info->indexed && r300->index_buffer.buffer; - unsigned min_index = 0; - unsigned max_index = r300->vertex_buffer_max_index; + unsigned start_indexed = info->start + r300->index_buffer.offset; + int max_index = MIN2(r300->vbuf_mgr->max_index, info->max_index); - if (r300->skip_rendering) { + if (r300->skip_rendering || + !u_trim_pipe_prim(info->mode, &count)) { return; } - if (!u_trim_pipe_prim(info->mode, &count)) { - return; + /* Start the vbuf manager and update buffers if needed. */ + u_vbuf_mgr_draw_begin(r300->vbuf_mgr, info, + &buffers_updated, &uploader_flushed); + if (buffers_updated) { + r300->vertex_arrays_dirty = TRUE; } - if (indexed) { - int real_min_index, real_max_index; - /* Compute the start for draw_elements, taking the offset into account. */ - unsigned start_indexed = - info->start + - (r300->index_buffer.offset / r300->index_buffer.index_size); - - assert(r300->index_buffer.offset % r300->index_buffer.index_size == 0); - - /* Index buffer range checking. */ - if ((start_indexed + count) * r300->index_buffer.index_size > - r300->index_buffer.buffer->width0) { - fprintf(stderr, "r300: Invalid index buffer range. Skipping rendering.\n"); - return; - } - - min_index = MAX2(min_index, info->min_index); - max_index = MIN2(max_index, info->max_index); - real_min_index = (int)min_index - info->index_bias; - real_max_index = (int)max_index - info->index_bias; - - if (max_index >= (1 << 24) - 1) { - fprintf(stderr, "r300: Invalid max_index: %i. Skipping rendering...\n", max_index); - return; - } - - r300_update_derived_state(r300); - - /* Set up the fallback for an incompatible vertex layout if needed. */ - if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { - r300_begin_vertex_translate(r300, real_min_index, real_max_index); - translate = TRUE; - } + /* Draw. */ + r300_update_derived_state(r300); - /* Upload vertex buffers. */ - if (r300->any_user_vbs) { - r300_upload_user_buffers(r300, real_min_index, real_max_index); + if (indexed) { + if (count <= 8 && + r300_resource(r300->index_buffer.buffer)->b.user_ptr) { + r300_draw_elements_immediate(r300, info->index_bias, + info->min_index, max_index, + info->mode, start_indexed, count); + } else { + r300_draw_elements(r300, info->index_bias, info->min_index, + max_index, info->mode, start_indexed, count); } - - r300_draw_range_elements(pipe, info->index_bias, min_index, max_index, - info->mode, start_indexed, count); } else { - min_index = MAX2(min_index, info->start); - max_index = MIN2(max_index, info->start + count - 1); - - r300_update_derived_state(r300); - - /* Set up the fallback for an incompatible vertex layout if needed. */ - if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { - r300_begin_vertex_translate(r300, min_index, max_index); - translate = TRUE; - } - - /* Upload vertex buffers. */ - if (r300->any_user_vbs) { - r300_upload_user_buffers(r300, min_index, max_index); + if (immd_is_good_idea(r300, count)) { + r300_draw_arrays_immediate(r300, info->mode, info->start, count); + } else { + r300_draw_arrays(r300, info->mode, info->start, count); } - - r300_draw_arrays(pipe, info->mode, info->start, count); } - if (translate) { - r300_end_vertex_translate(r300); - } + u_vbuf_mgr_draw_end(r300->vbuf_mgr); } /**************************************************************************** @@ -787,11 +811,12 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe, (indexed ? PREP_INDEXED : 0), indexed ? 256 : 6); - for (i = 0; i < r300->vertex_buffer_count; i++) { - if (r300->vertex_buffer[i].buffer) { + for (i = 0; i < r300->vbuf_mgr->nr_vertex_buffers; i++) { + if (r300->vbuf_mgr->vertex_buffer[i].buffer) { void *buf = pipe_buffer_map(pipe, - r300->vertex_buffer[i].buffer, - PIPE_TRANSFER_READ, + r300->vbuf_mgr->vertex_buffer[i].buffer, + PIPE_TRANSFER_READ | + PIPE_TRANSFER_UNSYNCHRONIZED, &vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, buf); } @@ -799,7 +824,8 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe, if (indexed) { indices = pipe_buffer_map(pipe, r300->index_buffer.buffer, - PIPE_TRANSFER_READ, &ib_transfer); + PIPE_TRANSFER_READ | + PIPE_TRANSFER_UNSYNCHRONIZED, &ib_transfer); } draw_set_mapped_index_buffer(r300->draw, indices); @@ -810,8 +836,8 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe, draw_flush(r300->draw); r300->draw_vbo_locked = FALSE; - for (i = 0; i < r300->vertex_buffer_count; i++) { - if (r300->vertex_buffer[i].buffer) { + for (i = 0; i < r300->vbuf_mgr->nr_vertex_buffers; i++) { + if (r300->vbuf_mgr->vertex_buffer[i].buffer) { pipe_buffer_unmap(pipe, vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, NULL); } @@ -874,10 +900,10 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render, pipe_resource_reference(&r300->vbo, NULL); r300->vbo = pipe_buffer_create(screen, PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STREAM, R300_MAX_DRAW_VBO_SIZE); r300->draw_vbo_offset = 0; r300->draw_vbo_size = R300_MAX_DRAW_VBO_SIZE; - r300->validate_buffers = TRUE; } r300render->vertex_size = vertex_size; @@ -896,7 +922,8 @@ static void* r300_render_map_vertices(struct vbuf_render* render) r300render->vbo_ptr = pipe_buffer_map(&r300render->r300->context, r300->vbo, - PIPE_TRANSFER_WRITE, + PIPE_TRANSFER_WRITE | + PIPE_TRANSFER_UNSYNCHRONIZED, &r300render->vbo_transfer); assert(r300render->vbo_ptr); @@ -963,7 +990,7 @@ static void r300_render_draw_arrays(struct vbuf_render* render, if (r300->draw_first_emitted) { if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL, - NULL, 6, 0, 0)) + NULL, dwords, 0, 0)) return; } else { if (!r300_emit_states(r300, @@ -972,23 +999,6 @@ static void r300_render_draw_arrays(struct vbuf_render* render, return; } - /* Uncomment to dump all VBOs rendered through this interface. - * Slow and noisy! - ptr = pipe_buffer_map(&r300render->r300->context, - r300render->vbo, PIPE_TRANSFER_READ, - &r300render->vbo_transfer); - - for (i = 0; i < count; i++) { - printf("r300: Vertex %d\n", i); - draw_dump_emitted_vertex(&r300->vertex_info, ptr); - ptr += r300->vertex_info.size * 4; - printf("\n"); - } - - pipe_buffer_unmap(&r300render->r300->context, r300render->vbo, - r300render->vbo_transfer); - */ - BEGIN_CS(dwords); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, r300render->prim)); @@ -1250,7 +1260,7 @@ static void r300_resource_resolve(struct pipe_context* pipe, aa->aaresolve_ctl = R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE | R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_AVERAGE; - r300->aa_state.size = 12; + r300->aa_state.size = 10; r300_mark_atom_dirty(r300, &r300->aa_state); /* Resolve the surface. */ diff --git a/src/gallium/drivers/r300/r300_render_translate.c b/src/gallium/drivers/r300/r300_render_translate.c index c48062c8084..f8c7558f4b4 100644 --- a/src/gallium/drivers/r300/r300_render_translate.c +++ b/src/gallium/drivers/r300/r300_render_translate.c @@ -20,207 +20,64 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/** - * The functions below translate vertex and index buffers to the layout - * compatible with the hardware, so that all vertex and index fetches are - * DWORD-aligned and all used vertex and index formats are supported. - * For indices, an optional index offset is added to each index. - */ - #include "r300_context.h" -#include "translate/translate.h" #include "util/u_index_modify.h" +#include "util/u_upload_mgr.h" -/* XXX Optimization: use min_index and translate only that range. */ -/* XXX Use the uploader. */ -void r300_begin_vertex_translate(struct r300_context *r300, - int min_index, int max_index) -{ - struct pipe_context *pipe = &r300->context; - struct translate_key key = {0}; - struct translate_element *te; - unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0}; - struct translate *tr; - struct r300_vertex_element_state *ve = r300->velems; - boolean vb_translated[PIPE_MAX_ATTRIBS] = {0}; - void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map; - struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer; - struct pipe_resource *out_buffer; - unsigned i, num_verts; - unsigned slot; - - /* Initialize the translate key, i.e. the recipe how vertices should be - * translated. */ - for (i = 0; i < ve->count; i++) { - struct pipe_vertex_buffer *vb = - &r300->vertex_buffer[ve->velem[i].vertex_buffer_index]; - enum pipe_format output_format = ve->hw_format[i]; - unsigned output_format_size = ve->hw_format_size[i]; - - /* Check for support. */ - if (ve->velem[i].src_format == ve->hw_format[i] && - (vb->buffer_offset + ve->velem[i].src_offset) % 4 == 0 && - vb->stride % 4 == 0) { - continue; - } - - /* Workaround for translate: output floats instead of halfs. */ - switch (output_format) { - case PIPE_FORMAT_R16_FLOAT: - output_format = PIPE_FORMAT_R32_FLOAT; - output_format_size = 4; - break; - case PIPE_FORMAT_R16G16_FLOAT: - output_format = PIPE_FORMAT_R32G32_FLOAT; - output_format_size = 8; - break; - case PIPE_FORMAT_R16G16B16_FLOAT: - output_format = PIPE_FORMAT_R32G32B32_FLOAT; - output_format_size = 12; - break; - case PIPE_FORMAT_R16G16B16A16_FLOAT: - output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - output_format_size = 16; - break; - default:; - } - - /* Add this vertex element. */ - te = &key.element[key.nr_elements]; - /*te->type; - te->instance_divisor;*/ - te->input_buffer = ve->velem[i].vertex_buffer_index; - te->input_format = ve->velem[i].src_format; - te->input_offset = vb->buffer_offset + ve->velem[i].src_offset; - te->output_format = output_format; - te->output_offset = key.output_stride; - - key.output_stride += output_format_size; - vb_translated[ve->velem[i].vertex_buffer_index] = TRUE; - tr_elem_index[i] = key.nr_elements; - key.nr_elements++; - } - - /* Get a translate object. */ - tr = translate_cache_find(r300->tran.translate_cache, &key); - - /* Map buffers we want to translate. */ - for (i = 0; i < r300->vertex_buffer_count; i++) { - if (vb_translated[i]) { - struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i]; - - vb_map[i] = pipe_buffer_map(pipe, vb->buffer, - PIPE_TRANSFER_READ, &vb_transfer[i]); - - tr->set_buffer(tr, i, vb_map[i], vb->stride, max_index); - } - } - - /* Create and map the output buffer. */ - num_verts = max_index + 1; - - out_buffer = pipe_buffer_create(&r300->screen->screen, - PIPE_BIND_VERTEX_BUFFER, - key.output_stride * num_verts); - - out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE, - &out_transfer); - - /* Translate. */ - tr->run(tr, 0, num_verts, 0, out_map); - - /* Unmap all buffers. */ - for (i = 0; i < r300->vertex_buffer_count; i++) { - if (vb_translated[i]) { - pipe_buffer_unmap(pipe, vb_transfer[i]); - } - } - - pipe_buffer_unmap(pipe, out_transfer); - - /* Setup the new vertex buffer in the first free slot. */ - slot = ~0; - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i]; - - if (!vb->buffer) { - pipe_resource_reference(&r300->valid_vertex_buffer[i], out_buffer); - vb->buffer_offset = 0; - vb->stride = key.output_stride; - slot = i; - /* XXX probably need to preserve the real count for u_blitter_save_*. */ - r300->vertex_buffer_count = MAX2(r300->vertex_buffer_count, i+1); - r300->validate_buffers = TRUE; - break; - } - } - /* XXX This may fail. */ - assert(slot != ~0); - - /* Save and replace vertex elements. */ - { - struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS]; - - r300->tran.saved_velems = r300->velems; - - for (i = 0; i < ve->count; i++) { - if (vb_translated[ve->velem[i].vertex_buffer_index]) { - te = &key.element[tr_elem_index[i]]; - new_velems[i].instance_divisor = ve->velem[i].instance_divisor; - new_velems[i].src_format = te->output_format; - new_velems[i].src_offset = te->output_offset; - new_velems[i].vertex_buffer_index = slot; - } else { - memcpy(&new_velems[i], &ve->velem[i], - sizeof(struct pipe_vertex_element)); - } - } - - r300->tran.new_velems = - pipe->create_vertex_elements_state(pipe, ve->count, new_velems); - pipe->bind_vertex_elements_state(pipe, r300->tran.new_velems); - } - - pipe_resource_reference(&out_buffer, NULL); -} -void r300_end_vertex_translate(struct r300_context *r300) -{ - struct pipe_context *pipe = &r300->context; - - /* Restore vertex elements. */ - pipe->bind_vertex_elements_state(pipe, r300->tran.saved_velems); - pipe->delete_vertex_elements_state(pipe, r300->tran.new_velems); -} - -/* XXX Use the uploader. */ void r300_translate_index_buffer(struct r300_context *r300, struct pipe_resource **index_buffer, unsigned *index_size, unsigned index_offset, unsigned *start, unsigned count) { + struct pipe_resource *out_buffer = NULL; + unsigned out_offset; + void *ptr; + boolean flushed; + switch (*index_size) { - case 1: - util_shorten_ubyte_elts(&r300->context, index_buffer, index_offset, *start, count); - *index_size = 2; - *start = 0; - r300->validate_buffers = TRUE; - break; + case 1: + u_upload_alloc(r300->vbuf_mgr->uploader, 0, count * 2, + &out_offset, &out_buffer, &flushed, &ptr); + + util_shorten_ubyte_elts_to_userptr( + &r300->context, *index_buffer, index_offset, + *start, count, ptr); + + *index_buffer = NULL; + pipe_resource_reference(index_buffer, out_buffer); + *index_size = 2; + *start = out_offset / 2; + break; + + case 2: + if (index_offset) { + u_upload_alloc(r300->vbuf_mgr->uploader, 0, count * 2, + &out_offset, &out_buffer, &flushed, &ptr); + + util_rebuild_ushort_elts_to_userptr(&r300->context, *index_buffer, + index_offset, *start, + count, ptr); + + *index_buffer = NULL; + pipe_resource_reference(index_buffer, out_buffer); + *start = out_offset / 2; + } + break; - case 2: - if (index_offset) { - util_rebuild_ushort_elts(&r300->context, index_buffer, index_offset, *start, count); - *start = 0; - r300->validate_buffers = TRUE; - } - break; + case 4: + if (index_offset) { + u_upload_alloc(r300->vbuf_mgr->uploader, 0, count * 4, + &out_offset, &out_buffer, &flushed, &ptr); - case 4: - if (index_offset) { - util_rebuild_uint_elts(&r300->context, index_buffer, index_offset, *start, count); - *start = 0; - r300->validate_buffers = TRUE; - } - break; + util_rebuild_uint_elts_to_userptr(&r300->context, *index_buffer, + index_offset, *start, + count, ptr); + + *index_buffer = NULL; + pipe_resource_reference(index_buffer, out_buffer); + *start = out_offset / 4; + } + break; } } diff --git a/src/gallium/drivers/r300/r300_resource.c b/src/gallium/drivers/r300/r300_resource.c index dd1df970594..f3d8c5b889f 100644 --- a/src/gallium/drivers/r300/r300_resource.c +++ b/src/gallium/drivers/r300/r300_resource.c @@ -38,26 +38,22 @@ r300_resource_create(struct pipe_screen *screen, } -static struct pipe_resource * -r300_resource_from_handle(struct pipe_screen * screen, - const struct pipe_resource *templ, - struct winsys_handle *whandle) +static unsigned r300_resource_is_referenced_by_cs(struct pipe_context *context, + struct pipe_resource *buf, + unsigned level, int layer) { - if (templ->target == PIPE_BUFFER) - return NULL; - else - return r300_texture_from_handle(screen, templ, whandle); + return r300_buffer_is_referenced(context, buf); } void r300_init_resource_functions(struct r300_context *r300) { r300->context.get_transfer = u_get_transfer_vtbl; r300->context.transfer_map = u_transfer_map_vtbl; - r300->context.transfer_flush_region = u_transfer_flush_region_vtbl; + r300->context.transfer_flush_region = u_default_transfer_flush_region; r300->context.transfer_unmap = u_transfer_unmap_vtbl; r300->context.transfer_destroy = u_transfer_destroy_vtbl; r300->context.transfer_inline_write = u_transfer_inline_write_vtbl; - r300->context.is_resource_referenced = u_is_resource_referenced_vtbl; + r300->context.is_resource_referenced = r300_resource_is_referenced_by_cs; r300->context.create_surface = r300_create_surface; r300->context.surface_destroy = r300_surface_destroy; } @@ -65,8 +61,8 @@ void r300_init_resource_functions(struct r300_context *r300) void r300_init_screen_resource_functions(struct r300_screen *r300screen) { r300screen->screen.resource_create = r300_resource_create; - r300screen->screen.resource_from_handle = r300_resource_from_handle; - r300screen->screen.resource_get_handle = u_resource_get_handle_vtbl; + r300screen->screen.resource_from_handle = r300_texture_from_handle; + r300screen->screen.resource_get_handle = r300_resource_get_handle; r300screen->screen.resource_destroy = u_resource_destroy_vtbl; r300screen->screen.user_buffer_create = r300_user_buffer_create; } diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index c75aeaa10a7..77a9c6ad86f 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -34,10 +34,6 @@ #include "draw/draw_context.h" -#ifdef HAVE_LLVM -#include "gallivm/lp_bld_init.h" -#endif - /* Return the identifier behind whom the brave coders responsible for this * amalgamation of code, sweat, and duct tape, routinely obscure their names. * @@ -87,12 +83,8 @@ static const char* r300_get_name(struct pipe_screen* pscreen) static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) { struct r300_screen* r300screen = r300_screen(pscreen); - boolean is_r400 = r300screen->caps.is_r400; boolean is_r500 = r300screen->caps.is_r500; - /* XXX extended shader capabilities of r400 unimplemented */ - is_r400 = FALSE; - switch (param) { /* Supported features (boolean caps). */ case PIPE_CAP_NPOT_TEXTURES: @@ -129,11 +121,13 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_DUAL_SOURCE_BLEND: case PIPE_CAP_INDEP_BLEND_ENABLE: case PIPE_CAP_INDEP_BLEND_FUNC: - case PIPE_CAP_DEPTH_CLAMP: /* XXX implemented, but breaks Regnum Online */ + case PIPE_CAP_DEPTH_CLAMP: case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_STREAM_OUTPUT: case PIPE_CAP_PRIMITIVE_RESTART: + case PIPE_CAP_INSTANCED_DRAWING: + case PIPE_CAP_ARRAY_TEXTURES: return 0; /* Texturing. */ @@ -175,9 +169,6 @@ static int r300_get_shader_param(struct pipe_screen *pscreen, unsigned shader, e boolean is_r400 = r300screen->caps.is_r400; boolean is_r500 = r300screen->caps.is_r500; - /* XXX extended shader capabilities of r400 unimplemented */ - is_r400 = FALSE; - switch (shader) { case PIPE_SHADER_FRAGMENT: @@ -407,6 +398,7 @@ static void r300_destroy_screen(struct pipe_screen* pscreen) struct r300_winsys_screen *rws = r300_winsys_screen(pscreen); util_slab_destroy(&r300screen->pool_buffers); + pipe_mutex_destroy(r300screen->num_contexts_mutex); if (rws) rws->destroy(rws); @@ -418,32 +410,28 @@ static void r300_fence_reference(struct pipe_screen *screen, struct pipe_fence_handle **ptr, struct pipe_fence_handle *fence) { - struct r300_fence **oldf = (struct r300_fence**)ptr; - struct r300_fence *newf = (struct r300_fence*)fence; - - if (pipe_reference(&(*oldf)->reference, &newf->reference)) - FREE(*oldf); - - *ptr = fence; + r300_winsys_bo_reference((struct r300_winsys_bo**)ptr, + (struct r300_winsys_bo*)fence); } static int r300_fence_signalled(struct pipe_screen *screen, struct pipe_fence_handle *fence, unsigned flags) { - struct r300_fence *rfence = (struct r300_fence*)fence; + struct r300_winsys_screen *rws = r300_screen(screen)->rws; + struct r300_winsys_bo *rfence = (struct r300_winsys_bo*)fence; - return rfence->signalled ? 0 : 1; /* 0 == success */ + return !rws->buffer_is_busy(rfence) ? 0 : 1; /* 0 == success */ } static int r300_fence_finish(struct pipe_screen *screen, struct pipe_fence_handle *fence, unsigned flags) { - struct r300_fence *rfence = (struct r300_fence*)fence; + struct r300_winsys_screen *rws = r300_screen(screen)->rws; + struct r300_winsys_bo *rfence = (struct r300_winsys_bo*)fence; - r300_finish(rfence->ctx); - rfence->signalled = TRUE; + rws->buffer_wait(rfence); return 0; /* 0 == success */ } @@ -463,12 +451,19 @@ struct pipe_screen* r300_screen_create(struct r300_winsys_screen *rws) r300_init_debug(r300screen); r300_parse_chipset(&r300screen->caps); + if (SCREEN_DBG_ON(r300screen, DBG_NO_ZMASK)) + r300screen->caps.zmask_ram = 0; + if (SCREEN_DBG_ON(r300screen, DBG_NO_HIZ)) + r300screen->caps.hiz_ram = 0; + r300screen->caps.index_bias_supported = r300screen->caps.is_r500 && rws->get_value(rws, R300_VID_DRM_2_3_0); + pipe_mutex_init(r300screen->num_contexts_mutex); + util_slab_create(&r300screen->pool_buffers, - sizeof(struct r300_buffer), 64, + sizeof(struct r300_resource), 64, UTIL_SLAB_SINGLETHREADED); r300screen->rws = rws; @@ -490,9 +485,5 @@ struct pipe_screen* r300_screen_create(struct r300_winsys_screen *rws) util_format_s3tc_init(); -#ifdef HAVE_LLVM - lp_build_init(); -#endif - return &r300screen->screen; } diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index 752f53b7579..576f9c1f4a9 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -52,6 +52,7 @@ struct r300_screen { /* The number of created contexts to know whether we have multiple * contexts or not. */ int num_contexts; + pipe_mutex num_contexts_mutex; }; @@ -94,6 +95,7 @@ r300_winsys_screen(struct pipe_screen *screen) { #define DBG_HYPERZ (1 << 12) #define DBG_SCISSOR (1 << 13) #define DBG_UPLOAD (1 << 14) +#define DBG_INFO (1 << 15) /* Features. */ #define DBG_ANISOHQ (1 << 16) #define DBG_NO_TILING (1 << 17) @@ -101,6 +103,8 @@ r300_winsys_screen(struct pipe_screen *screen) { #define DBG_FAKE_OCC (1 << 19) #define DBG_NO_OPT (1 << 20) #define DBG_NO_CBZB (1 << 21) +#define DBG_NO_ZMASK (1 << 22) +#define DBG_NO_HIZ (1 << 23) /* Statistics. */ #define DBG_P_STAT (1 << 25) /*@}*/ diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c index cc3c1d7687e..1045911f3ae 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.c +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -34,117 +34,50 @@ #include "r300_winsys.h" unsigned r300_buffer_is_referenced(struct pipe_context *context, - struct pipe_resource *buf, - enum r300_reference_domain domain) + struct pipe_resource *buf) { struct r300_context *r300 = r300_context(context); - struct r300_buffer *rbuf = r300_buffer(buf); + struct r300_resource *rbuf = r300_resource(buf); - if (r300_is_user_buffer(buf)) + if (rbuf->b.user_ptr || rbuf->constant_buffer) return PIPE_UNREFERENCED; - if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->cs_buf, domain)) + if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->cs_buf)) return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; return PIPE_UNREFERENCED; } -static unsigned r300_buffer_is_referenced_by_cs(struct pipe_context *context, - struct pipe_resource *buf, - unsigned level, int layer) -{ - return r300_buffer_is_referenced(context, buf, R300_REF_CS); -} - void r300_upload_index_buffer(struct r300_context *r300, struct pipe_resource **index_buffer, unsigned index_size, unsigned *start, - unsigned count) + unsigned count, uint8_t *ptr) { unsigned index_offset; - uint8_t *ptr = r300_buffer(*index_buffer)->user_buffer; boolean flushed; *index_buffer = NULL; - u_upload_data(r300->upload_ib, + u_upload_data(r300->vbuf_mgr->uploader, 0, count * index_size, ptr + (*start * index_size), &index_offset, index_buffer, &flushed); *start = index_offset / index_size; - - if (flushed || !r300->upload_ib_validated) { - r300->upload_ib_validated = FALSE; - r300->validate_buffers = TRUE; - } -} - -void r300_upload_user_buffers(struct r300_context *r300, - int min_index, int max_index) -{ - int i, nr = r300->velems->count; - unsigned count = max_index + 1 - min_index; - boolean flushed; - boolean uploaded[16] = {0}; - - for (i = 0; i < nr; i++) { - unsigned index = r300->velems->velem[i].vertex_buffer_index; - struct pipe_vertex_buffer *vb = &r300->vertex_buffer[index]; - struct r300_buffer *userbuf = r300_buffer(vb->buffer); - - if (userbuf && userbuf->user_buffer && !uploaded[index]) { - unsigned first, size; - - if (vb->stride) { - first = vb->stride * min_index; - size = vb->stride * count; - } else { - first = 0; - size = r300->velems->hw_format_size[i]; - } - - DBG(r300, DBG_UPLOAD, - "Uploading %i bytes, index: %i, buffer: %p, userptr: %p " - "offset: %i, stride: %i.\n", - size, index, userbuf, userbuf->user_buffer, - vb->buffer_offset, vb->stride); - - u_upload_data(r300->upload_vb, first, size, - userbuf->user_buffer + first, - &vb->buffer_offset, - &r300->valid_vertex_buffer[index], - &flushed); - - vb->buffer_offset -= first; - - r300->vertex_arrays_dirty = TRUE; - - if (flushed || !r300->upload_vb_validated) { - r300->upload_vb_validated = FALSE; - r300->validate_buffers = TRUE; - } - uploaded[index] = TRUE; - } else { - assert(r300->valid_vertex_buffer[index]); - } - } - DBG(r300, DBG_UPLOAD, "-------\n"); } static void r300_buffer_destroy(struct pipe_screen *screen, struct pipe_resource *buf) { struct r300_screen *r300screen = r300_screen(screen); - struct r300_buffer *rbuf = r300_buffer(buf); - struct r300_winsys_screen *rws = r300screen->rws; + struct r300_resource *rbuf = r300_resource(buf); if (rbuf->constant_buffer) FREE(rbuf->constant_buffer); if (rbuf->buf) - rws->buffer_reference(rws, &rbuf->buf, NULL); + r300_winsys_bo_reference(&rbuf->buf, NULL); util_slab_free(&r300screen->pool_buffers, rbuf); } @@ -188,15 +121,15 @@ r300_buffer_transfer_map( struct pipe_context *pipe, struct r300_context *r300 = r300_context(pipe); struct r300_screen *r300screen = r300_screen(pipe->screen); struct r300_winsys_screen *rws = r300screen->rws; - struct r300_buffer *rbuf = r300_buffer(transfer->resource); + struct r300_resource *rbuf = r300_resource(transfer->resource); uint8_t *map; - if (rbuf->user_buffer) - return (uint8_t *) rbuf->user_buffer + transfer->box.x; + if (rbuf->b.user_ptr) + return (uint8_t *) rbuf->b.user_ptr + transfer->box.x; if (rbuf->constant_buffer) return (uint8_t *) rbuf->constant_buffer + transfer->box.x; - map = rws->buffer_map(rws, rbuf->buf, r300->cs, transfer->usage); + map = rws->buffer_map(rbuf->buf, r300->cs, transfer->usage); if (map == NULL) return NULL; @@ -204,22 +137,15 @@ r300_buffer_transfer_map( struct pipe_context *pipe, return map + transfer->box.x; } -static void r300_buffer_transfer_flush_region( struct pipe_context *pipe, - struct pipe_transfer *transfer, - const struct pipe_box *box) -{ - /* no-op */ -} - static void r300_buffer_transfer_unmap( struct pipe_context *pipe, struct pipe_transfer *transfer ) { struct r300_screen *r300screen = r300_screen(pipe->screen); struct r300_winsys_screen *rws = r300screen->rws; - struct r300_buffer *rbuf = r300_buffer(transfer->resource); + struct r300_resource *rbuf = r300_resource(transfer->resource); if (rbuf->buf) { - rws->buffer_unmap(rws, rbuf->buf); + rws->buffer_unmap(rbuf->buf); } } @@ -234,32 +160,32 @@ static void r300_buffer_transfer_inline_write(struct pipe_context *pipe, { struct r300_context *r300 = r300_context(pipe); struct r300_winsys_screen *rws = r300->screen->rws; - struct r300_buffer *rbuf = r300_buffer(resource); + struct r300_resource *rbuf = r300_resource(resource); uint8_t *map = NULL; if (rbuf->constant_buffer) { memcpy(rbuf->constant_buffer + box->x, data, box->width); return; } - assert(rbuf->user_buffer == NULL); + assert(rbuf->b.user_ptr == NULL); - map = rws->buffer_map(rws, rbuf->buf, r300->cs, + map = rws->buffer_map(rbuf->buf, r300->cs, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | usage); memcpy(map + box->x, data, box->width); - rws->buffer_unmap(rws, rbuf->buf); + rws->buffer_unmap(rbuf->buf); } -struct u_resource_vtbl r300_buffer_vtbl = +static const struct u_resource_vtbl r300_buffer_vtbl = { - u_default_resource_get_handle, /* get_handle */ + NULL, /* get_handle */ r300_buffer_destroy, /* resource_destroy */ - r300_buffer_is_referenced_by_cs, /* is_buffer_referenced */ + NULL, /* is_buffer_referenced */ r300_buffer_get_transfer, /* get_transfer */ r300_buffer_transfer_destroy, /* transfer_destroy */ r300_buffer_transfer_map, /* transfer_map */ - r300_buffer_transfer_flush_region, /* transfer_flush_region */ + NULL, /* transfer_flush_region */ r300_buffer_transfer_unmap, /* transfer_unmap */ r300_buffer_transfer_inline_write /* transfer_inline_write */ }; @@ -268,42 +194,41 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, const struct pipe_resource *templ) { struct r300_screen *r300screen = r300_screen(screen); - struct r300_buffer *rbuf; + struct r300_resource *rbuf; unsigned alignment = 16; rbuf = util_slab_alloc(&r300screen->pool_buffers); - rbuf->magic = R300_BUFFER_MAGIC; - - rbuf->b.b = *templ; - rbuf->b.vtbl = &r300_buffer_vtbl; - pipe_reference_init(&rbuf->b.b.reference, 1); - rbuf->b.b.screen = screen; + rbuf->b.b.b = *templ; + rbuf->b.b.vtbl = &r300_buffer_vtbl; + pipe_reference_init(&rbuf->b.b.b.reference, 1); + rbuf->b.b.b.screen = screen; + rbuf->b.user_ptr = NULL; rbuf->domain = R300_DOMAIN_GTT; rbuf->buf = NULL; + rbuf->buf_size = templ->width0; rbuf->constant_buffer = NULL; - rbuf->user_buffer = NULL; /* Alloc constant buffers in RAM. */ if (templ->bind & PIPE_BIND_CONSTANT_BUFFER) { rbuf->constant_buffer = MALLOC(templ->width0); - return &rbuf->b.b; + return &rbuf->b.b.b; } rbuf->buf = r300screen->rws->buffer_create(r300screen->rws, - rbuf->b.b.width0, alignment, - rbuf->b.b.bind, rbuf->b.b.usage, + rbuf->b.b.b.width0, alignment, + rbuf->b.b.b.bind, rbuf->b.b.b.usage, rbuf->domain); - rbuf->cs_buf = - r300screen->rws->buffer_get_cs_handle(r300screen->rws, rbuf->buf); - if (!rbuf->buf) { util_slab_free(&r300screen->pool_buffers, rbuf); return NULL; } - return &rbuf->b.b; + rbuf->cs_buf = + r300screen->rws->buffer_get_cs_handle(rbuf->buf); + + return &rbuf->b.b.b; } struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, @@ -311,27 +236,26 @@ struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, unsigned bind) { struct r300_screen *r300screen = r300_screen(screen); - struct r300_buffer *rbuf; + struct r300_resource *rbuf; rbuf = util_slab_alloc(&r300screen->pool_buffers); - rbuf->magic = R300_BUFFER_MAGIC; - - pipe_reference_init(&rbuf->b.b.reference, 1); - rbuf->b.vtbl = &r300_buffer_vtbl; - rbuf->b.b.screen = screen; - rbuf->b.b.target = PIPE_BUFFER; - rbuf->b.b.format = PIPE_FORMAT_R8_UNORM; - rbuf->b.b.usage = PIPE_USAGE_IMMUTABLE; - rbuf->b.b.bind = bind; - rbuf->b.b.width0 = ~0; - rbuf->b.b.height0 = 1; - rbuf->b.b.depth0 = 1; - rbuf->b.b.array_size = 1; - rbuf->b.b.flags = 0; + pipe_reference_init(&rbuf->b.b.b.reference, 1); + rbuf->b.b.b.screen = screen; + rbuf->b.b.b.target = PIPE_BUFFER; + rbuf->b.b.b.format = PIPE_FORMAT_R8_UNORM; + rbuf->b.b.b.usage = PIPE_USAGE_IMMUTABLE; + rbuf->b.b.b.bind = bind; + rbuf->b.b.b.width0 = ~0; + rbuf->b.b.b.height0 = 1; + rbuf->b.b.b.depth0 = 1; + rbuf->b.b.b.array_size = 1; + rbuf->b.b.b.flags = 0; + rbuf->b.b.vtbl = &r300_buffer_vtbl; + rbuf->b.user_ptr = ptr; rbuf->domain = R300_DOMAIN_GTT; rbuf->buf = NULL; + rbuf->buf_size = size; rbuf->constant_buffer = NULL; - rbuf->user_buffer = ptr; - return &rbuf->b.b; + return &rbuf->b.b.b; } diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h index 58dec8539b6..14bee460d5b 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.h +++ b/src/gallium/drivers/r300/r300_screen_buffer.h @@ -35,39 +35,12 @@ #include "r300_winsys.h" #include "r300_context.h" -#define R300_BUFFER_MAGIC 0xabcd1234 -#define R300_BUFFER_MAX_RANGES 32 - -struct r300_buffer_range { - uint32_t start; - uint32_t end; -}; - -/* Vertex buffer. */ -struct r300_buffer -{ - struct u_resource b; - - uint32_t magic; - - struct r300_winsys_buffer *buf; - struct r300_winsys_cs_buffer *cs_buf; - - enum r300_buffer_domain domain; - - uint8_t *user_buffer; - uint8_t *constant_buffer; -}; - /* Functions. */ -void r300_upload_user_buffers(struct r300_context *r300, - int min_index, int max_index); - void r300_upload_index_buffer(struct r300_context *r300, struct pipe_resource **index_buffer, unsigned index_size, unsigned *start, - unsigned count); + unsigned count, uint8_t *ptr); struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, const struct pipe_resource *templ); @@ -77,8 +50,7 @@ struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, unsigned bind); unsigned r300_buffer_is_referenced(struct pipe_context *context, - struct pipe_resource *buf, - enum r300_reference_domain domain); + struct pipe_resource *buf); /* Inline functions. */ @@ -87,9 +59,4 @@ static INLINE struct r300_buffer *r300_buffer(struct pipe_resource *buffer) return (struct r300_buffer *)buffer; } -static INLINE boolean r300_is_user_buffer(struct pipe_resource *buffer) -{ - return r300_buffer(buffer)->user_buffer ? true : false; -} - #endif diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 3a97b76a4c8..09f18b3e624 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -28,6 +28,7 @@ #include "util/u_mm.h" #include "util/u_memory.h" #include "util/u_pack_color.h" +#include "util/u_transfer.h" #include "tgsi/tgsi_parse.h" @@ -442,8 +443,7 @@ static void r300_set_clip_state(struct pipe_context* pipe, OUT_CB_TABLE(state->ucp, state->nr * 4); } OUT_CB_REG(R300_VAP_CLIP_CNTL, ((1 << state->nr) - 1) | - R300_PS_UCP_MODE_CLIP_AS_TRIFAN | - (state->depth_clamp ? R300_CLIP_DISABLE : 0)); + R300_PS_UCP_MODE_CLIP_AS_TRIFAN); END_CB; r300_mark_atom_dirty(r300, &r300->clip_state); @@ -617,21 +617,16 @@ static void r300_set_stencil_ref(struct pipe_context* pipe, } static void r300_tex_set_tiling_flags(struct r300_context *r300, - struct r300_texture *tex, unsigned level) + struct r300_resource *tex, + unsigned level) { /* Check if the macrotile flag needs to be changed. * Skip changing the flags otherwise. */ - if (tex->desc.macrotile[tex->surface_level] != - tex->desc.macrotile[level]) { - /* Tiling determines how DRM treats the buffer data. - * We must flush CS when changing it if the buffer is referenced. */ - if (r300->rws->cs_is_buffer_referenced(r300->cs, - tex->cs_buffer, R300_REF_CS)) - r300->context.flush(&r300->context, 0, NULL); - - r300->rws->buffer_set_tiling(r300->rws, tex->buffer, - tex->desc.microtile, tex->desc.macrotile[level], - tex->desc.stride_in_bytes[0]); + if (tex->tex.macrotile[tex->surface_level] != + tex->tex.macrotile[level]) { + r300->rws->buffer_set_tiling(tex->buf, r300->cs, + tex->tex.microtile, tex->tex.macrotile[level], + tex->tex.stride_in_bytes[0]); tex->surface_level = level; } @@ -646,12 +641,12 @@ static void r300_fb_set_tiling_flags(struct r300_context *r300, /* Set tiling flags for new surfaces. */ for (i = 0; i < state->nr_cbufs; i++) { r300_tex_set_tiling_flags(r300, - r300_texture(state->cbufs[i]->texture), + r300_resource(state->cbufs[i]->texture), state->cbufs[i]->u.tex.level); } if (state->zsbuf) { r300_tex_set_tiling_flags(r300, - r300_texture(state->zsbuf->texture), + r300_resource(state->zsbuf->texture), state->zsbuf->u.tex.level); } } @@ -660,7 +655,7 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index, const char *binding) { struct pipe_resource *tex = surf->texture; - struct r300_texture *rtex = r300_texture(tex); + struct r300_resource *rtex = r300_resource(tex); fprintf(stderr, "r300: %s[%i] Dim: %ix%i, Firstlayer: %i, " @@ -673,9 +668,9 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index, surf->u.tex.first_layer, surf->u.tex.last_layer, surf->u.tex.level, util_format_short_name(surf->format), - rtex->desc.macrotile[0] ? "YES" : " NO", - rtex->desc.microtile ? "YES" : " NO", - rtex->desc.stride_in_pixels[0], + 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)); } @@ -695,8 +690,7 @@ void r300_mark_fb_state_dirty(struct r300_context *r300, } if (change == R300_CHANGED_FB_STATE || - change == R300_CHANGED_CBZB_FLAG || - change == R300_CHANGED_ZCLEAR_FLAG) { + change == R300_CHANGED_HYPERZ_FLAG) { r300_mark_atom_dirty(r300, &r300->hyperz_state); } @@ -720,8 +714,8 @@ void r300_mark_fb_state_dirty(struct r300_context *r300, } static void - r300_set_framebuffer_state(struct pipe_context* pipe, - const struct pipe_framebuffer_state* state) +r300_set_framebuffer_state(struct pipe_context* pipe, + const struct pipe_framebuffer_state* state) { struct r300_context* r300 = r300_context(pipe); struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state; @@ -729,7 +723,6 @@ static void boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ); unsigned max_width, max_height, i; uint32_t zbuffer_bpp = 0; - int blocksize; if (r300->screen->caps.is_r500) { max_width = max_height = 4096; @@ -745,6 +738,32 @@ static void return; } + if (old_state->zsbuf && r300->zmask_in_use && !r300->zmask_locked) { + /* There is a zmask in use, what are we gonna do? */ + if (state->zsbuf) { + if (!pipe_surface_equal(old_state->zsbuf, state->zsbuf)) { + /* Decompress the currently bound zbuffer before we bind another one. */ + r300_decompress_zmask(r300); + } + } else { + /* We don't bind another zbuffer, so lock the current one. */ + r300->zmask_locked = TRUE; + pipe_surface_reference(&r300->locked_zbuffer, old_state->zsbuf); + } + } else if (r300->zmask_locked && r300->locked_zbuffer) { + /* We have a locked zbuffer now, what are we gonna do? */ + if (state->zsbuf) { + if (!pipe_surface_equal(r300->locked_zbuffer, state->zsbuf)) { + /* We are binding some other zbuffer, so decompress the locked one, + * it gets unlocked automatically. */ + r300_decompress_zmask_locked_unsafe(r300); + } else { + /* We are binding the locked zbuffer again, so unlock it. */ + r300->zmask_locked = FALSE; + } + } + } + /* If nr_cbufs is changed from zero to non-zero or vice versa... */ if (!!old_state->nr_cbufs != !!state->nr_cbufs) { r300_mark_atom_dirty(r300, &r300->blend_state); @@ -759,14 +778,14 @@ static void util_copy_framebuffer_state(r300->fb_state.state, state); + if (!r300->zmask_locked) { + pipe_surface_reference(&r300->locked_zbuffer, NULL); + } + r300_mark_fb_state_dirty(r300, R300_CHANGED_FB_STATE); - r300->validate_buffers = TRUE; - r300->z_compression = false; - if (state->zsbuf) { - blocksize = util_format_get_blocksize(state->zsbuf->texture->format); - switch (blocksize) { + switch (util_format_get_blocksize(state->zsbuf->texture->format)) { case 2: zbuffer_bpp = 16; break; @@ -774,30 +793,19 @@ static void zbuffer_bpp = 24; break; } + + /* Setup Hyper-Z. */ if (can_hyperz) { struct r300_surface *zs_surf = r300_surface(state->zsbuf); - struct r300_texture *tex; - int compress = r300->screen->caps.is_rv350 ? RV350_Z_COMPRESS_88 : R300_Z_COMPRESS_44; + struct r300_resource *tex = r300_resource(zs_surf->base.texture); int level = zs_surf->base.u.tex.level; - tex = r300_texture(zs_surf->base.texture); - /* work out whether we can support hiz on this buffer */ r300_hiz_alloc_block(r300, zs_surf); - - /* work out whether we can support zmask features on this buffer */ - r300_zmask_alloc_block(r300, zs_surf, compress); - - if (tex->zmask_mem[level]) { - /* compression causes hangs on 16-bit */ - if (zbuffer_bpp == 24) - r300->z_compression = compress; - } + DBG(r300, DBG_HYPERZ, - "hyper-z features: hiz: %d @ %08x z-compression: %d z-fastfill: %d @ %08x\n", tex->hiz_mem[level] ? 1 : 0, - tex->hiz_mem[level] ? tex->hiz_mem[level]->ofs : 0xdeadbeef, - r300->z_compression, tex->zmask_mem[level] ? 1 : 0, - tex->zmask_mem[level] ? tex->zmask_mem[level]->ofs : 0xdeadbeef); + "hyper-z features: hiz: %d @ %08x\n", tex->hiz_mem[level] ? 1 : 0, + tex->hiz_mem[level] ? tex->hiz_mem[level]->ofs : 0xdeadbeef); } /* Polygon offset depends on the zbuffer bit depth. */ @@ -1300,7 +1308,7 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); struct r300_textures_state* state = (struct r300_textures_state*)r300->textures_state.state; - struct r300_texture *texture; + struct r300_resource *texture; unsigned i, real_num_views = 0, view_index = 0; unsigned tex_units = r300->screen->caps.num_tex_units; boolean dirty_tex = FALSE; @@ -1329,8 +1337,8 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, /* Set the texrect factor in the fragment shader. * Needed for RECT and NPOT fallback. */ - texture = r300_texture(views[i]->texture); - if (texture->desc.is_npot) { + texture = r300_resource(views[i]->texture); + if (texture->tex.is_npot) { r300_mark_atom_dirty(r300, &r300->fs_rc_constant_state); } @@ -1350,7 +1358,6 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, state->sampler_view_count = count; r300_mark_atom_dirty(r300, &r300->textures_state); - r300->validate_buffers = TRUE; if (dirty_tex) { r300_mark_atom_dirty(r300, &r300->texture_cache_inval); @@ -1363,7 +1370,7 @@ r300_create_sampler_view(struct pipe_context *pipe, const struct pipe_sampler_view *templ) { struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view); - struct r300_texture *tex = r300_texture(texture); + struct r300_resource *tex = r300_resource(texture); boolean is_r500 = r300_screen(pipe->screen)->caps.is_r500; boolean dxtc_swizzle = r300_screen(pipe->screen)->caps.dxtc_swizzle; @@ -1465,10 +1472,7 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, const struct pipe_vertex_buffer* buffers) { struct r300_context* r300 = r300_context(pipe); - const struct pipe_vertex_buffer *vbo; - unsigned i, max_index = (1 << 24) - 1; - boolean any_user_buffer = FALSE; - boolean any_nonuser_buffer = FALSE; + unsigned i; struct pipe_vertex_buffer dummy_vb = {0}; /* There must be at least one vertex buffer set, otherwise it locks up. */ @@ -1478,90 +1482,20 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, count = 1; } - if (count == r300->vertex_buffer_count && - memcmp(r300->vertex_buffer, buffers, - sizeof(struct pipe_vertex_buffer) * count) == 0) { - return; - } + u_vbuf_mgr_set_vertex_buffers(r300->vbuf_mgr, count, buffers); if (r300->screen->caps.has_tcl) { /* HW TCL. */ - r300->incompatible_vb_layout = FALSE; - - /* Check if the strides and offsets are aligned to the size of DWORD. */ - for (i = 0; i < count; i++) { - if (buffers[i].buffer) { - if (buffers[i].stride % 4 != 0 || - buffers[i].buffer_offset % 4 != 0) { - r300->incompatible_vb_layout = TRUE; - break; - } - } - } - for (i = 0; i < count; i++) { - vbo = &buffers[i]; - - /* Skip NULL buffers */ - if (!vbo->buffer) { - continue; - } - - /* User buffers have no info about maximum index, - * we will have to compute it in draw_vbo. */ - if (r300_is_user_buffer(vbo->buffer)) { - any_user_buffer = TRUE; - continue; - } - any_nonuser_buffer = TRUE; - - /* The stride of zero means we will be fetching only the first - * vertex, so don't care about max_index. */ - if (!vbo->stride) - continue; - - /* Update the maximum index. */ - { - unsigned vbo_max_index = - (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; - max_index = MIN2(max_index, vbo_max_index); + if (buffers[i].buffer && + !r300_resource(buffers[i].buffer)->b.user_ptr) { } } - - r300->any_user_vbs = any_user_buffer; - r300->vertex_buffer_max_index = max_index; r300->vertex_arrays_dirty = TRUE; - if (any_nonuser_buffer) - r300->validate_buffers = TRUE; - if (!any_user_buffer) - r300->upload_vb_validated = FALSE; } else { /* SW TCL. */ draw_set_vertex_buffers(r300->draw, count, buffers); } - - /* Common code. */ - for (i = 0; i < count; i++) { - vbo = &buffers[i]; - - /* Reference our buffer. */ - pipe_resource_reference(&r300->vertex_buffer[i].buffer, vbo->buffer); - if (vbo->buffer && r300_is_user_buffer(vbo->buffer)) { - pipe_resource_reference(&r300->valid_vertex_buffer[i], NULL); - } else { - pipe_resource_reference(&r300->valid_vertex_buffer[i], vbo->buffer); - } - } - for (; i < r300->vertex_buffer_count; i++) { - /* Dereference any old buffers. */ - pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); - pipe_resource_reference(&r300->valid_vertex_buffer[i], NULL); - } - - memcpy(r300->vertex_buffer, buffers, - sizeof(struct pipe_vertex_buffer) * count); - - r300->vertex_buffer_count = count; } static void r300_set_index_buffer(struct pipe_context* pipe, @@ -1570,14 +1504,11 @@ static void r300_set_index_buffer(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); if (ib && ib->buffer) { + assert(ib->offset % ib->index_size == 0); + pipe_resource_reference(&r300->index_buffer.buffer, ib->buffer); memcpy(&r300->index_buffer, ib, sizeof(r300->index_buffer)); - - if (r300->screen->caps.has_tcl && - !r300_is_user_buffer(ib->buffer)) { - r300->validate_buffers = TRUE; - r300->upload_ib_validated = FALSE; - } + r300->index_buffer.offset /= r300->index_buffer.index_size; } else { pipe_resource_reference(&r300->index_buffer.buffer, NULL); @@ -1607,7 +1538,7 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems) * so PSC should just route stuff based on the vertex elements, * and not on attrib information. */ for (i = 0; i < velems->count; i++) { - format = velems->hw_format[i]; + format = velems->velem[i].src_format; type = r300_translate_vertex_data_type(format); if (type == R300_INVALID_FORMAT) { @@ -1639,16 +1570,13 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems) vstream->count = (i >> 1) + 1; } -#define FORMAT_REPLACE(what, withwhat) \ - case PIPE_FORMAT_##what: *format = PIPE_FORMAT_##withwhat; break - static void* r300_create_vertex_elements_state(struct pipe_context* pipe, unsigned count, const struct pipe_vertex_element* attribs) { + struct r300_context *r300 = r300_context(pipe); struct r300_vertex_element_state *velems; unsigned i; - enum pipe_format *format; struct pipe_vertex_element dummy_attrib = {0}; /* R300 Programmable Stream Control (PSC) doesn't support 0 vertex elements. */ @@ -1660,77 +1588,26 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, assert(count <= PIPE_MAX_ATTRIBS); velems = CALLOC_STRUCT(r300_vertex_element_state); - if (velems != NULL) { - velems->count = count; - memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count); - - if (r300_screen(pipe->screen)->caps.has_tcl) { - /* Set the best hw format in case the original format is not - * supported by hw. */ - for (i = 0; i < count; i++) { - velems->hw_format[i] = velems->velem[i].src_format; - format = &velems->hw_format[i]; - - /* This is basically the list of unsupported formats. - * For now we don't care about the alignment, that's going to - * be sorted out after the PSC setup. */ - switch (*format) { - FORMAT_REPLACE(R64_FLOAT, R32_FLOAT); - FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT); - FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT); - FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT); - - FORMAT_REPLACE(R32_UNORM, R32_FLOAT); - FORMAT_REPLACE(R32G32_UNORM, R32G32_FLOAT); - FORMAT_REPLACE(R32G32B32_UNORM, R32G32B32_FLOAT); - FORMAT_REPLACE(R32G32B32A32_UNORM, R32G32B32A32_FLOAT); - - FORMAT_REPLACE(R32_USCALED, R32_FLOAT); - FORMAT_REPLACE(R32G32_USCALED, R32G32_FLOAT); - FORMAT_REPLACE(R32G32B32_USCALED, R32G32B32_FLOAT); - FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT); - - FORMAT_REPLACE(R32_SNORM, R32_FLOAT); - FORMAT_REPLACE(R32G32_SNORM, R32G32_FLOAT); - FORMAT_REPLACE(R32G32B32_SNORM, R32G32B32_FLOAT); - FORMAT_REPLACE(R32G32B32A32_SNORM, R32G32B32A32_FLOAT); - - FORMAT_REPLACE(R32_SSCALED, R32_FLOAT); - FORMAT_REPLACE(R32G32_SSCALED, R32G32_FLOAT); - FORMAT_REPLACE(R32G32B32_SSCALED, R32G32B32_FLOAT); - FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT); - - FORMAT_REPLACE(R32_FIXED, R32_FLOAT); - FORMAT_REPLACE(R32G32_FIXED, R32G32_FLOAT); - FORMAT_REPLACE(R32G32B32_FIXED, R32G32B32_FLOAT); - FORMAT_REPLACE(R32G32B32A32_FIXED, R32G32B32A32_FLOAT); - - default:; - } + if (!velems) + return NULL; - velems->incompatible_layout = - velems->incompatible_layout || - velems->velem[i].src_format != velems->hw_format[i] || - velems->velem[i].src_offset % 4 != 0; - } + velems->count = count; + velems->vmgr_elements = + u_vbuf_mgr_create_vertex_elements(r300->vbuf_mgr, count, attribs, + velems->velem); - /* Now setup PSC. - * The unused components will be replaced by (..., 0, 1). */ - r300_vertex_psc(velems); - - /* Align the formats to the size of DWORD. - * We only care about the blocksizes of the formats since - * swizzles are already set up. - * Also compute the vertex size. */ - for (i = 0; i < count; i++) { - /* This is OK because we check for aligned strides too - * elsewhere. */ - velems->hw_format_size[i] = - align(util_format_get_blocksize(velems->hw_format[i]), 4); - velems->vertex_size_dwords += velems->hw_format_size[i] / 4; - } + if (r300_screen(pipe->screen)->caps.has_tcl) { + /* Setup PSC. + * The unused components will be replaced by (..., 0, 1). */ + r300_vertex_psc(velems); + + for (i = 0; i < count; i++) { + velems->format_size[i] = + align(util_format_get_blocksize(velems->velem[i].src_format), 4); + velems->vertex_size_dwords += velems->format_size[i] / 4; } } + return velems; } @@ -1746,6 +1623,8 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, r300->velems = velems; + u_vbuf_mgr_bind_vertex_elements(r300->vbuf_mgr, state, velems->vmgr_elements); + if (r300->draw) { draw_set_vertex_elements(r300->draw, velems->count, velems->velem); return; @@ -1758,7 +1637,11 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, static void r300_delete_vertex_elements_state(struct pipe_context *pipe, void *state) { - FREE(state); + struct r300_context *r300 = r300_context(pipe); + struct r300_vertex_element_state *velems = state; + + u_vbuf_mgr_destroy_vertex_elements(r300->vbuf_mgr, velems->vmgr_elements); + FREE(state); } static void* r300_create_vs_state(struct pipe_context* pipe, @@ -1845,7 +1728,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, { struct r300_context* r300 = r300_context(pipe); struct r300_constant_buffer *cbuf; - struct r300_buffer *rbuf = r300_buffer(buf); + struct r300_resource *rbuf = r300_resource(buf); uint32_t *mapped; switch (shader) { @@ -1862,8 +1745,8 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, if (buf == NULL || buf->width0 == 0) return; - if (rbuf->user_buffer) - mapped = (uint32_t*)rbuf->user_buffer; + if (rbuf->b.user_ptr) + mapped = (uint32_t*)rbuf->b.user_ptr; else if (rbuf->constant_buffer) mapped = (uint32_t*)rbuf->constant_buffer; else @@ -1947,6 +1830,7 @@ void r300_init_state_functions(struct r300_context* r300) r300->context.set_vertex_buffers = r300_set_vertex_buffers; r300->context.set_index_buffer = r300_set_index_buffer; + r300->context.redefine_user_buffer = u_default_redefine_user_buffer; r300->context.create_vertex_elements_state = r300_create_vertex_elements_state; r300->context.bind_vertex_elements_state = r300_bind_vertex_elements_state; diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 95be7849f8f..003fe9a58cd 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -489,7 +489,8 @@ static void r300_update_rs_block(struct r300_context *r300) for (; i < ATTR_GENERIC_COUNT; i++) { if (fs_inputs->generic[i] != ATTR_UNUSED) { fprintf(stderr, "r300: ERROR: FS input generic %i unassigned, " - "not enough hardware slots.\n", i); + "not enough hardware slots (it's not a bug, do not " + "report it).\n", i); } } @@ -524,7 +525,8 @@ static void r300_update_rs_block(struct r300_context *r300) DBG(r300, DBG_RS, "r300: FS input fog unassigned.\n"); } else { fprintf(stderr, "r300: ERROR: FS input fog unassigned, " - "not enough hardware slots.\n"); + "not enough hardware slots. (it's not a bug, " + "do not report it)\n"); } } } @@ -551,7 +553,8 @@ static void r300_update_rs_block(struct r300_context *r300) } else { if (fs_inputs->wpos != ATTR_UNUSED && tex_count >= 8) { fprintf(stderr, "r300: ERROR: FS input WPOS unassigned, " - "not enough hardware slots.\n"); + "not enough hardware slots. (it's not a bug, do not " + "report it)\n"); } } @@ -674,7 +677,20 @@ static uint32_t r300_get_border_color(enum pipe_format format, case 16: if (desc->nr_channels <= 2) { border_swizzled[0] = border_swizzled[2]; - util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_UNORM, &uc); + if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) { + util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_FLOAT, &uc); + } else { + util_pack_color(border_swizzled, PIPE_FORMAT_R16G16_UNORM, &uc); + } + } else { + util_pack_color(border_swizzled, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); + } + break; + + case 32: + if (desc->nr_channels == 1) { + border_swizzled[0] = border_swizzled[2]; + util_pack_color(border_swizzled, PIPE_FORMAT_R32_FLOAT, &uc); } else { util_pack_color(border_swizzled, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); } @@ -684,6 +700,25 @@ static uint32_t r300_get_border_color(enum pipe_format format, return uc.ui; } +static boolean util_format_is_float(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + unsigned i; + + if (!format) + return FALSE; + + /* Find the first non-void channel. */ + for (i = 0; i < 4; i++) + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) + break; + + if (i == 4) + return FALSE; + + return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE; +} + static void r300_merge_textures_and_samplers(struct r300_context* r300) { struct r300_textures_state *state = @@ -691,7 +726,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) struct r300_texture_sampler_state *texstate; struct r300_sampler_state *sampler; struct r300_sampler_view *view; - struct r300_texture *tex; + struct r300_resource *tex; unsigned min_level, max_level, i, j, size; unsigned count = MIN2(state->sampler_view_count, state->sampler_state_count); @@ -709,7 +744,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) state->tx_enable |= 1 << i; view = state->sampler_views[i]; - tex = r300_texture(view->base.texture); + tex = r300_resource(view->base.texture); sampler = state->sampler_states[i]; texstate = &state->regs[i]; @@ -725,32 +760,37 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) /* determine min/max levels */ max_level = MIN3(sampler->max_lod + view->base.u.tex.first_level, - tex->desc.b.b.last_level, view->base.u.tex.last_level); + tex->b.b.b.last_level, view->base.u.tex.last_level); min_level = MIN2(sampler->min_lod + view->base.u.tex.first_level, max_level); - if (tex->desc.is_npot && min_level > 0) { + if (tex->tex.is_npot && min_level > 0) { /* Even though we do not implement mipmapping for NPOT * textures, we should at least honor the minimum level * which is allowed to be displayed. We do this by setting up - * an i-th mipmap level as the zero level. */ - r300_texture_setup_format_state(r300->screen, &tex->desc, + * the i-th mipmap level as the zero level. */ + unsigned offset = tex->tex_offset + + tex->tex.offset_in_bytes[min_level]; + + r300_texture_setup_format_state(r300->screen, tex, min_level, &texstate->format); - texstate->format.tile_config |= - tex->desc.offset_in_bytes[min_level] & 0xffffffe0; - assert((tex->desc.offset_in_bytes[min_level] & 0x1f) == 0); + texstate->format.tile_config |= offset & 0xffffffe0; + assert((offset & 0x1f) == 0); + } else { + texstate->format.tile_config |= tex->tex_offset & 0xffffffe0; + assert((tex->tex_offset & 0x1f) == 0); } /* Assign a texture cache region. */ texstate->format.format1 |= view->texcache_region; /* Depth textures are kinda special. */ - if (util_format_is_depth_or_stencil(tex->desc.b.b.format)) { + if (util_format_is_depth_or_stencil(tex->b.b.b.format)) { unsigned char depth_swizzle[4]; if (!r300->screen->caps.is_r500 && - util_format_get_blocksizebits(tex->desc.b.b.format) == 32) { + util_format_get_blocksizebits(tex->b.b.b.format) == 32) { /* X24x8 is sampled as Y16X16 on r3xx-r4xx. * The depth here is at the Y component. */ for (j = 0; j < 4; j++) @@ -775,17 +815,17 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) } if (r300->screen->caps.dxtc_swizzle && - util_format_is_compressed(tex->desc.b.b.format)) { + util_format_is_compressed(tex->b.b.b.format)) { texstate->filter1 |= R400_DXTC_SWIZZLE_ENABLE; } /* to emulate 1D textures through 2D ones correctly */ - if (tex->desc.b.b.target == PIPE_TEXTURE_1D) { + if (tex->b.b.b.target == PIPE_TEXTURE_1D) { texstate->filter0 &= ~R300_TX_WRAP_T_MASK; texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); } - if (tex->desc.is_npot) { + if (tex->tex.is_npot) { /* NPOT textures don't support mip filter, unfortunately. * This prevents incorrect rendering. */ texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK; @@ -814,6 +854,32 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) texstate->filter0 |= R300_TX_MAX_MIP_LEVEL(min_level); } + /* Float textures only support nearest and mip-nearest filtering. */ + if (util_format_is_float(tex->b.b.b.format)) { + /* No MAG linear filtering. */ + if ((texstate->filter0 & R300_TX_MAG_FILTER_MASK) == + R300_TX_MAG_FILTER_LINEAR) { + texstate->filter0 &= ~R300_TX_MAG_FILTER_MASK; + texstate->filter0 |= R300_TX_MAG_FILTER_NEAREST; + } + /* No MIN linear filtering. */ + if ((texstate->filter0 & R300_TX_MIN_FILTER_MASK) == + R300_TX_MIN_FILTER_LINEAR) { + texstate->filter0 &= ~R300_TX_MIN_FILTER_MASK; + texstate->filter0 |= R300_TX_MIN_FILTER_NEAREST; + } + /* No mipmap linear filtering. */ + if ((texstate->filter0 & R300_TX_MIN_FILTER_MIP_MASK) == + R300_TX_MIN_FILTER_MIP_LINEAR) { + texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK; + texstate->filter0 |= R300_TX_MIN_FILTER_MIP_NEAREST; + } + /* No anisotropic filtering. */ + texstate->filter0 &= ~R300_TX_MAX_ANISO_MASK; + texstate->filter1 &= ~R500_TX_MAX_ANISO_MASK; + texstate->filter1 &= ~R500_TX_ANISO_HIGH_QUALITY; + } + texstate->filter0 |= i << 28; size += 16; @@ -862,11 +928,35 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) } } -void r300_update_derived_state(struct r300_context* r300) +static void r300_decompress_depth_textures(struct r300_context *r300) { - r300_flush_depth_textures(r300); + struct r300_textures_state *state = + (struct r300_textures_state*)r300->textures_state.state; + struct pipe_resource *tex; + unsigned count = MIN2(state->sampler_view_count, + state->sampler_state_count); + unsigned i; + + if (!r300->zmask_locked || !r300->locked_zbuffer) { + return; + } + for (i = 0; i < count; i++) { + if (state->sampler_views[i] && state->sampler_states[i]) { + tex = state->sampler_views[i]->base.texture; + + if (tex == r300->locked_zbuffer->texture) { + r300_decompress_zmask_locked(r300); + return; + } + } + } +} + +void r300_update_derived_state(struct r300_context* r300) +{ if (r300->textures_state.dirty) { + r300_decompress_depth_textures(r300); r300_merge_textures_and_samplers(r300); } diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 7e501221b1f..06da04c7ad7 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -25,13 +25,9 @@ #define R300_STATE_INLINES_H #include "draw/draw_vertex.h" - #include "pipe/p_format.h" - #include "util/u_format.h" - #include "r300_reg.h" - #include <stdio.h> /* Some maths. These should probably find their way to u_math, if needed. */ @@ -341,24 +337,6 @@ static INLINE uint32_t r500_anisotropy(unsigned max_aniso) R500_TX_ANISO_HIGH_QUALITY; } -/* Non-CSO state. (For now.) */ - -static INLINE uint32_t r300_translate_gb_pipes(int pipe_count) -{ - switch (pipe_count) { - case 1: - return R300_GB_TILE_PIPE_COUNT_RV300; - case 2: - return R300_GB_TILE_PIPE_COUNT_R300; - case 3: - return R300_GB_TILE_PIPE_COUNT_R420_3P; - case 4: - return R300_GB_TILE_PIPE_COUNT_R420; - } - return 0; -} - - /* Translate pipe_formats into PSC vertex types. */ static INLINE uint16_t r300_translate_vertex_data_type(enum pipe_format format) { diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 6fdc504ed54..354144cac79 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -370,14 +370,18 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) switch (format) { /* 8-bit buffers. */ case PIPE_FORMAT_A8_UNORM: + /*case PIPE_FORMAT_A8_SNORM:*/ case PIPE_FORMAT_I8_UNORM: + /*case PIPE_FORMAT_I8_SNORM:*/ case PIPE_FORMAT_L8_UNORM: + /*case PIPE_FORMAT_L8_SNORM:*/ case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_R8_SNORM: return R300_COLOR_FORMAT_I8; /* 16-bit buffers. */ case PIPE_FORMAT_L8A8_UNORM: + /*case PIPE_FORMAT_L8A8_SNORM:*/ case PIPE_FORMAT_R8G8_UNORM: case PIPE_FORMAT_R8G8_SNORM: return R300_COLOR_FORMAT_UV88; @@ -395,13 +399,21 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) /* 32-bit buffers. */ case PIPE_FORMAT_B8G8R8A8_UNORM: + /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/ case PIPE_FORMAT_B8G8R8X8_UNORM: + /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/ case PIPE_FORMAT_A8R8G8B8_UNORM: + /*case PIPE_FORMAT_A8R8G8B8_SNORM:*/ case PIPE_FORMAT_X8R8G8B8_UNORM: + /*case PIPE_FORMAT_X8R8G8B8_SNORM:*/ case PIPE_FORMAT_A8B8G8R8_UNORM: + /*case PIPE_FORMAT_A8B8G8R8_SNORM:*/ + case PIPE_FORMAT_R8G8B8A8_UNORM: case PIPE_FORMAT_R8G8B8A8_SNORM: case PIPE_FORMAT_X8B8G8R8_UNORM: + /*case PIPE_FORMAT_X8B8G8R8_SNORM:*/ case PIPE_FORMAT_R8G8B8X8_UNORM: + /*case PIPE_FORMAT_R8G8B8X8_SNORM:*/ case PIPE_FORMAT_R8SG8SB8UX8U_NORM: return R300_COLOR_FORMAT_ARGB8888; @@ -506,9 +518,12 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) /* 8-bit outputs, one channel. * COLORFORMAT_I8 stores the C2 component. */ case PIPE_FORMAT_A8_UNORM: + /*case PIPE_FORMAT_A8_SNORM:*/ return modifier | R300_C2_SEL_A; case PIPE_FORMAT_I8_UNORM: + /*case PIPE_FORMAT_I8_SNORM:*/ case PIPE_FORMAT_L8_UNORM: + /*case PIPE_FORMAT_L8_SNORM:*/ case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_R8_SNORM: return modifier | R300_C2_SEL_R; @@ -516,6 +531,7 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) /* 16-bit outputs, two channels. * COLORFORMAT_UV88 stores C2 and C0. */ case PIPE_FORMAT_L8A8_UNORM: + /*case PIPE_FORMAT_L8A8_SNORM:*/ return modifier | R300_C0_SEL_A | R300_C2_SEL_R; case PIPE_FORMAT_R8G8_UNORM: case PIPE_FORMAT_R8G8_SNORM: @@ -528,7 +544,9 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) case PIPE_FORMAT_B4G4R4A4_UNORM: case PIPE_FORMAT_B4G4R4X4_UNORM: case PIPE_FORMAT_B8G8R8A8_UNORM: + /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/ case PIPE_FORMAT_B8G8R8X8_UNORM: + /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/ case PIPE_FORMAT_B10G10R10A2_UNORM: return modifier | R300_C0_SEL_B | R300_C1_SEL_G | @@ -536,20 +554,26 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) /* ARGB outputs. */ case PIPE_FORMAT_A8R8G8B8_UNORM: + /*case PIPE_FORMAT_A8R8G8B8_SNORM:*/ case PIPE_FORMAT_X8R8G8B8_UNORM: + /*case PIPE_FORMAT_X8R8G8B8_SNORM:*/ return modifier | R300_C0_SEL_A | R300_C1_SEL_R | R300_C2_SEL_G | R300_C3_SEL_B; /* ABGR outputs. */ case PIPE_FORMAT_A8B8G8R8_UNORM: + /*case PIPE_FORMAT_A8B8G8R8_SNORM:*/ case PIPE_FORMAT_X8B8G8R8_UNORM: + /*case PIPE_FORMAT_X8B8G8R8_SNORM:*/ return modifier | R300_C0_SEL_A | R300_C1_SEL_B | R300_C2_SEL_G | R300_C3_SEL_R; /* RGBA outputs. */ case PIPE_FORMAT_R8G8B8X8_UNORM: + /*case PIPE_FORMAT_R8G8B8X8_SNORM:*/ + case PIPE_FORMAT_R8G8B8A8_UNORM: case PIPE_FORMAT_R8G8B8A8_SNORM: case PIPE_FORMAT_R8SG8SB8UX8U_NORM: case PIPE_FORMAT_R10G10B10A2_UNORM: @@ -585,11 +609,12 @@ boolean r300_is_sampler_format_supported(enum pipe_format format) } void r300_texture_setup_format_state(struct r300_screen *screen, - struct r300_texture_desc *desc, + struct r300_resource *tex, unsigned level, struct r300_texture_format_state *out) { - struct pipe_resource *pt = &desc->b.b; + struct pipe_resource *pt = &tex->b.b.b; + struct r300_texture_desc *desc = &tex->tex; boolean is_r500 = screen->caps.is_r500; /* Mask out all the fields we change. */ @@ -632,163 +657,152 @@ void r300_texture_setup_format_state(struct r300_screen *screen, R300_TXO_MICRO_TILE(desc->microtile); } -static void r300_texture_setup_fb_state(struct r300_screen* screen, - struct r300_texture* tex) +static void r300_texture_setup_fb_state(struct r300_surface *surf) { - unsigned i; + struct r300_resource *tex = r300_resource(surf->base.texture); + unsigned level = surf->base.u.tex.level; /* Set framebuffer state. */ - if (util_format_is_depth_or_stencil(tex->desc.b.b.format)) { - for (i = 0; i <= tex->desc.b.b.last_level; i++) { - tex->fb_state.pitch[i] = - tex->desc.stride_in_pixels[i] | - R300_DEPTHMACROTILE(tex->desc.macrotile[i]) | - R300_DEPTHMICROTILE(tex->desc.microtile); - } - tex->fb_state.format = r300_translate_zsformat(tex->desc.b.b.format); + if (util_format_is_depth_or_stencil(surf->base.format)) { + surf->pitch = + tex->tex.stride_in_pixels[level] | + R300_DEPTHMACROTILE(tex->tex.macrotile[level]) | + R300_DEPTHMICROTILE(tex->tex.microtile); + surf->format = r300_translate_zsformat(surf->base.format); } else { - for (i = 0; i <= tex->desc.b.b.last_level; i++) { - tex->fb_state.pitch[i] = - tex->desc.stride_in_pixels[i] | - r300_translate_colorformat(tex->desc.b.b.format) | - R300_COLOR_TILE(tex->desc.macrotile[i]) | - R300_COLOR_MICROTILE(tex->desc.microtile); - } - tex->fb_state.format = r300_translate_out_fmt(tex->desc.b.b.format); + surf->pitch = + tex->tex.stride_in_pixels[level] | + r300_translate_colorformat(surf->base.format) | + R300_COLOR_TILE(tex->tex.macrotile[level]) | + R300_COLOR_MICROTILE(tex->tex.microtile); + surf->format = r300_translate_out_fmt(surf->base.format); } } -void r300_texture_reinterpret_format(struct pipe_screen *screen, +boolean r300_resource_set_properties(struct pipe_screen *screen, struct pipe_resource *tex, - enum pipe_format new_format) + unsigned offset, + const struct pipe_resource *new_properties) { - struct r300_screen *r300screen = r300_screen(screen); + struct r300_screen *rscreen = r300_screen(screen); + struct r300_resource *res = r300_resource(tex); - SCREEN_DBG(r300screen, DBG_TEX, - "r300: texture_reinterpret_format: %s -> %s\n", + SCREEN_DBG(rscreen, DBG_TEX, + "r300: texture_set_properties: %s -> %s\n", util_format_short_name(tex->format), - util_format_short_name(new_format)); - - tex->format = new_format; + util_format_short_name(new_properties->format)); - r300_texture_setup_fb_state(r300_screen(screen), r300_texture(tex)); -} - -static unsigned r300_texture_is_referenced(struct pipe_context *context, - struct pipe_resource *texture, - unsigned level, int layer) -{ - struct r300_context *r300 = r300_context(context); - struct r300_texture *rtex = (struct r300_texture *)texture; - - if (r300->rws->cs_is_buffer_referenced(r300->cs, - rtex->cs_buffer, R300_REF_CS)) - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; + if (!r300_texture_desc_init(rscreen, res, new_properties)) { + fprintf(stderr, "r300: ERROR: Cannot set texture properties.\n"); + return FALSE; + } + res->tex_offset = offset; + r300_texture_setup_format_state(rscreen, res, 0, &res->tx_format); - return PIPE_UNREFERENCED; + return TRUE; } static void r300_texture_destroy(struct pipe_screen *screen, struct pipe_resource* texture) { - struct r300_texture* tex = (struct r300_texture*)texture; - struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys; + struct r300_resource* tex = (struct r300_resource*)texture; int i; - rws->buffer_reference(rws, &tex->buffer, NULL); + r300_winsys_bo_reference(&tex->buf, NULL); for (i = 0; i < R300_MAX_TEXTURE_LEVELS; i++) { if (tex->hiz_mem[i]) u_mmFreeMem(tex->hiz_mem[i]); - if (tex->zmask_mem[i]) - u_mmFreeMem(tex->zmask_mem[i]); } FREE(tex); } -static boolean r300_texture_get_handle(struct pipe_screen* screen, - struct pipe_resource *texture, - struct winsys_handle *whandle) +boolean r300_resource_get_handle(struct pipe_screen* screen, + struct pipe_resource *texture, + struct winsys_handle *whandle) { struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; - struct r300_texture* tex = (struct r300_texture*)texture; + struct r300_resource* tex = (struct r300_resource*)texture; if (!tex) { return FALSE; } - return rws->buffer_get_handle(rws, tex->buffer, - tex->desc.stride_in_bytes[0], whandle); + return rws->buffer_get_handle(tex->buf, + tex->tex.stride_in_bytes[0], whandle); } -struct u_resource_vtbl r300_texture_vtbl = +static const struct u_resource_vtbl r300_texture_vtbl = { - r300_texture_get_handle, /* get_handle */ - r300_texture_destroy, /* resource_destroy */ - r300_texture_is_referenced, /* is_resource_referenced */ - r300_texture_get_transfer, /* get_transfer */ - r300_texture_transfer_destroy, /* transfer_destroy */ - r300_texture_transfer_map, /* transfer_map */ - u_default_transfer_flush_region, /* transfer_flush_region */ - r300_texture_transfer_unmap, /* transfer_unmap */ - u_default_transfer_inline_write /* transfer_inline_write */ + NULL, /* get_handle */ + r300_texture_destroy, /* resource_destroy */ + NULL, /* is_resource_referenced */ + r300_texture_get_transfer, /* get_transfer */ + r300_texture_transfer_destroy, /* transfer_destroy */ + r300_texture_transfer_map, /* transfer_map */ + NULL, /* transfer_flush_region */ + r300_texture_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ }; /* The common texture constructor. */ -static struct r300_texture* +static struct r300_resource* r300_texture_create_object(struct r300_screen *rscreen, const struct pipe_resource *base, enum r300_buffer_tiling microtile, enum r300_buffer_tiling macrotile, unsigned stride_in_bytes_override, unsigned max_buffer_size, - struct r300_winsys_buffer *buffer) + struct r300_winsys_bo *buffer) { struct r300_winsys_screen *rws = rscreen->rws; - struct r300_texture *tex = CALLOC_STRUCT(r300_texture); + struct r300_resource *tex = CALLOC_STRUCT(r300_resource); if (!tex) { if (buffer) - rws->buffer_reference(rws, &buffer, NULL); + r300_winsys_bo_reference(&buffer, NULL); return NULL; } - /* Initialize the descriptor. */ - if (!r300_texture_desc_init(rscreen, &tex->desc, base, - microtile, macrotile, - stride_in_bytes_override, - max_buffer_size)) { + pipe_reference_init(&tex->b.b.b.reference, 1); + tex->b.b.b.screen = &rscreen->screen; + tex->b.b.b.usage = base->usage; + tex->b.b.b.bind = base->bind; + tex->b.b.b.flags = base->flags; + tex->b.b.vtbl = &r300_texture_vtbl; + tex->tex.microtile = microtile; + tex->tex.macrotile[0] = macrotile; + tex->tex.stride_in_bytes_override = stride_in_bytes_override; + tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ? + R300_DOMAIN_GTT : + R300_DOMAIN_VRAM | R300_DOMAIN_GTT; + tex->buf_size = max_buffer_size; + + if (!r300_resource_set_properties(&rscreen->screen, &tex->b.b.b, 0, base)) { if (buffer) - rws->buffer_reference(rws, &buffer, NULL); + r300_winsys_bo_reference(&buffer, NULL); FREE(tex); return NULL; } - /* Initialize the hardware state. */ - r300_texture_setup_format_state(rscreen, &tex->desc, 0, &tex->tx_format); - r300_texture_setup_fb_state(rscreen, tex); - - tex->desc.b.vtbl = &r300_texture_vtbl; - pipe_reference_init(&tex->desc.b.b.reference, 1); - tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ? - R300_DOMAIN_GTT : - R300_DOMAIN_VRAM | R300_DOMAIN_GTT; - tex->buffer = buffer; /* Create the backing buffer if needed. */ - if (!tex->buffer) { - tex->buffer = rws->buffer_create(rws, tex->desc.size_in_bytes, 2048, + if (!buffer) { + tex->buf_size = tex->tex.size_in_bytes; + tex->buf = rws->buffer_create(rws, tex->tex.size_in_bytes, 2048, base->bind, base->usage, tex->domain); - if (!tex->buffer) { + if (!tex->buf) { FREE(tex); return NULL; } + } else { + tex->buf = buffer; } - tex->cs_buffer = rws->buffer_get_cs_handle(rws, tex->buffer); + tex->cs_buf = rws->buffer_get_cs_handle(tex->buf); - rws->buffer_set_tiling(rws, tex->buffer, - tex->desc.microtile, tex->desc.macrotile[0], - tex->desc.stride_in_bytes[0]); + rws->buffer_set_tiling(tex->buf, NULL, + tex->tex.microtile, tex->tex.macrotile[0], + tex->tex.stride_in_bytes[0]); return tex; } @@ -820,7 +834,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, { struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys; struct r300_screen *rscreen = r300_screen(screen); - struct r300_winsys_buffer *buffer; + struct r300_winsys_bo *buffer; enum r300_buffer_tiling microtile, macrotile; unsigned stride, size; @@ -836,7 +850,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, if (!buffer) return NULL; - rws->buffer_get_tiling(rws, buffer, µtile, ¯otile); + rws->buffer_get_tiling(buffer, µtile, ¯otile); /* Enforce a microtiled zbuffer. */ if (util_format_is_depth_or_stencil(base->format) && @@ -847,7 +861,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, break; case 2: - if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) + if (rws->get_value(rws, R300_VID_DRM_2_1_0)) microtile = R300_BUFFER_SQUARETILED; break; } @@ -864,7 +878,7 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx, struct pipe_resource* texture, const struct pipe_surface *surf_tmpl) { - struct r300_texture* tex = r300_texture(texture); + struct r300_resource* tex = r300_resource(texture); struct r300_surface* surface = CALLOC_STRUCT(r300_surface); unsigned level = surf_tmpl->u.tex.level; @@ -884,28 +898,27 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx, surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; surface->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; - surface->buffer = tex->buffer; - surface->cs_buffer = tex->cs_buffer; + surface->buf = tex->buf; + surface->cs_buf = tex->cs_buf; /* Prefer VRAM if there are multiple domains to choose from. */ surface->domain = tex->domain; if (surface->domain & R300_DOMAIN_VRAM) surface->domain &= ~R300_DOMAIN_GTT; - surface->offset = r300_texture_get_offset(&tex->desc, level, + surface->offset = r300_texture_get_offset(tex, level, surf_tmpl->u.tex.first_layer); - surface->pitch = tex->fb_state.pitch[level]; - surface->format = tex->fb_state.format; + r300_texture_setup_fb_state(surface); /* Parameters for the CBZB clear. */ - surface->cbzb_allowed = tex->desc.cbzb_allowed[level]; + surface->cbzb_allowed = tex->tex.cbzb_allowed[level]; 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->desc.b.b.format, - tex->desc.b.b.nr_samples, - tex->desc.microtile, - tex->desc.macrotile[level], + tile_height = r300_get_pixel_alignment(tex->b.b.b.format, + tex->b.b.b.nr_samples, + tex->tex.microtile, + tex->tex.macrotile[level], DIM_HEIGHT, 0); surface->cbzb_height = align((surface->base.height + 1) / 2, @@ -914,7 +927,7 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx, /* Offset must be aligned to 2K and must point at the beginning * of a scanline. */ offset = surface->offset + - tex->desc.stride_in_bytes[level] * surface->cbzb_height; + tex->tex.stride_in_bytes[level] * surface->cbzb_height; surface->cbzb_midpoint_offset = offset & ~2047; surface->cbzb_pitch = surface->pitch & 0x1ffffc; @@ -929,8 +942,8 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx, surface->cbzb_allowed ? "YES" : " NO", surface->cbzb_width, surface->cbzb_height, offset & 2047, - tex->desc.microtile ? "YES" : " NO", - tex->desc.macrotile[level] ? "YES" : " NO"); + tex->tex.microtile ? "YES" : " NO", + tex->tex.macrotile[level] ? "YES" : " NO"); } return &surface->base; diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index 0ab22f747e4..158a387478f 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -32,7 +32,7 @@ struct pipe_resource; struct winsys_handle; struct r300_texture_format_state; struct r300_texture_desc; -struct r300_texture; +struct r300_resource; struct r300_screen; unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, @@ -46,9 +46,10 @@ uint32_t r300_translate_texformat(enum pipe_format format, uint32_t r500_tx_format_msb_bit(enum pipe_format format); -void r300_texture_reinterpret_format(struct pipe_screen *screen, +boolean r300_resource_set_properties(struct pipe_screen *screen, struct pipe_resource *tex, - enum pipe_format new_format); + unsigned offset, + const struct pipe_resource *new_properties); boolean r300_is_colorbuffer_format_supported(enum pipe_format format); @@ -57,10 +58,14 @@ boolean r300_is_zs_format_supported(enum pipe_format format); boolean r300_is_sampler_format_supported(enum pipe_format format); void r300_texture_setup_format_state(struct r300_screen *screen, - struct r300_texture_desc *desc, + struct r300_resource *tex, unsigned level, struct r300_texture_format_state *out); +boolean r300_resource_get_handle(struct pipe_screen* screen, + struct pipe_resource *texture, + struct winsys_handle *whandle); + struct pipe_resource* r300_texture_from_handle(struct pipe_screen* screen, const struct pipe_resource* base, diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c index 7b1739142d4..2cfeec7d751 100644 --- a/src/gallium/drivers/r300/r300_texture_desc.c +++ b/src/gallium/drivers/r300/r300_texture_desc.c @@ -90,19 +90,19 @@ unsigned r300_get_pixel_alignment(enum pipe_format format, } /* Return true if macrotiling should be enabled on the miplevel. */ -static boolean r300_texture_macro_switch(struct r300_texture_desc *desc, +static boolean r300_texture_macro_switch(struct r300_resource *tex, unsigned level, boolean rv350_mode, enum r300_dim dim) { unsigned tile, texdim; - tile = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples, - desc->microtile, R300_BUFFER_TILED, dim, 0); + tile = r300_get_pixel_alignment(tex->b.b.b.format, tex->b.b.b.nr_samples, + tex->tex.microtile, R300_BUFFER_TILED, dim, 0); if (dim == DIM_WIDTH) { - texdim = u_minify(desc->width0, level); + texdim = u_minify(tex->tex.width0, level); } else { - texdim = u_minify(desc->height0, level); + texdim = u_minify(tex->tex.height0, level); } /* See TX_FILTER1_n.MACRO_SWITCH. */ @@ -118,7 +118,7 @@ static boolean r300_texture_macro_switch(struct r300_texture_desc *desc, * at the given level. */ static unsigned r300_texture_get_stride(struct r300_screen *screen, - struct r300_texture_desc *desc, + struct r300_resource *tex, unsigned level) { unsigned tile_width, width, stride; @@ -126,62 +126,62 @@ static unsigned r300_texture_get_stride(struct r300_screen *screen, screen->caps.family == CHIP_FAMILY_RS690 || screen->caps.family == CHIP_FAMILY_RS740); - if (desc->stride_in_bytes_override) - return desc->stride_in_bytes_override; + if (tex->tex.stride_in_bytes_override) + return tex->tex.stride_in_bytes_override; /* Check the level. */ - if (level > desc->b.b.last_level) { + if (level > tex->b.b.b.last_level) { SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", - __FUNCTION__, level, desc->b.b.last_level); + __FUNCTION__, level, tex->b.b.b.last_level); return 0; } - width = u_minify(desc->width0, level); + width = u_minify(tex->tex.width0, level); - if (util_format_is_plain(desc->b.b.format)) { - tile_width = r300_get_pixel_alignment(desc->b.b.format, - desc->b.b.nr_samples, - desc->microtile, - desc->macrotile[level], + if (util_format_is_plain(tex->b.b.b.format)) { + tile_width = r300_get_pixel_alignment(tex->b.b.b.format, + tex->b.b.b.nr_samples, + tex->tex.microtile, + tex->tex.macrotile[level], DIM_WIDTH, is_rs690); width = align(width, tile_width); - stride = util_format_get_stride(desc->b.b.format, width); + stride = util_format_get_stride(tex->b.b.b.format, width); /* The alignment to 32 bytes is sort of implied by the layout... */ return stride; } else { - return align(util_format_get_stride(desc->b.b.format, width), is_rs690 ? 64 : 32); + return align(util_format_get_stride(tex->b.b.b.format, width), is_rs690 ? 64 : 32); } } -static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc, +static unsigned r300_texture_get_nblocksy(struct r300_resource *tex, unsigned level, boolean *out_aligned_for_cbzb) { unsigned height, tile_height; - height = u_minify(desc->height0, level); + height = u_minify(tex->tex.height0, level); - if (util_format_is_plain(desc->b.b.format)) { - tile_height = r300_get_pixel_alignment(desc->b.b.format, - desc->b.b.nr_samples, - desc->microtile, - desc->macrotile[level], + /* Mipmapped and 3D textures must have their height aligned to POT. */ + if ((tex->b.b.b.target != PIPE_TEXTURE_1D && + tex->b.b.b.target != PIPE_TEXTURE_2D && + tex->b.b.b.target != PIPE_TEXTURE_RECT) || + tex->b.b.b.last_level != 0) { + height = util_next_power_of_two(height); + } + + if (util_format_is_plain(tex->b.b.b.format)) { + tile_height = r300_get_pixel_alignment(tex->b.b.b.format, + tex->b.b.b.nr_samples, + tex->tex.microtile, + tex->tex.macrotile[level], DIM_HEIGHT, 0); height = align(height, tile_height); - /* This is needed for the kernel checker, unfortunately. */ - if ((desc->b.b.target != PIPE_TEXTURE_1D && - desc->b.b.target != PIPE_TEXTURE_2D && - desc->b.b.target != PIPE_TEXTURE_RECT) || - desc->b.b.last_level != 0) { - height = util_next_power_of_two(height); - } - /* See if the CBZB clear can be used on the buffer, * taking the texture size into account. */ if (out_aligned_for_cbzb) { - if (desc->macrotile[level]) { + if (tex->tex.macrotile[level]) { /* When clearing, the layer (width*height) is horizontally split * into two, and the upper and lower halves are cleared by the CB * and ZB units, respectively. Therefore, the number of macrotiles @@ -189,10 +189,10 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc, /* Align the height so that there is an even number of macrotiles. * Do so for 3 or more macrotiles in the Y direction. */ - if (level == 0 && desc->b.b.last_level == 0 && - (desc->b.b.target == PIPE_TEXTURE_1D || - desc->b.b.target == PIPE_TEXTURE_2D || - desc->b.b.target == PIPE_TEXTURE_RECT) && + if (level == 0 && tex->b.b.b.last_level == 0 && + (tex->b.b.b.target == PIPE_TEXTURE_1D || + tex->b.b.b.target == PIPE_TEXTURE_2D || + tex->b.b.b.target == PIPE_TEXTURE_RECT) && height >= tile_height * 3) { height = align(height, tile_height * 2); } @@ -204,11 +204,11 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc, } } - return util_format_get_nblocksy(desc->b.b.format, height); + return util_format_get_nblocksy(tex->b.b.b.format, height); } static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen, - struct r300_texture_desc *desc) + struct r300_resource *tex) { /* The kernels <= 2.6.34-rc4 compute the size of mipmapped 3D textures * incorrectly. This is a workaround to prevent CS from being rejected. */ @@ -216,17 +216,17 @@ static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen, unsigned i, size; if (!screen->rws->get_value(screen->rws, R300_VID_DRM_2_3_0) && - desc->b.b.target == PIPE_TEXTURE_3D && - desc->b.b.last_level > 0) { + tex->b.b.b.target == PIPE_TEXTURE_3D && + tex->b.b.b.last_level > 0) { size = 0; - for (i = 0; i <= desc->b.b.last_level; i++) { - size += desc->stride_in_bytes[i] * - r300_texture_get_nblocksy(desc, i, FALSE); + for (i = 0; i <= tex->b.b.b.last_level; i++) { + size += tex->tex.stride_in_bytes[i] * + r300_texture_get_nblocksy(tex, i, FALSE); } - size *= desc->depth0; - desc->size_in_bytes = size; + size *= tex->tex.depth0; + tex->tex.size_in_bytes = size; } } @@ -239,15 +239,15 @@ static unsigned stride_to_width(enum pipe_format format, } static void r300_setup_miptree(struct r300_screen *screen, - struct r300_texture_desc *desc, + struct r300_resource *tex, boolean align_for_cbzb) { - struct pipe_resource *base = &desc->b.b; + struct pipe_resource *base = &tex->b.b.b; unsigned stride, size, layer_size, nblocksy, i; boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; boolean aligned_for_cbzb; - desc->size_in_bytes = 0; + tex->tex.size_in_bytes = 0; SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Making miptree for texture, format %s\n", @@ -255,21 +255,21 @@ static void r300_setup_miptree(struct r300_screen *screen, for (i = 0; i <= base->last_level; i++) { /* Let's see if this miplevel can be macrotiled. */ - desc->macrotile[i] = - (desc->macrotile[0] == R300_BUFFER_TILED && - r300_texture_macro_switch(desc, i, rv350_mode, DIM_WIDTH) && - r300_texture_macro_switch(desc, i, rv350_mode, DIM_HEIGHT)) ? + tex->tex.macrotile[i] = + (tex->tex.macrotile[0] == R300_BUFFER_TILED && + r300_texture_macro_switch(tex, i, rv350_mode, DIM_WIDTH) && + r300_texture_macro_switch(tex, i, rv350_mode, DIM_HEIGHT)) ? R300_BUFFER_TILED : R300_BUFFER_LINEAR; - stride = r300_texture_get_stride(screen, desc, i); + stride = r300_texture_get_stride(screen, tex, i); /* Compute the number of blocks in Y, see if the CBZB clear can be * used on the texture. */ aligned_for_cbzb = FALSE; - if (align_for_cbzb && desc->cbzb_allowed[i]) - nblocksy = r300_texture_get_nblocksy(desc, i, &aligned_for_cbzb); + if (align_for_cbzb && tex->tex.cbzb_allowed[i]) + nblocksy = r300_texture_get_nblocksy(tex, i, &aligned_for_cbzb); else - nblocksy = r300_texture_get_nblocksy(desc, i, NULL); + nblocksy = r300_texture_get_nblocksy(tex, i, NULL); layer_size = stride * nblocksy; @@ -280,75 +280,136 @@ static void r300_setup_miptree(struct r300_screen *screen, if (base->target == PIPE_TEXTURE_CUBE) size = layer_size * 6; else - size = layer_size * u_minify(desc->depth0, i); + size = layer_size * u_minify(tex->tex.depth0, i); - desc->offset_in_bytes[i] = desc->size_in_bytes; - desc->size_in_bytes = desc->offset_in_bytes[i] + size; - desc->layer_size_in_bytes[i] = layer_size; - desc->stride_in_bytes[i] = stride; - desc->stride_in_pixels[i] = stride_to_width(desc->b.b.format, stride); - desc->cbzb_allowed[i] = desc->cbzb_allowed[i] && aligned_for_cbzb; + tex->tex.offset_in_bytes[i] = tex->tex.size_in_bytes; + 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 " "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n", - i, u_minify(desc->width0, i), u_minify(desc->height0, i), - u_minify(desc->depth0, i), stride, desc->size_in_bytes, - desc->macrotile[i] ? "TRUE" : "FALSE"); + i, u_minify(tex->tex.width0, i), u_minify(tex->tex.height0, i), + u_minify(tex->tex.depth0, i), stride, tex->tex.size_in_bytes, + tex->tex.macrotile[i] ? "TRUE" : "FALSE"); } } -static void r300_setup_flags(struct r300_texture_desc *desc) +static void r300_setup_flags(struct r300_resource *tex) { - desc->uses_stride_addressing = - !util_is_power_of_two(desc->b.b.width0) || - (desc->stride_in_bytes_override && - stride_to_width(desc->b.b.format, - desc->stride_in_bytes_override) != desc->b.b.width0); - - desc->is_npot = - desc->uses_stride_addressing || - !util_is_power_of_two(desc->b.b.height0) || - !util_is_power_of_two(desc->b.b.depth0); + 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, + tex->tex.stride_in_bytes_override) != tex->b.b.b.width0); + + tex->tex.is_npot = + tex->tex.uses_stride_addressing || + !util_is_power_of_two(tex->b.b.b.height0) || + !util_is_power_of_two(tex->b.b.b.depth0); } static void r300_setup_cbzb_flags(struct r300_screen *rscreen, - struct r300_texture_desc *desc) + struct r300_resource *tex) { unsigned i, bpp; boolean first_level_valid; - bpp = util_format_get_blocksizebits(desc->b.b.format); + bpp = util_format_get_blocksizebits(tex->b.b.b.format); /* 1) The texture must be point-sampled, * 2) The depth must be 16 or 32 bits. * 3) If the midpoint ZB offset is not aligned to 2048, it returns garbage * with certain texture sizes. Macrotiling ensures the alignment. */ - first_level_valid = desc->b.b.nr_samples <= 1 && + first_level_valid = tex->b.b.b.nr_samples <= 1 && (bpp == 16 || bpp == 32) && - desc->macrotile[0]; + tex->tex.macrotile[0]; if (SCREEN_DBG_ON(rscreen, DBG_NO_CBZB)) first_level_valid = FALSE; - for (i = 0; i <= desc->b.b.last_level; i++) - desc->cbzb_allowed[i] = first_level_valid && desc->macrotile[i]; + for (i = 0; i <= tex->b.b.b.last_level; i++) + tex->tex.cbzb_allowed[i] = first_level_valid && tex->tex.macrotile[i]; +} + +#define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y)) + +static void r300_setup_zmask_flags(struct r300_screen *screen, + struct r300_resource *tex) +{ + /* The tile size of 1 DWORD is: + * + * GPU Pipes 4x4 mode 8x8 mode + * ------------------------------------------ + * R580 4P/1Z 32x32 64x64 + * RV570 3P/1Z 48x16 96x32 + * RV530 1P/2Z 32x16 64x32 + * 1P/1Z 16x16 32x32 + */ + static unsigned num_blocks_x_per_dw[4] = {4, 8, 12, 8}; + static unsigned num_blocks_y_per_dw[4] = {4, 4, 4, 8}; + + if (util_format_is_depth_or_stencil(tex->b.b.b.format) && + util_format_get_blocksizebits(tex->b.b.b.format) == 32 && + tex->tex.microtile) { + unsigned i, pipes; + + if (screen->caps.family == CHIP_FAMILY_RV530) { + pipes = screen->caps.num_z_pipes; + } else { + pipes = screen->caps.num_frag_pipes; + } + + for (i = 0; i <= tex->b.b.b.last_level; i++) { + unsigned numdw, compsize; + + /* The 8x8 compression mode needs macrotiling. */ + compsize = screen->caps.z_compress == R300_ZCOMP_8X8 && + tex->tex.macrotile[i] && + tex->b.b.b.nr_samples <= 1 ? 8 : 4; + + /* Get the zbuffer size (with the aligned width and height). */ + numdw = align(tex->tex.stride_in_pixels[i], + num_blocks_x_per_dw[pipes-1] * compsize) * + align(u_minify(tex->b.b.b.height0, i), + num_blocks_y_per_dw[pipes-1] * compsize); + + /* Convert pixels -> dwords. */ + numdw = ALIGN_DIVUP(numdw, num_blocks_x_per_dw[pipes-1] * compsize * + num_blocks_y_per_dw[pipes-1] * compsize); + + /* Check that we have enough ZMASK memory. */ + if (numdw <= screen->caps.zmask_ram * pipes) { + tex->tex.zmask_dwords[i] = numdw; + tex->tex.zcomp8x8[i] = compsize == 8; + } else { + tex->tex.zmask_dwords[i] = 0; + tex->tex.zcomp8x8[i] = FALSE; + } + } + } } static void r300_setup_tiling(struct r300_screen *screen, - struct r300_texture_desc *desc) + struct r300_resource *tex) { struct r300_winsys_screen *rws = screen->rws; - enum pipe_format format = desc->b.b.format; + enum pipe_format format = tex->b.b.b.format; boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; boolean is_zb = util_format_is_depth_or_stencil(format); boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING); + tex->tex.microtile = R300_BUFFER_LINEAR; + tex->tex.macrotile[0] = R300_BUFFER_LINEAR; + if (!util_format_is_plain(format)) { return; } /* If height == 1, disable microtiling except for zbuffer. */ - if (!is_zb && (desc->b.b.height0 == 1 || dbg_no_tiling)) { + if (!is_zb && (tex->b.b.b.height0 == 1 || dbg_no_tiling)) { return; } @@ -357,12 +418,12 @@ static void r300_setup_tiling(struct r300_screen *screen, case 1: case 4: case 8: - desc->microtile = R300_BUFFER_TILED; + tex->tex.microtile = R300_BUFFER_TILED; break; case 2: - if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) { - desc->microtile = R300_BUFFER_SQUARETILED; + if (rws->get_value(rws, R300_VID_DRM_2_1_0)) { + tex->tex.microtile = R300_BUFFER_SQUARETILED; } break; } @@ -372,104 +433,100 @@ static void r300_setup_tiling(struct r300_screen *screen, } /* Set macrotiling. */ - if (r300_texture_macro_switch(desc, 0, rv350_mode, DIM_WIDTH) && - r300_texture_macro_switch(desc, 0, rv350_mode, DIM_HEIGHT)) { - desc->macrotile[0] = R300_BUFFER_TILED; + if (r300_texture_macro_switch(tex, 0, rv350_mode, DIM_WIDTH) && + r300_texture_macro_switch(tex, 0, rv350_mode, DIM_HEIGHT)) { + tex->tex.macrotile[0] = R300_BUFFER_TILED; } } -static void r300_tex_print_info(struct r300_screen *rscreen, - struct r300_texture_desc *desc, +static void r300_tex_print_info(struct r300_resource *tex, const char *func) { fprintf(stderr, "r300: %s: Macro: %s, Micro: %s, Pitch: %i, Dim: %ix%ix%i, " "LastLevel: %i, Size: %i, Format: %s\n", func, - desc->macrotile[0] ? "YES" : " NO", - desc->microtile ? "YES" : " NO", - desc->stride_in_pixels[0], - desc->b.b.width0, desc->b.b.height0, desc->b.b.depth0, - desc->b.b.last_level, desc->size_in_bytes, - util_format_short_name(desc->b.b.format)); + tex->tex.macrotile[0] ? "YES" : " NO", + tex->tex.microtile ? "YES" : " NO", + tex->tex.stride_in_pixels[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)); } boolean r300_texture_desc_init(struct r300_screen *rscreen, - struct r300_texture_desc *desc, - const struct pipe_resource *base, - enum r300_buffer_tiling microtile, - enum r300_buffer_tiling macrotile, - unsigned stride_in_bytes_override, - unsigned max_buffer_size) + struct r300_resource *tex, + const struct pipe_resource *base) { - desc->b.b = *base; - desc->b.b.screen = &rscreen->screen; - desc->stride_in_bytes_override = stride_in_bytes_override; - desc->width0 = base->width0; - desc->height0 = base->height0; - desc->depth0 = base->depth0; - - r300_setup_flags(desc); + tex->b.b.b.target = base->target; + tex->b.b.b.format = base->format; + tex->b.b.b.width0 = base->width0; + tex->b.b.b.height0 = base->height0; + tex->b.b.b.depth0 = base->depth0; + tex->b.b.b.array_size = base->array_size; + tex->b.b.b.last_level = base->last_level; + tex->b.b.b.nr_samples = base->nr_samples; + tex->tex.width0 = base->width0; + tex->tex.height0 = base->height0; + tex->tex.depth0 = base->depth0; + + r300_setup_flags(tex); /* Align a 3D NPOT texture to POT. */ - if (base->target == PIPE_TEXTURE_3D && desc->is_npot) { - desc->width0 = util_next_power_of_two(desc->width0); - desc->height0 = util_next_power_of_two(desc->height0); - desc->depth0 = util_next_power_of_two(desc->depth0); + if (base->target == PIPE_TEXTURE_3D && tex->tex.is_npot) { + tex->tex.width0 = util_next_power_of_two(tex->tex.width0); + tex->tex.height0 = util_next_power_of_two(tex->tex.height0); + tex->tex.depth0 = util_next_power_of_two(tex->tex.depth0); } /* Setup tiling. */ - if (microtile == R300_BUFFER_SELECT_LAYOUT || - macrotile == R300_BUFFER_SELECT_LAYOUT) { - r300_setup_tiling(rscreen, desc); - } else { - desc->microtile = microtile; - desc->macrotile[0] = macrotile; - assert(desc->b.b.last_level == 0); + if (tex->tex.microtile == R300_BUFFER_SELECT_LAYOUT) { + r300_setup_tiling(rscreen, tex); } - r300_setup_cbzb_flags(rscreen, desc); + r300_setup_cbzb_flags(rscreen, tex); /* Setup the miptree description. */ - r300_setup_miptree(rscreen, desc, TRUE); + r300_setup_miptree(rscreen, tex, TRUE); /* If the required buffer size is larger the given max size, * try again without the alignment for the CBZB clear. */ - if (max_buffer_size && desc->size_in_bytes > max_buffer_size) { - r300_setup_miptree(rscreen, desc, FALSE); + if (tex->buf_size && tex->tex.size_in_bytes > tex->buf_size) { + r300_setup_miptree(rscreen, tex, FALSE); } - r300_texture_3d_fix_mipmapping(rscreen, desc); + r300_texture_3d_fix_mipmapping(rscreen, tex); + r300_setup_zmask_flags(rscreen, tex); - if (max_buffer_size) { + if (tex->buf_size) { /* Make sure the buffer we got is large enough. */ - if (desc->size_in_bytes > max_buffer_size) { + if (tex->tex.size_in_bytes > tex->buf_size) { fprintf(stderr, "r300: texture_desc_init: The buffer is not " "large enough. Got: %i, Need: %i, Info:\n", - max_buffer_size, desc->size_in_bytes); - r300_tex_print_info(rscreen, desc, "texture_desc_init"); + tex->buf_size, tex->tex.size_in_bytes); + r300_tex_print_info(tex, "texture_desc_init"); return FALSE; } - desc->buffer_size_in_bytes = max_buffer_size; + tex->tex.buffer_size_in_bytes = tex->buf_size; } else { - desc->buffer_size_in_bytes = desc->size_in_bytes; + tex->tex.buffer_size_in_bytes = tex->tex.size_in_bytes; } if (SCREEN_DBG_ON(rscreen, DBG_TEX)) - r300_tex_print_info(rscreen, desc, "texture_desc_init"); + r300_tex_print_info(tex, "texture_desc_init"); return TRUE; } -unsigned r300_texture_get_offset(struct r300_texture_desc *desc, +unsigned r300_texture_get_offset(struct r300_resource *tex, unsigned level, unsigned layer) { - unsigned offset = desc->offset_in_bytes[level]; + unsigned offset = tex->tex.offset_in_bytes[level]; - switch (desc->b.b.target) { + switch (tex->b.b.b.target) { case PIPE_TEXTURE_3D: case PIPE_TEXTURE_CUBE: - return offset + layer * desc->layer_size_in_bytes[level]; + return offset + layer * tex->tex.layer_size_in_bytes[level]; default: assert(layer == 0); diff --git a/src/gallium/drivers/r300/r300_texture_desc.h b/src/gallium/drivers/r300/r300_texture_desc.h index 121d215b4cb..ce6e9643ec6 100644 --- a/src/gallium/drivers/r300/r300_texture_desc.h +++ b/src/gallium/drivers/r300/r300_texture_desc.h @@ -30,7 +30,7 @@ struct pipe_resource; struct r300_screen; struct r300_texture_desc; -struct r300_texture; +struct r300_resource; enum r300_dim { DIM_WIDTH = 0, @@ -44,14 +44,10 @@ unsigned r300_get_pixel_alignment(enum pipe_format format, enum r300_dim dim, boolean is_rs690); boolean r300_texture_desc_init(struct r300_screen *rscreen, - struct r300_texture_desc *desc, - const struct pipe_resource *base, - enum r300_buffer_tiling microtile, - enum r300_buffer_tiling macrotile, - unsigned stride_in_bytes_override, - unsigned max_buffer_size); - -unsigned r300_texture_get_offset(struct r300_texture_desc *desc, + struct r300_resource *tex, + const struct pipe_resource *base); + +unsigned r300_texture_get_offset(struct r300_resource *tex, unsigned level, unsigned layer); #endif diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c index 15a323989b2..97ec0a1a1f2 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c @@ -191,7 +191,12 @@ static void transform_dstreg( dst->File = translate_register_file(src->Register.File); dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index); dst->WriteMask = src->Register.WriteMask; - dst->RelAddr = src->Register.Indirect; + + if (src->Register.Indirect) { + ttr->error = TRUE; + fprintf(stderr, "r300: Relative addressing of destination operands " + "is unsupported.\n"); + } } static void transform_srcreg( @@ -332,6 +337,8 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, unsigned imm_index = 0; int i; + ttr->error = FALSE; + /* Allocate constants placeholders. * * Note: What if declared constants are not contiguous? */ diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.h b/src/gallium/drivers/r300/r300_tgsi_to_rc.h index 97641a954b9..adb044cfe56 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.h +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.h @@ -47,6 +47,9 @@ struct tgsi_to_rc { /* Vertex shaders have no half swizzles, and no way to handle them, so * until rc grows proper support, indicate if they're safe to use. */ boolean use_half_swizzles; + + /* If an error occured. */ + boolean error; }; void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens); diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index ae93fab554e..30de9ec1e32 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -37,7 +37,7 @@ struct r300_transfer { unsigned offset; /* Linear texture. */ - struct r300_texture *linear_texture; + struct r300_resource *linear_texture; }; /* Convenience cast wrapper. */ @@ -54,7 +54,7 @@ static void r300_copy_from_tiled_texture(struct pipe_context *ctx, struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; struct pipe_resource *tex = transfer->resource; - ctx->resource_copy_region(ctx, &r300transfer->linear_texture->desc.b.b, 0, + ctx->resource_copy_region(ctx, &r300transfer->linear_texture->b.b.b, 0, 0, 0, 0, tex, transfer->level, &transfer->box); } @@ -70,7 +70,7 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, ctx->resource_copy_region(ctx, tex, transfer->level, transfer->box.x, transfer->box.y, transfer->box.z, - &r300transfer->linear_texture->desc.b.b, 0, &src_box); + &r300transfer->linear_texture->b.b.b, 0, &src_box); ctx->flush(ctx, 0, NULL); } @@ -83,25 +83,24 @@ r300_texture_get_transfer(struct pipe_context *ctx, const struct pipe_box *box) { struct r300_context *r300 = r300_context(ctx); - struct r300_texture *tex = r300_texture(texture); + 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); referenced_cs = - r300->rws->cs_is_buffer_referenced(r300->cs, - tex->cs_buffer, R300_REF_CS); + r300->rws->cs_is_buffer_referenced(r300->cs, tex->cs_buf); if (referenced_cs) { referenced_hw = TRUE; } else { referenced_hw = - r300->rws->cs_is_buffer_referenced(r300->cs, - tex->cs_buffer, R300_REF_HW); + r300->rws->buffer_is_busy(tex->buf); } - blittable = ctx->screen->is_format_supported( - ctx->screen, texture->format, texture->target, 0, - PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, 0); + blittable = desc->layout == UTIL_FORMAT_LAYOUT_PLAIN || + desc->layout == UTIL_FORMAT_LAYOUT_S3TC; trans = CALLOC_STRUCT(r300_transfer); if (trans) { @@ -114,8 +113,13 @@ r300_texture_get_transfer(struct pipe_context *ctx, /* If the texture is tiled, we must create a temporary detiled texture * for this transfer. * Also make write transfers pipelined. */ - if (tex->desc.microtile || tex->desc.macrotile[level] || - ((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) { + if (tex->tex.microtile || tex->tex.macrotile[level] || + (referenced_hw && blittable && !(usage & PIPE_TRANSFER_READ))) { + if (r300->blitter->running) { + fprintf(stderr, "r300: ERROR: Blitter recursion in texture_get_transfer.\n"); + os_break(); + } + base.target = PIPE_TEXTURE_2D; base.format = texture->format; base.width0 = box->width; @@ -140,7 +144,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, } /* Create the temporary texture. */ - trans->linear_texture = r300_texture( + trans->linear_texture = r300_resource( ctx->screen->resource_create(ctx->screen, &base)); @@ -149,14 +153,14 @@ r300_texture_get_transfer(struct pipe_context *ctx, * Let's flush and try again. */ ctx->flush(ctx, 0, NULL); - trans->linear_texture = r300_texture( + trans->linear_texture = r300_resource( ctx->screen->resource_create(ctx->screen, &base)); if (!trans->linear_texture) { /* For linear textures, it's safe to fallback to * an unpipelined transfer. */ - if (!tex->desc.microtile && !tex->desc.macrotile[level]) { + if (!tex->tex.microtile && !tex->tex.macrotile[level]) { goto unpipelined; } @@ -168,8 +172,8 @@ r300_texture_get_transfer(struct pipe_context *ctx, } } - assert(!trans->linear_texture->desc.microtile && - !trans->linear_texture->desc.macrotile[0]); + assert(!trans->linear_texture->tex.microtile && + !trans->linear_texture->tex.macrotile[0]); /* Set the stride. * @@ -179,7 +183,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, * right thing internally. */ trans->transfer.stride = - trans->linear_texture->desc.stride_in_bytes[0]; + trans->linear_texture->tex.stride_in_bytes[0]; if (usage & PIPE_TRANSFER_READ) { /* We cannot map a tiled texture directly because the data is @@ -194,8 +198,8 @@ r300_texture_get_transfer(struct pipe_context *ctx, unpipelined: /* Unpipelined transfer. */ - trans->transfer.stride = tex->desc.stride_in_bytes[level]; - trans->offset = r300_texture_get_offset(&tex->desc, level, box->z); + trans->transfer.stride = tex->tex.stride_in_bytes[level]; + trans->offset = r300_texture_get_offset(tex, level, box->z); if (referenced_cs) ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL); @@ -227,20 +231,19 @@ void* r300_texture_transfer_map(struct pipe_context *ctx, struct r300_context *r300 = r300_context(ctx); struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; struct r300_transfer *r300transfer = r300_transfer(transfer); - struct r300_texture *tex = r300_texture(transfer->resource); + struct r300_resource *tex = r300_resource(transfer->resource); char *map; - enum pipe_format format = tex->desc.b.b.format; + enum pipe_format format = tex->b.b.b.format; if (r300transfer->linear_texture) { /* The detiled texture is of the same size as the region being mapped * (no offset needed). */ - return rws->buffer_map(rws, - r300transfer->linear_texture->buffer, + return rws->buffer_map(r300transfer->linear_texture->buf, r300->cs, transfer->usage); } else { /* Tiling is disabled. */ - map = rws->buffer_map(rws, tex->buffer, r300->cs, + map = rws->buffer_map(tex->buf, r300->cs, transfer->usage); if (!map) { @@ -258,11 +261,11 @@ void r300_texture_transfer_unmap(struct pipe_context *ctx, { struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; struct r300_transfer *r300transfer = r300_transfer(transfer); - struct r300_texture *tex = r300_texture(transfer->resource); + struct r300_resource *tex = r300_resource(transfer->resource); if (r300transfer->linear_texture) { - rws->buffer_unmap(rws, r300transfer->linear_texture->buffer); + rws->buffer_unmap(r300transfer->linear_texture->buf); } else { - rws->buffer_unmap(rws, tex->buffer); + rws->buffer_unmap(tex->buf); } } diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 78021e2c5d4..b319890157f 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -226,6 +226,13 @@ void r300_translate_vertex_shader(struct r300_context *r300, r300_tgsi_to_rc(&ttr, vs->state.tokens); + if (ttr.error) { + fprintf(stderr, "r300 VP: Cannot translate a shader. " + "Using a dummy shader instead.\n"); + r300_dummy_vertex_shader(r300, vs); + return; + } + if (compiler.Base.Program.Constants.Count > 200) { compiler.Base.remove_unused_constants = TRUE; } diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 460da77a4fb..d5c73585c81 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -28,38 +28,45 @@ * Any winsys hosting this pipe needs to implement r300_winsys_screen and then * call r300_screen_create to start things. */ +#include "r300_defines.h" + +#include "pipebuffer/pb_bufmgr.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" -#include "r300_defines.h" - #define R300_MAX_CMDBUF_DWORDS (16 * 1024) struct winsys_handle; struct r300_winsys_screen; -struct r300_winsys_buffer; /* for map/unmap etc. */ -struct r300_winsys_cs_buffer; /* for write_reloc etc. */ +#define r300_winsys_bo pb_buffer +#define r300_winsys_bo_reference(pdst, src) pb_reference(pdst, src) + +struct r300_winsys_cs_handle; /* for write_reloc etc. */ struct r300_winsys_cs { - unsigned cdw; /* Number of used dwords. */ - uint32_t buf[R300_MAX_CMDBUF_DWORDS]; /* The command buffer. */ + unsigned cdw; /* Number of used dwords. */ + uint32_t *buf; /* The command buffer. */ }; enum r300_value_id { R300_VID_PCI_ID, R300_VID_GB_PIPES, R300_VID_Z_PIPES, - R300_VID_SQUARE_TILING_SUPPORT, - R300_VID_DRM_2_3_0, /* R500 VAP regs, MSPOS regs, fixed tex3D size checking */ - R300_VID_DRM_2_6_0, /* Hyper-Z, GB_Z_PEQ_CONFIG on rv350->r4xx, R500 FG_ALPHA_VALUE */ - R300_VID_DRM_2_8_0, /* R500 US_FORMAT regs, R500 ARGB2101010 colorbuffer */ - R300_CAN_HYPERZ, -}; - -enum r300_reference_domain { /* bitfield */ - R300_REF_CS = 1, - R300_REF_HW = 2 + R300_VID_GART_SIZE, + R300_VID_VRAM_SIZE, + R300_VID_DRM_MAJOR, + R300_VID_DRM_MINOR, + R300_VID_DRM_PATCHLEVEL, + + /* These should probably go away: */ + R300_VID_DRM_2_1_0, /* Square tiling. */ + R300_VID_DRM_2_3_0, /* R500 VAP regs, MSPOS regs, fixed tex3D size checking */ + R300_VID_DRM_2_6_0, /* Hyper-Z, GB_Z_PEQ_CONFIG on rv350->r4xx, R500 FG_ALPHA_VALUE */ + R300_VID_DRM_2_8_0, /* R500 US_FORMAT regs, R500 ARGB2101010 colorbuffer, CMask */ + + R300_CAN_HYPERZ, /* ZMask + HiZ */ + R300_CAN_AACOMPRESS, /* CMask */ }; struct r300_winsys_screen { @@ -98,91 +105,78 @@ struct r300_winsys_screen { * \param domain A bitmask of the R300_DOMAIN_* flags. * \return The created buffer object. */ - struct r300_winsys_buffer *(*buffer_create)(struct r300_winsys_screen *ws, + struct r300_winsys_bo *(*buffer_create)(struct r300_winsys_screen *ws, unsigned size, unsigned alignment, unsigned bind, unsigned usage, enum r300_buffer_domain domain); - struct r300_winsys_cs_buffer *(*buffer_get_cs_handle)( - struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf); - - /** - * Reference a buffer object (assign with reference counting). - * - * \param ws The winsys this function is called from. - * \param pdst A destination pointer to set the source buffer to. - * \param src A source buffer object. - */ - void (*buffer_reference)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer **pdst, - struct r300_winsys_buffer *src); + struct r300_winsys_cs_handle *(*buffer_get_cs_handle)( + struct r300_winsys_bo *buf); /** * Map the entire data store of a buffer object into the client's address * space. * - * \param ws The winsys this function is called from. * \param buf A winsys buffer object to map. * \param cs A command stream to flush if the buffer is referenced by it. * \param usage A bitmask of the PIPE_TRANSFER_* flags. * \return The pointer at the beginning of the buffer. */ - void *(*buffer_map)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf, + void *(*buffer_map)(struct r300_winsys_bo *buf, struct r300_winsys_cs *cs, enum pipe_transfer_usage usage); /** * Unmap a buffer object from the client's address space. * - * \param ws The winsys this function is called from. * \param buf A winsys buffer object to unmap. */ - void (*buffer_unmap)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf); + void (*buffer_unmap)(struct r300_winsys_bo *buf); + + /** + * Return TRUE if a buffer object is being used by the GPU. + * + * \param buf A winsys buffer object. + */ + boolean (*buffer_is_busy)(struct r300_winsys_bo *buf); /** * Wait for a buffer object until it is not used by a GPU. This is * equivalent to a fence placed after the last command using the buffer, * and synchronizing to the fence. * - * \param ws The winsys this function is called from. * \param buf A winsys buffer object to wait for. */ - void (*buffer_wait)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf); + void (*buffer_wait)(struct r300_winsys_bo *buf); /** * Return tiling flags describing a memory layout of a buffer object. * - * \param ws The winsys this function is called from. * \param buf A winsys buffer object to get the flags from. * \param macrotile A pointer to the return value of the microtile flag. * \param microtile A pointer to the return value of the macrotile flag. * * \note microtile and macrotile are not bitmasks! */ - void (*buffer_get_tiling)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf, + void (*buffer_get_tiling)(struct r300_winsys_bo *buf, enum r300_buffer_tiling *microtile, enum r300_buffer_tiling *macrotile); /** * Set tiling flags describing a memory layout of a buffer object. * - * \param ws The winsys this function is called from. * \param buf A winsys buffer object to set the flags for. + * \param cs A command stream to flush if the buffer is referenced by it. * \param macrotile A macrotile flag. * \param microtile A microtile flag. * \param stride A stride of the buffer in bytes, for texturing. * * \note microtile and macrotile are not bitmasks! */ - void (*buffer_set_tiling)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf, + void (*buffer_set_tiling)(struct r300_winsys_bo *buf, + struct r300_winsys_cs *cs, enum r300_buffer_tiling microtile, enum r300_buffer_tiling macrotile, unsigned stride); @@ -197,7 +191,7 @@ struct r300_winsys_screen { * \param stride The returned buffer stride in bytes. * \param size The returned buffer size. */ - struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *ws, + struct r300_winsys_bo *(*buffer_from_handle)(struct r300_winsys_screen *ws, struct winsys_handle *whandle, unsigned *stride, unsigned *size); @@ -206,14 +200,12 @@ struct r300_winsys_screen { * Get a winsys handle from a winsys buffer. The internal structure * of the handle is platform-specific and only a winsys should access it. * - * \param ws The winsys this function is called from. * \param buf A winsys buffer object to get the handle from. * \param whandle A winsys handle pointer. * \param stride A stride of the buffer in bytes, for texturing. * \return TRUE on success. */ - boolean (*buffer_get_handle)(struct r300_winsys_screen *ws, - struct r300_winsys_buffer *buf, + boolean (*buffer_get_handle)(struct r300_winsys_bo *buf, unsigned stride, struct winsys_handle *whandle); @@ -248,7 +240,7 @@ struct r300_winsys_screen { * \param wd A write domain containing a bitmask of the R300_DOMAIN_* flags. */ void (*cs_add_reloc)(struct r300_winsys_cs *cs, - struct r300_winsys_cs_buffer *buf, + struct r300_winsys_cs_handle *buf, enum r300_buffer_domain rd, enum r300_buffer_domain wd); @@ -269,7 +261,7 @@ struct r300_winsys_screen { * \param wd A write domain containing a bitmask of the R300_DOMAIN_* flags. */ void (*cs_write_reloc)(struct r300_winsys_cs *cs, - struct r300_winsys_cs_buffer *buf); + struct r300_winsys_cs_handle *buf); /** * Flush a command stream. @@ -279,6 +271,13 @@ struct r300_winsys_screen { void (*cs_flush)(struct r300_winsys_cs *cs); /** + * Wait until the last flush is completed. + * + * \param cs A command stream. + */ + void (*cs_sync_flush)(struct r300_winsys_cs *cs); + + /** * Set a flush callback which is called from winsys when flush is * required. * @@ -291,16 +290,13 @@ struct r300_winsys_screen { void *user); /** - * Return TRUE if a buffer is referenced by a command stream or by hardware - * (i.e. is busy), based on the domain parameter. + * Return TRUE if a buffer is referenced by a command stream. * * \param cs A command stream. * \param buf A winsys buffer. - * \param domain A bitmask of the R300_REF_* enums. */ boolean (*cs_is_buffer_referenced)(struct r300_winsys_cs *cs, - struct r300_winsys_cs_buffer *buf, - enum r300_reference_domain domain); + struct r300_winsys_cs_handle *buf); }; #endif /* R300_WINSYS_H */ |