diff options
Diffstat (limited to 'src/gallium/drivers/i915')
-rw-r--r-- | src/gallium/drivers/i915/TODO | 25 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_batch.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_batchbuffer.h | 35 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_blit.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_context.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_debug.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_debug.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_prim_vbuf.c | 15 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_reg.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_resource.h | 16 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_resource_buffer.c | 25 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_resource_texture.c | 136 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_screen.c | 15 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_state_emit.c | 73 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_state_sampler.c | 25 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_surface.c | 98 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_surface.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/i915/i915_winsys.h | 29 |
18 files changed, 314 insertions, 205 deletions
diff --git a/src/gallium/drivers/i915/TODO b/src/gallium/drivers/i915/TODO new file mode 100644 index 00000000000..94c428bebf8 --- /dev/null +++ b/src/gallium/drivers/i915/TODO @@ -0,0 +1,25 @@ +Random list of problems with i915g: + +- Dies with BadDrawable on GLXFBconfig changes/destruction. Makes piglit totally + unusable :( Upgrading xserver helped here, it doesn't crash anymore. Still + broken, it doesn't update the viewport/get new buffers. + +- Tends to hang the chip after a few minutes of openarena. Looks tiling related, + at the last frame rendered has tiling corruption over the complete frame. + +- Kills the chip in 3D_PRIMITIVE LINELIST with mesa-demos/fbotexture in + wireframe mode. + +- Tiling is funny: If unlucky, it renders/samples all black. No clue yet what's + going on. Seems to depend on tiny details like whethever the sampler + relocation is fenced/unfenced (broken _with_ fenced reloc using tiling bits!). + +- Y-tiling is even more fun. i915c doesn't use it, maybe there's a reason? + Texture sampling from Y-tiled buffers seems to work, though (save above + problems). + +- Need to validate buffers before usage. Currently do_exec on the batchbuffer + can fail with -ENOSPC. + +Other bugs can be found here: +https://bugs.freedesktop.org/buglist.cgi?bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&component=Drivers/Gallium/i915g diff --git a/src/gallium/drivers/i915/i915_batch.h b/src/gallium/drivers/i915/i915_batch.h index c411b84ccd4..6e93da76209 100644 --- a/src/gallium/drivers/i915/i915_batch.h +++ b/src/gallium/drivers/i915/i915_batch.h @@ -38,7 +38,10 @@ i915_winsys_batchbuffer_dword(i915->batch, dword) #define OUT_RELOC(buf, usage, offset) \ - i915_winsys_batchbuffer_reloc(i915->batch, buf, usage, offset) + i915_winsys_batchbuffer_reloc(i915->batch, buf, usage, offset, false) + +#define OUT_RELOC_FENCED(buf, usage, offset) \ + i915_winsys_batchbuffer_reloc(i915->batch, buf, usage, offset, true) #define FLUSH_BATCH(fence) \ i915_flush(i915, fence) diff --git a/src/gallium/drivers/i915/i915_batchbuffer.h b/src/gallium/drivers/i915/i915_batchbuffer.h index c1cd314e7b8..d92b2ccb31e 100644 --- a/src/gallium/drivers/i915/i915_batchbuffer.h +++ b/src/gallium/drivers/i915/i915_batchbuffer.h @@ -29,42 +29,47 @@ #define I915_BATCHBUFFER_H #include "i915_winsys.h" +#include "util/u_debug.h" struct i915_context; +static INLINE size_t +i915_winsys_batchbuffer_space(struct i915_winsys_batchbuffer *batch) +{ + return batch->size - (batch->ptr - batch->map); +} + static INLINE boolean i915_winsys_batchbuffer_check(struct i915_winsys_batchbuffer *batch, size_t dwords, size_t relocs) { - return dwords * 4 <= batch->size - (batch->ptr - batch->map) && + return dwords * 4 <= i915_winsys_batchbuffer_space(batch) && relocs <= (batch->max_relocs - batch->relocs); } -static INLINE size_t -i915_winsys_batchbuffer_space(struct i915_winsys_batchbuffer *batch) +static INLINE void +i915_winsys_batchbuffer_dword_unchecked(struct i915_winsys_batchbuffer *batch, + unsigned dword) { - return batch->size - (batch->ptr - batch->map); + *(unsigned *)batch->ptr = dword; + batch->ptr += 4; } static INLINE void i915_winsys_batchbuffer_dword(struct i915_winsys_batchbuffer *batch, unsigned dword) { - if (i915_winsys_batchbuffer_space(batch) < 4) - return; - - *(unsigned *)batch->ptr = dword; - batch->ptr += 4; + assert (i915_winsys_batchbuffer_space(batch) >= 4); + i915_winsys_batchbuffer_dword_unchecked(batch, dword); } static INLINE void i915_winsys_batchbuffer_write(struct i915_winsys_batchbuffer *batch, - void *data, - size_t size) + void *data, + size_t size) { - if (i915_winsys_batchbuffer_space(batch) < size) - return; + assert (i915_winsys_batchbuffer_space(batch) >= size); memcpy(data, batch->ptr, size); batch->ptr += size; @@ -74,9 +79,9 @@ static INLINE int i915_winsys_batchbuffer_reloc(struct i915_winsys_batchbuffer *batch, struct i915_winsys_buffer *buffer, enum i915_winsys_buffer_usage usage, - size_t offset) + size_t offset, bool fenced) { - return batch->iws->batchbuffer_reloc(batch, buffer, usage, offset); + return batch->iws->batchbuffer_reloc(batch, buffer, usage, offset, fenced); } #endif diff --git a/src/gallium/drivers/i915/i915_blit.c b/src/gallium/drivers/i915/i915_blit.c index cdf20c0055a..97c25665156 100644 --- a/src/gallium/drivers/i915/i915_blit.c +++ b/src/gallium/drivers/i915/i915_blit.c @@ -74,7 +74,7 @@ i915_fill_blit(struct i915_context *i915, OUT_BATCH(BR13); OUT_BATCH((y << 16) | x); OUT_BATCH(((y + h) << 16) | (x + w)); - OUT_RELOC(dst_buffer, I915_USAGE_2D_TARGET, dst_offset); + OUT_RELOC_FENCED(dst_buffer, I915_USAGE_2D_TARGET, dst_offset); OUT_BATCH(color); } @@ -138,8 +138,8 @@ i915_copy_blit(struct i915_context *i915, OUT_BATCH(BR13); OUT_BATCH((dst_y << 16) | dst_x); OUT_BATCH((dst_y2 << 16) | dst_x2); - OUT_RELOC(dst_buffer, I915_USAGE_2D_TARGET, dst_offset); + OUT_RELOC_FENCED(dst_buffer, I915_USAGE_2D_TARGET, dst_offset); OUT_BATCH((src_y << 16) | src_x); OUT_BATCH(((int) src_pitch & 0xffff)); - OUT_RELOC(src_buffer, I915_USAGE_2D_SOURCE, src_offset); + OUT_RELOC_FENCED(src_buffer, I915_USAGE_2D_SOURCE, src_offset); } diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h index 3ae61d0ea70..d15e1723d83 100644 --- a/src/gallium/drivers/i915/i915_context.h +++ b/src/gallium/drivers/i915/i915_context.h @@ -193,8 +193,7 @@ struct i915_velems_state { }; -struct i915_context -{ +struct i915_context { struct pipe_context base; struct i915_winsys *iws; @@ -273,7 +272,7 @@ struct i915_context #define I915_HW_PROGRAM (1<<I915_CACHE_PROGRAM) #define I915_HW_CONSTANTS (1<<I915_CACHE_CONSTANTS) #define I915_HW_IMMEDIATE (1<<(I915_MAX_CACHE+0)) -#define I915_HW_INVARIENT (1<<(I915_MAX_CACHE+1)) +#define I915_HW_INVARIANT (1<<(I915_MAX_CACHE+1)) /*********************************************************************** diff --git a/src/gallium/drivers/i915/i915_debug.c b/src/gallium/drivers/i915/i915_debug.c index 57d3390dea3..87c435a2f36 100644 --- a/src/gallium/drivers/i915/i915_debug.c +++ b/src/gallium/drivers/i915/i915_debug.c @@ -46,10 +46,12 @@ static const struct debug_named_value debug_options[] = { }; unsigned i915_debug = 0; +boolean i915_tiling = TRUE; void i915_debug_init(struct i915_screen *screen) { i915_debug = debug_get_flags_option("I915_DEBUG", debug_options, 0); + i915_tiling = !debug_get_bool_option("I915_NO_TILING", FALSE); } @@ -974,7 +976,7 @@ i915_dump_hardware_dirty(struct i915_context *i915, const char *func) {I915_HW_PROGRAM, "program"}, {I915_HW_CONSTANTS, "constants"}, {I915_HW_IMMEDIATE, "immediate"}, - {I915_HW_INVARIENT, "invarient"}, + {I915_HW_INVARIANT, "invariant"}, {0, NULL}, }; int i; diff --git a/src/gallium/drivers/i915/i915_debug.h b/src/gallium/drivers/i915/i915_debug.h index fa60799d0c5..11af7662f0a 100644 --- a/src/gallium/drivers/i915/i915_debug.h +++ b/src/gallium/drivers/i915/i915_debug.h @@ -46,6 +46,7 @@ struct i915_winsys_batchbuffer; #define DBG_CONSTANTS 0x20 extern unsigned i915_debug; +extern boolean i915_tiling; #ifdef DEBUG static INLINE boolean diff --git a/src/gallium/drivers/i915/i915_prim_vbuf.c b/src/gallium/drivers/i915/i915_prim_vbuf.c index bd046bd9058..baebbc7bae3 100644 --- a/src/gallium/drivers/i915/i915_prim_vbuf.c +++ b/src/gallium/drivers/i915/i915_prim_vbuf.c @@ -172,6 +172,7 @@ i915_vbuf_render_reserve(struct i915_vbuf_render *i915_render, size_t size) * * Side effects: * Updates hw_offset, sw_offset, index and allocates a new buffer. + * Will set i915->vbo to null on buffer allocation. */ static void i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size) @@ -179,8 +180,16 @@ i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size) struct i915_context *i915 = i915_render->i915; struct i915_winsys *iws = i915->iws; - if (i915_render->vbo) + if (i915_render->vbo) { iws->buffer_destroy(iws, i915_render->vbo); + /* + * XXX If buffers where referenced then this should be done in + * update_vbo_state but since they arn't and malloc likes to reuse + * memory we need to set it to null + */ + i915->vbo = NULL; + i915_render->vbo = NULL; + } i915->vbo_flushed = 0; @@ -198,7 +207,7 @@ i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size) #endif i915_render->vbo = iws->buffer_create(iws, i915_render->vbo_size, - 64, I915_NEW_VERTEX); + I915_NEW_VERTEX); } /** @@ -726,7 +735,7 @@ i915_vbuf_render_create(struct i915_context *i915) i915_render->pool_fifo = u_fifo_create(6); for (i = 0; i < 6; i++) u_fifo_add(i915_render->pool_fifo, - iws->buffer_create(iws, i915_render->pool_buffer_size, 64, + iws->buffer_create(iws, i915_render->pool_buffer_size, I915_NEW_VERTEX)); #else (void)i; diff --git a/src/gallium/drivers/i915/i915_reg.h b/src/gallium/drivers/i915/i915_reg.h index 04620fec681..5e4e80ddf6b 100644 --- a/src/gallium/drivers/i915/i915_reg.h +++ b/src/gallium/drivers/i915/i915_reg.h @@ -753,7 +753,7 @@ #define MT_COMPRESS_DXT1_RGB (4<<3) #define MS3_USE_FENCE_REGS (1<<2) #define MS3_TILED_SURFACE (1<<1) -#define MS3_TILE_WALK (1<<0) +#define MS3_TILE_WALK_Y (1<<0) #define MS4_PITCH_SHIFT 21 #define MS4_CUBE_FACE_ENA_NEGX (1<<20) @@ -851,6 +851,7 @@ #define MI_FLUSH ((0<<29)|(4<<23)) #define FLUSH_MAP_CACHE (1<<0) #define INHIBIT_FLUSH_RENDER_CACHE (1<<2) +#define MI_NOOP 0 #define CMD_3D (0x3<<29) @@ -973,6 +974,8 @@ #define PCI_CHIP_G33_G 0x29C2 #define PCI_CHIP_Q35_G 0x29B2 #define PCI_CHIP_Q33_G 0x29D2 +#define PCI_CHIP_PINEVIEW_G 0xA001 +#define PCI_CHIP_PINEVIEW_M 0xA011 #endif diff --git a/src/gallium/drivers/i915/i915_resource.h b/src/gallium/drivers/i915/i915_resource.h index 1093e8f41f9..86620e6a123 100644 --- a/src/gallium/drivers/i915/i915_resource.h +++ b/src/gallium/drivers/i915/i915_resource.h @@ -32,6 +32,7 @@ struct i915_screen; #include "util/u_transfer.h" #include "util/u_debug.h" +#include "i915_winsys.h" struct i915_context; @@ -48,29 +49,36 @@ struct i915_buffer { #define I915_MAX_TEXTURE_3D_LEVELS 8 /* max 128x128x128 */ +struct offset_pair { + unsigned short nblocksx; + unsigned short nblocksy; +}; struct i915_texture { struct u_resource b; + /* tiling flags */ + enum i915_winsys_buffer_tile tiling; unsigned stride; unsigned depth_stride; /* per-image on i945? */ unsigned total_nblocksy; - unsigned sw_tiled; /**< tiled with software flags */ - unsigned hw_tiled; /**< tiled with hardware fences */ - unsigned nr_images[I915_MAX_TEXTURE_2D_LEVELS]; /* Explicitly store the offset of each image for each cube face or * depth value. + * + * Array [depth] off offsets. */ - unsigned *image_offset[I915_MAX_TEXTURE_2D_LEVELS]; /**< array [depth] of offsets */ + struct offset_pair *image_offset[I915_MAX_TEXTURE_2D_LEVELS]; /* The data is held here: */ struct i915_winsys_buffer *buffer; }; +unsigned i915_texture_offset(struct i915_texture *tex, + unsigned level, unsigned layer); void i915_init_screen_resource_functions(struct i915_screen *is); void i915_init_resource_functions(struct i915_context *i915); diff --git a/src/gallium/drivers/i915/i915_resource_buffer.c b/src/gallium/drivers/i915/i915_resource_buffer.c index 0d379497dfc..450203d60a9 100644 --- a/src/gallium/drivers/i915/i915_resource_buffer.c +++ b/src/gallium/drivers/i915/i915_resource_buffer.c @@ -62,7 +62,7 @@ i915_buffer_destroy(struct pipe_screen *screen, static void * i915_buffer_transfer_map( struct pipe_context *pipe, - struct pipe_transfer *transfer ) + struct pipe_transfer *transfer ) { struct i915_buffer *buffer = i915_buffer(transfer->resource); return buffer->data + transfer->box.x; @@ -71,19 +71,19 @@ i915_buffer_transfer_map( struct pipe_context *pipe, static void i915_buffer_transfer_inline_write( struct pipe_context *rm_ctx, - struct pipe_resource *resource, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box, - const void *data, - unsigned stride, - unsigned slice_stride) + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) { struct i915_buffer *buffer = i915_buffer(resource); memcpy(buffer->data + box->x, - data, - box->width); + data, + box->width); } @@ -115,7 +115,7 @@ i915_buffer_create(struct pipe_screen *screen, buf->b.vtbl = &i915_buffer_vtbl; pipe_reference_init(&buf->b.b.reference, 1); buf->b.b.screen = screen; - + buf->data = MALLOC(template->width0); buf->free_on_destroy = TRUE; @@ -135,7 +135,7 @@ struct pipe_resource * i915_user_buffer_create(struct pipe_screen *screen, void *ptr, unsigned bytes, - unsigned bind) + unsigned bind) { struct i915_buffer *buf = CALLOC_STRUCT(i915_buffer); @@ -152,6 +152,7 @@ i915_user_buffer_create(struct pipe_screen *screen, buf->b.b.width0 = bytes; buf->b.b.height0 = 1; buf->b.b.depth0 = 1; + buf->b.b.array_size = 1; buf->data = ptr; buf->free_on_destroy = FALSE; diff --git a/src/gallium/drivers/i915/i915_resource_texture.c b/src/gallium/drivers/i915/i915_resource_texture.c index c5c6179b169..f19106f3414 100644 --- a/src/gallium/drivers/i915/i915_resource_texture.c +++ b/src/gallium/drivers/i915/i915_resource_texture.c @@ -106,6 +106,23 @@ get_pot_stride(enum pipe_format format, unsigned width) return util_next_power_of_two(util_format_get_stride(format, width)); } +static INLINE const char* +get_tiling_string(enum i915_winsys_buffer_tile tile) +{ + switch(tile) { + case I915_TILE_NONE: + return "none"; + case I915_TILE_X: + return "x"; + case I915_TILE_Y: + return "y"; + default: + assert(FALSE); + return "?"; + } +} + + /* * More advanced helper funcs */ @@ -120,28 +137,56 @@ i915_texture_set_level_info(struct i915_texture *tex, assert(!tex->image_offset[level]); tex->nr_images[level] = nr_images; - tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned)); - tex->image_offset[level][0] = 0; + tex->image_offset[level] = MALLOC(nr_images * sizeof(struct offset_pair)); + tex->image_offset[level][0].nblocksx = 0; + tex->image_offset[level][0].nblocksy = 0; +} + +INLINE unsigned i915_texture_offset(struct i915_texture *tex, + unsigned level, unsigned layer) +{ + unsigned x, y; + x = tex->image_offset[level][layer].nblocksx + * util_format_get_blocksize(tex->b.b.format); + y = tex->image_offset[level][layer].nblocksy; + + return y * tex->stride + x; } static void i915_texture_set_image_offset(struct i915_texture *tex, unsigned level, unsigned img, - unsigned x, unsigned y) + unsigned nblocksx, unsigned nblocksy) { /* for the first image and level make sure offset is zero */ - assert(!(img == 0 && level == 0) || (x == 0 && y == 0)); + assert(!(img == 0 && level == 0) || (nblocksx == 0 && nblocksy == 0)); assert(img < tex->nr_images[level]); - tex->image_offset[level][img] = y * tex->stride + x * util_format_get_blocksize(tex->b.b.format); + tex->image_offset[level][img].nblocksx = nblocksx; + tex->image_offset[level][img].nblocksy = nblocksy; #if DEBUG_TEXTURES - debug_printf("%s: %p level %u, img %u (%u, %u) %p\n", __FUNCTION__, - tex, level, img, x, y, - (void*)(uintptr_t)tex->image_offset[level][img]); + debug_printf("%s: %p level %u, img %u (%u, %u)\n", __FUNCTION__, + tex, level, img, x, y); #endif } +static enum i915_winsys_buffer_tile +i915_texture_tiling(struct pipe_resource *pt) +{ + if (!i915_tiling) + return I915_TILE_NONE; + + if (pt->target == PIPE_TEXTURE_1D) + return I915_TILE_NONE; + + if (util_format_is_s3tc(pt->format)) + /* XXX X-tiling might make sense */ + return I915_TILE_NONE; + + return I915_TILE_X; +} + /* * Shared layout functions @@ -163,9 +208,10 @@ i9x5_scanout_layout(struct i915_texture *tex) i915_texture_set_image_offset(tex, 0, 0, 0, 0); if (pt->width0 >= 240) { - tex->stride = get_pot_stride(pt->format, pt->width0); + tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64); tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); - tex->hw_tiled = I915_TILE_X; + tex->tiling = I915_TILE_X; + /* special case for cursors */ } else if (pt->width0 == 64 && pt->height0 == 64) { tex->stride = get_pot_stride(pt->format, pt->width0); tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); @@ -200,9 +246,9 @@ i9x5_display_target_layout(struct i915_texture *tex) i915_texture_set_level_info(tex, 0, 1); i915_texture_set_image_offset(tex, 0, 0, 0, 0); - tex->stride = get_pot_stride(pt->format, pt->width0); + tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64); tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); - tex->hw_tiled = I915_TILE_X; + tex->tiling = I915_TILE_X; #if DEBUG_TEXTURE debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__, @@ -357,6 +403,8 @@ i915_texture_layout(struct i915_texture * tex) { struct pipe_resource *pt = &tex->b.b; + tex->tiling = i915_texture_tiling(pt); + switch (pt->target) { case PIPE_TEXTURE_1D: case PIPE_TEXTURE_2D: @@ -603,6 +651,8 @@ i945_texture_layout(struct i915_texture * tex) { struct pipe_resource *pt = &tex->b.b; + tex->tiling = i915_texture_tiling(pt); + switch (pt->target) { case PIPE_TEXTURE_1D: case PIPE_TEXTURE_2D: @@ -650,7 +700,7 @@ i915_texture_get_handle(struct pipe_screen * screen, static void i915_texture_destroy(struct pipe_screen *screen, - struct pipe_resource *pt) + struct pipe_resource *pt) { struct i915_texture *tex = i915_texture(pt); struct i915_winsys *iws = i915_screen(screen)->iws; @@ -667,10 +717,10 @@ i915_texture_destroy(struct pipe_screen *screen, static struct pipe_transfer * i915_texture_get_transfer(struct pipe_context *context, - struct pipe_resource *resource, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box) { struct i915_texture *tex = i915_texture(resource); struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer); @@ -678,37 +728,31 @@ i915_texture_get_transfer(struct pipe_context *context, return NULL; transfer->resource = resource; - transfer->sr = sr; + transfer->level = level; transfer->usage = usage; transfer->box = *box; transfer->stride = tex->stride; + /* FIXME: layer_stride */ return transfer; } - static void * i915_texture_transfer_map(struct pipe_context *pipe, - struct pipe_transfer *transfer) + struct pipe_transfer *transfer) { struct pipe_resource *resource = transfer->resource; struct i915_texture *tex = i915_texture(resource); struct i915_winsys *iws = i915_screen(pipe->screen)->iws; - struct pipe_subresource sr = transfer->sr; struct pipe_box *box = &transfer->box; enum pipe_format format = resource->format; unsigned offset; char *map; - if (resource->target == PIPE_TEXTURE_CUBE) { - offset = tex->image_offset[sr.level][sr.face]; - } else if (resource->target == PIPE_TEXTURE_3D) { - offset = tex->image_offset[sr.level][box->z]; - } else { - offset = tex->image_offset[sr.level][0]; - assert(sr.face == 0); + if (resource->target != PIPE_TEXTURE_3D && + resource->target != PIPE_TEXTURE_CUBE) assert(box->z == 0); - } + offset = i915_texture_offset(tex, transfer->level, box->z); map = iws->buffer_map(iws, tex->buffer, (transfer->usage & PIPE_TRANSFER_WRITE) ? TRUE : FALSE); @@ -754,7 +798,6 @@ i915_texture_create(struct pipe_screen *screen, struct i915_screen *is = i915_screen(screen); struct i915_winsys *iws = is->iws; struct i915_texture *tex = CALLOC_STRUCT(i915_texture); - size_t tex_size; unsigned buf_usage = 0; if (!tex) @@ -773,8 +816,6 @@ i915_texture_create(struct pipe_screen *screen, goto fail; } - tex_size = tex->stride * tex->total_nblocksy; - /* for scanouts and cursors, cursors arn't scanouts */ /* XXX: use a custom flag for cursors, don't rely on magically @@ -785,28 +826,15 @@ i915_texture_create(struct pipe_screen *screen, else buf_usage = I915_NEW_TEXTURE; - tex->buffer = iws->buffer_create(iws, tex_size, 64, buf_usage); + tex->buffer = iws->buffer_create_tiled(iws, &tex->stride, tex->total_nblocksy, + &tex->tiling, buf_usage); if (!tex->buffer) goto fail; - /* setup any hw fences */ - if (tex->hw_tiled) { - assert(tex->sw_tiled == I915_TILE_NONE); - iws->buffer_set_fence_reg(iws, tex->buffer, tex->stride, tex->hw_tiled); - } - - -#if 0 - void *ptr = ws->buffer_map(ws, tex->buffer, - PIPE_BUFFER_USAGE_CPU_WRITE); - memset(ptr, 0x80, tex_size); - ws->buffer_unmap(ws, tex->buffer); -#endif - - I915_DBG(DBG_TEXTURE, "%s: %p size %u, stride %u, blocks (%u, %u)\n", __func__, - tex, (unsigned int)tex_size, tex->stride, + I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n", __func__, + tex, tex->stride, tex->stride / util_format_get_blocksize(tex->b.b.format), - tex->total_nblocksy); + tex->total_nblocksy, get_tiling_string(tex->tiling)); return &tex->b.b; @@ -825,10 +853,11 @@ i915_texture_from_handle(struct pipe_screen * screen, struct i915_winsys *iws = is->iws; struct i915_winsys_buffer *buffer; unsigned stride; + enum i915_winsys_buffer_tile tiling; assert(screen); - buffer = iws->buffer_from_handle(iws, whandle, &stride); + buffer = iws->buffer_from_handle(iws, whandle, &tiling, &stride); /* Only supports one type */ if ((template->target != PIPE_TEXTURE_2D && @@ -848,6 +877,7 @@ i915_texture_from_handle(struct pipe_screen * screen, tex->b.b.screen = screen; tex->stride = stride; + tex->tiling = tiling; tex->total_nblocksy = align_nblocksy(tex->b.b.format, tex->b.b.height0, 8); i915_texture_set_level_info(tex, 0, 1); @@ -855,10 +885,10 @@ i915_texture_from_handle(struct pipe_screen * screen, tex->buffer = buffer; - I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%ux%u)\n", __func__, + I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n", __func__, tex, tex->stride, tex->stride / util_format_get_blocksize(tex->b.b.format), - tex->total_nblocksy); + tex->total_nblocksy, get_tiling_string(tex->tiling)); return &tex->b.b; } diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index 312847fba9e..f66478e729c 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -83,6 +83,12 @@ i915_get_name(struct pipe_screen *screen) case PCI_CHIP_Q33_G: chipset = "Q33"; break; + case PCI_CHIP_PINEVIEW_G: + chipset = "Pineview G"; + break; + case PCI_CHIP_PINEVIEW_M: + chipset = "Pineview M"; + break; default: chipset = "unknown"; break; @@ -183,6 +189,8 @@ i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_sha case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 1; + case PIPE_SHADER_CAP_SUBROUTINES: + return 0; default: assert(0); return 0; @@ -225,10 +233,6 @@ i915_is_format_supported(struct pipe_screen *screen, static const enum pipe_format tex_supported[] = { PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_B8G8R8X8_UNORM, - PIPE_FORMAT_R8G8B8A8_UNORM, -#if 0 - PIPE_FORMAT_R8G8B8X8_UNORM, -#endif PIPE_FORMAT_B5G6R5_UNORM, PIPE_FORMAT_L8_UNORM, PIPE_FORMAT_A8_UNORM, @@ -351,6 +355,8 @@ i915_screen_create(struct i915_winsys *iws) case PCI_CHIP_G33_G: case PCI_CHIP_Q33_G: case PCI_CHIP_Q35_G: + case PCI_CHIP_PINEVIEW_G: + case PCI_CHIP_PINEVIEW_M: is->is_i945 = TRUE; break; @@ -381,7 +387,6 @@ i915_screen_create(struct i915_winsys *iws) is->base.fence_finish = i915_fence_finish; i915_init_screen_resource_functions(is); - i915_init_screen_surface_functions(is); i915_debug_init(is); diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c index bd059d5716c..86c02976495 100644 --- a/src/gallium/drivers/i915/i915_state_emit.c +++ b/src/gallium/drivers/i915/i915_state_emit.c @@ -86,6 +86,22 @@ framebuffer_size(const struct pipe_framebuffer_state *fb, } } +static inline uint32_t +buf_3d_tiling_bits(enum i915_winsys_buffer_tile tiling) +{ + uint32_t tiling_bits = 0; + + switch (tiling) { + case I915_TILE_Y: + tiling_bits |= BUF_3D_TILE_WALK_Y; + case I915_TILE_X: + tiling_bits |= BUF_3D_TILED_SURFACE; + case I915_TILE_NONE: + break; + } + + return tiling_bits; +} /* Push the state into the sarea and/or texture memory. */ @@ -126,7 +142,7 @@ i915_emit_hardware_state(struct i915_context *i915 ) save_relocs = i915->batch->relocs; /* 14 dwords, 0 relocs */ - if (i915->hardware_dirty & I915_HW_INVARIENT) + if (i915->hardware_dirty & I915_HW_INVARIANT) { OUT_BATCH(_3DSTATE_AA_CMD | AA_LINE_ECAAR_WIDTH_ENABLE | @@ -220,46 +236,39 @@ i915_emit_hardware_state(struct i915_context *i915 ) struct pipe_surface *depth_surface = i915->framebuffer.zsbuf; if (cbuf_surface) { - unsigned ctile = BUF_3D_USE_FENCE; struct i915_texture *tex = i915_texture(cbuf_surface->texture); assert(tex); - if (tex && tex->sw_tiled) { - ctile = BUF_3D_TILED_SURFACE; - } - OUT_BATCH(_3DSTATE_BUF_INFO_CMD); OUT_BATCH(BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(tex->stride) | /* pitch in bytes */ - ctile); + buf_3d_tiling_bits(tex->tiling)); OUT_RELOC(tex->buffer, I915_USAGE_RENDER, - cbuf_surface->offset); + 0); } /* What happens if no zbuf?? */ if (depth_surface) { - unsigned ztile = BUF_3D_USE_FENCE; struct i915_texture *tex = i915_texture(depth_surface->texture); + unsigned offset = i915_texture_offset(tex, depth_surface->u.tex.level, + depth_surface->u.tex.first_layer); assert(tex); - - if (tex && tex->sw_tiled) { - ztile = BUF_3D_TILED_SURFACE; - } + assert(offset == 0); OUT_BATCH(_3DSTATE_BUF_INFO_CMD); assert(tex); OUT_BATCH(BUF_3D_ID_DEPTH | BUF_3D_PITCH(tex->stride) | /* pitch in bytes */ - ztile); + buf_3d_tiling_bits(tex->tiling)); OUT_RELOC(tex->buffer, I915_USAGE_RENDER, - depth_surface->offset); + 0); } { @@ -301,12 +310,11 @@ i915_emit_hardware_state(struct i915_context *i915 ) if (enabled & (1 << unit)) { struct i915_texture *texture = i915_texture(i915->fragment_sampler_views[unit]->texture); struct i915_winsys_buffer *buf = texture->buffer; - uint offset = 0; assert(buf); count++; - OUT_RELOC(buf, I915_USAGE_SAMPLER, offset); + OUT_RELOC(buf, I915_USAGE_SAMPLER, 0); OUT_BATCH(i915->current.texbuffer[unit][0]); /* MS3 */ OUT_BATCH(i915->current.texbuffer[unit][1]); /* MS4 */ } @@ -399,18 +407,33 @@ i915_emit_hardware_state(struct i915_context *i915 ) #if 01 /* drawing surface size */ /* 6 dwords, 0 relocs */ + if (i915->hardware_dirty & I915_HW_STATIC) { uint w, h; - boolean k = framebuffer_size(&i915->framebuffer, &w, &h); - (void)k; - assert(k); + struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0]; + struct i915_texture *tex = i915_texture(cbuf_surface->texture); + unsigned x, y; + int layer; + uint32_t draw_offset; + boolean ret; + + ret = framebuffer_size(&i915->framebuffer, &w, &h); + assert(ret); + + layer = cbuf_surface->u.tex.first_layer; + + x = tex->image_offset[cbuf_surface->u.tex.level][layer].nblocksx; + y = tex->image_offset[cbuf_surface->u.tex.level][layer].nblocksy; + + draw_offset = x | (y << 16); + /* XXX flush only required when the draw_offset changes! */ + OUT_BATCH(MI_FLUSH | INHIBIT_FLUSH_RENDER_CACHE); OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); - OUT_BATCH(0); - OUT_BATCH(0); - OUT_BATCH(((w - 1) & 0xffff) | ((h - 1) << 16)); - OUT_BATCH(0); - OUT_BATCH(0); + OUT_BATCH(DRAW_RECT_DIS_DEPTH_OFS); + OUT_BATCH(draw_offset); + OUT_BATCH((w - 1 + x) | ((h - 1 + y) << 16)); + OUT_BATCH(draw_offset); } #endif diff --git a/src/gallium/drivers/i915/i915_state_sampler.c b/src/gallium/drivers/i915/i915_state_sampler.c index 4667e0b78d4..916cb767536 100644 --- a/src/gallium/drivers/i915/i915_state_sampler.c +++ b/src/gallium/drivers/i915/i915_state_sampler.c @@ -243,6 +243,23 @@ static uint translate_texture_format(enum pipe_format pipeFormat) } } +static inline uint32_t +ms3_tiling_bits(enum i915_winsys_buffer_tile tiling) +{ + uint32_t tiling_bits = 0; + + switch (tiling) { + case I915_TILE_Y: + tiling_bits |= MS3_TILE_WALK_Y; + case I915_TILE_X: + tiling_bits |= MS3_TILED_SURFACE; + case I915_TILE_NONE: + break; + } + + return tiling_bits; +} + static void update_map(struct i915_context *i915, uint unit, const struct i915_texture *tex, @@ -254,7 +271,6 @@ static void update_map(struct i915_context *i915, const uint width = pt->width0, height = pt->height0, depth = pt->depth0; const uint num_levels = pt->last_level; unsigned max_lod = num_levels * 4; - unsigned tiled = MS3_USE_FENCE_REGS; assert(tex); assert(width); @@ -267,17 +283,12 @@ static void update_map(struct i915_context *i915, assert(format); assert(pitch); - if (tex->sw_tiled) { - assert(!((pitch - 1) & pitch)); - tiled = MS3_TILED_SURFACE; - } - /* MS3 state */ state[0] = (((height - 1) << MS3_HEIGHT_SHIFT) | ((width - 1) << MS3_WIDTH_SHIFT) | format - | tiled); + | ms3_tiling_bits(tex->tiling)); /* * XXX When min_filter != mag_filter and there's just one mipmap level, diff --git a/src/gallium/drivers/i915/i915_surface.c b/src/gallium/drivers/i915/i915_surface.c index f40876e708e..becc6e93c2d 100644 --- a/src/gallium/drivers/i915/i915_surface.c +++ b/src/gallium/drivers/i915/i915_surface.c @@ -43,11 +43,10 @@ */ static void i915_surface_copy(struct pipe_context *pipe, - struct pipe_resource *dst, struct pipe_subresource subdst, + struct pipe_resource *dst, unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, - struct pipe_resource *src, struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) + struct pipe_resource *src, unsigned src_level, + const struct pipe_box *src_box) { struct i915_texture *dst_tex = i915_texture(dst); struct i915_texture *src_tex = i915_texture(src); @@ -55,29 +54,17 @@ i915_surface_copy(struct pipe_context *pipe, struct pipe_resource *spt = &src_tex->b.b; unsigned dst_offset, src_offset; /* in bytes */ - if (dst->target == PIPE_TEXTURE_CUBE) { - dst_offset = dst_tex->image_offset[subdst.level][subdst.face]; - } - else if (dst->target == PIPE_TEXTURE_3D) { - dst_offset = dst_tex->image_offset[subdst.level][dstz]; - } - else { - dst_offset = dst_tex->image_offset[subdst.level][0]; - assert(subdst.face == 0); + /* XXX cannot copy 3d regions at this time */ + assert(src_box->depth == 1); + if (dst->target != PIPE_TEXTURE_CUBE && + dst->target != PIPE_TEXTURE_3D) assert(dstz == 0); - } - if (src->target == PIPE_TEXTURE_CUBE) { - src_offset = src_tex->image_offset[subsrc.level][subsrc.face]; - } - else if (src->target == PIPE_TEXTURE_3D) { - src_offset = src_tex->image_offset[subsrc.level][srcz]; - } - else { - src_offset = src_tex->image_offset[subsrc.level][0]; - assert(subsrc.face == 0); - assert(srcz == 0); - } + dst_offset = i915_texture_offset(dst_tex, dst_level, dstz); + if (src->target != PIPE_TEXTURE_CUBE && + src->target != PIPE_TEXTURE_3D) + assert(src_box->z == 0); + src_offset = i915_texture_offset(src_tex, src_level, src_box->z); assert( dst != src ); assert( util_format_get_blocksize(dpt->format) == util_format_get_blocksize(spt->format) ); @@ -90,7 +77,8 @@ i915_surface_copy(struct pipe_context *pipe, util_format_get_blocksize(dpt->format), (unsigned short) src_tex->stride, src_tex->buffer, src_offset, (unsigned short) dst_tex->stride, dst_tex->buffer, dst_offset, - (short) srcx, (short) srcy, (short) dstx, (short) dsty, (short) width, (short) height ); + (short) src_box->x, (short) src_box->y, (short) dstx, (short) dsty, + (short) src_box->width, (short) src_box->height ); } @@ -104,6 +92,7 @@ i915_clear_render_target(struct pipe_context *pipe, struct i915_texture *tex = i915_texture(dst->texture); struct pipe_resource *pt = &tex->b.b; union util_color uc; + unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer); assert(util_format_get_blockwidth(pt->format) == 1); assert(util_format_get_blockheight(pt->format) == 1); @@ -113,7 +102,7 @@ i915_clear_render_target(struct pipe_context *pipe, util_format_get_blocksize(pt->format), XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB, (unsigned short) tex->stride, - tex->buffer, dst->offset, + tex->buffer, offset, (short) dstx, (short) dsty, (short) width, (short) height, uc.ui ); @@ -132,6 +121,7 @@ i915_clear_depth_stencil(struct pipe_context *pipe, struct pipe_resource *pt = &tex->b.b; unsigned packedds; unsigned mask = 0; + unsigned offset = i915_texture_offset(tex, dst->u.tex.level, dst->u.tex.first_layer); assert(util_format_get_blockwidth(pt->format) == 1); assert(util_format_get_blockheight(pt->format) == 1); @@ -151,7 +141,7 @@ i915_clear_depth_stencil(struct pipe_context *pipe, util_format_get_blocksize(pt->format), mask, (unsigned short) tex->stride, - tex->buffer, dst->offset, + tex->buffer, offset, (short) dstx, (short) dsty, (short) width, (short) height, packedds ); @@ -163,42 +153,37 @@ i915_clear_depth_stencil(struct pipe_context *pipe, static struct pipe_surface * -i915_get_tex_surface(struct pipe_screen *screen, - struct pipe_resource *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags) +i915_create_surface(struct pipe_context *ctx, + struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl) { - struct i915_texture *tex = i915_texture(pt); struct pipe_surface *ps; - unsigned offset; /* in bytes */ - if (pt->target == PIPE_TEXTURE_CUBE) { - offset = tex->image_offset[level][face]; - } - else if (pt->target == PIPE_TEXTURE_3D) { - offset = tex->image_offset[level][zslice]; - } - else { - offset = tex->image_offset[level][0]; - assert(face == 0); - assert(zslice == 0); - } + assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); + if (pt->target != PIPE_TEXTURE_CUBE && + pt->target != PIPE_TEXTURE_3D) + assert(surf_tmpl->u.tex.first_layer == 0); ps = CALLOC_STRUCT(pipe_surface); if (ps) { + /* could subclass pipe_surface and store offset as it used to do */ pipe_reference_init(&ps->reference, 1); pipe_resource_reference(&ps->texture, pt); - ps->format = pt->format; - ps->width = u_minify(pt->width0, level); - ps->height = u_minify(pt->height0, level); - ps->offset = offset; - ps->usage = flags; + ps->format = surf_tmpl->format; + ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level); + ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level); + ps->u.tex.level = surf_tmpl->u.tex.level; + ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; + ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; + ps->usage = surf_tmpl->usage; + ps->context = ctx; } return ps; } static void -i915_tex_surface_destroy(struct pipe_surface *surf) +i915_surface_destroy(struct pipe_context *ctx, + struct pipe_surface *surf) { pipe_resource_reference(&surf->texture, NULL); FREE(surf); @@ -211,13 +196,6 @@ i915_init_surface_functions(struct i915_context *i915) i915->base.resource_copy_region = i915_surface_copy; i915->base.clear_render_target = i915_clear_render_target; i915->base.clear_depth_stencil = i915_clear_depth_stencil; -} - -/* No good reason for these to be in the screen. - */ -void -i915_init_screen_surface_functions(struct i915_screen *is) -{ - is->base.get_tex_surface = i915_get_tex_surface; - is->base.tex_surface_destroy = i915_tex_surface_destroy; + i915->base.create_surface = i915_create_surface; + i915->base.surface_destroy = i915_surface_destroy; } diff --git a/src/gallium/drivers/i915/i915_surface.h b/src/gallium/drivers/i915/i915_surface.h index 448106d5662..70b61de80f2 100644 --- a/src/gallium/drivers/i915/i915_surface.h +++ b/src/gallium/drivers/i915/i915_surface.h @@ -32,7 +32,6 @@ struct i915_context; struct i915_screen; void i915_init_surface_functions( struct i915_context *i915 ); -void i915_init_screen_surface_functions( struct i915_screen *is ); #endif /* I915_SCREEN_H */ diff --git a/src/gallium/drivers/i915/i915_winsys.h b/src/gallium/drivers/i915/i915_winsys.h index 5385e403d22..24ea416f015 100644 --- a/src/gallium/drivers/i915/i915_winsys.h +++ b/src/gallium/drivers/i915/i915_winsys.h @@ -53,6 +53,7 @@ enum i915_winsys_buffer_type I915_NEW_VERTEX }; +/* These need to be in sync with the definitions of libdrm-intel! */ enum i915_winsys_buffer_tile { I915_TILE_NONE, @@ -106,7 +107,7 @@ struct i915_winsys { int (*batchbuffer_reloc)(struct i915_winsys_batchbuffer *batch, struct i915_winsys_buffer *reloc, enum i915_winsys_buffer_usage usage, - unsigned offset); + unsigned offset, bool fenced); /** * Flush a bufferbatch. @@ -130,10 +131,24 @@ struct i915_winsys { */ struct i915_winsys_buffer * (*buffer_create)(struct i915_winsys *iws, - unsigned size, unsigned alignment, + unsigned size, enum i915_winsys_buffer_type type); /** + * Create a tiled buffer. + * + * *stride, height are in bytes. The winsys tries to allocate the buffer with + * the tiling mode provide in *tiling. If tiling is no possible, *tiling will + * be set to I915_TILE_NONE. The calculated stride (incorporateing hw/kernel + * requirements) is always returned in *stride. + */ + struct i915_winsys_buffer * + (*buffer_create_tiled)(struct i915_winsys *iws, + unsigned *stride, unsigned height, + enum i915_winsys_buffer_tile *tiling, + enum i915_winsys_buffer_type type); + + /** * Creates a buffer from a handle. * Used to implement pipe_screen::resource_from_handle. * Also provides the stride information needed for the @@ -142,6 +157,7 @@ struct i915_winsys { struct i915_winsys_buffer * (*buffer_from_handle)(struct i915_winsys *iws, struct winsys_handle *whandle, + enum i915_winsys_buffer_tile *tiling, unsigned *stride); /** @@ -154,15 +170,6 @@ struct i915_winsys { unsigned stride); /** - * Fence a buffer with a fence reg. - * Not to be confused with pipe_fence_handle. - */ - int (*buffer_set_fence_reg)(struct i915_winsys *iws, - struct i915_winsys_buffer *buffer, - unsigned stride, - enum i915_winsys_buffer_tile tile); - - /** * Map a buffer. */ void *(*buffer_map)(struct i915_winsys *iws, |