summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/i915simple
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/i915simple')
-rw-r--r--src/gallium/drivers/i915simple/i915_batch.h82
-rw-r--r--src/gallium/drivers/i915simple/i915_blit.c5
-rw-r--r--src/gallium/drivers/i915simple/i915_clear.c1
-rw-r--r--src/gallium/drivers/i915simple/i915_context.c38
-rw-r--r--src/gallium/drivers/i915simple/i915_context.h8
-rw-r--r--src/gallium/drivers/i915simple/i915_debug.c5
-rw-r--r--src/gallium/drivers/i915simple/i915_flush.c2
-rw-r--r--src/gallium/drivers/i915simple/i915_fpc_translate.c10
-rw-r--r--src/gallium/drivers/i915simple/i915_prim_vbuf.c349
-rw-r--r--src/gallium/drivers/i915simple/i915_state.c30
-rw-r--r--src/gallium/drivers/i915simple/i915_state_emit.c25
-rw-r--r--src/gallium/drivers/i915simple/i915_state_immediate.c12
-rw-r--r--src/gallium/drivers/i915simple/i915_state_sampler.c86
-rw-r--r--src/gallium/drivers/i915simple/i915_texture.c372
-rw-r--r--src/gallium/drivers/i915simple/i915_winsys.h22
15 files changed, 768 insertions, 279 deletions
diff --git a/src/gallium/drivers/i915simple/i915_batch.h b/src/gallium/drivers/i915simple/i915_batch.h
index 4ea06ce02b..45bf4f4028 100644
--- a/src/gallium/drivers/i915simple/i915_batch.h
+++ b/src/gallium/drivers/i915simple/i915_batch.h
@@ -29,26 +29,88 @@
#define I915_BATCH_H
#include "i915_winsys.h"
-#include "i915_debug.h"
-#define BATCH_LOCALS
+struct i915_batchbuffer
+{
+ struct pipe_buffer *buffer;
+ struct i915_winsys *winsys;
+
+ unsigned char *map;
+ unsigned char *ptr;
+
+ size_t size;
+ size_t actual_size;
+
+ size_t relocs;
+ size_t max_relocs;
+};
+
+static INLINE boolean
+i915_batchbuffer_check( struct i915_batchbuffer *batch,
+ size_t dwords,
+ size_t relocs )
+{
+ /** TODO JB: Check relocs */
+ return dwords * 4 <= batch->size - (batch->ptr - batch->map);
+}
+
+static INLINE size_t
+i915_batchbuffer_space( struct i915_batchbuffer *batch )
+{
+ return batch->size - (batch->ptr - batch->map);
+}
+
+static INLINE void
+i915_batchbuffer_dword( struct i915_batchbuffer *batch,
+ unsigned dword )
+{
+ if (i915_batchbuffer_space(batch) < 4)
+ return;
+
+ *(unsigned *)batch->ptr = dword;
+ batch->ptr += 4;
+}
+
+static INLINE void
+i915_batchbuffer_write( struct i915_batchbuffer *batch,
+ void *data,
+ size_t size )
+{
+ if (i915_batchbuffer_space(batch) < size)
+ return;
+
+ memcpy(data, batch->ptr, size);
+ batch->ptr += size;
+}
+
+static INLINE void
+i915_batchbuffer_reloc( struct i915_batchbuffer *batch,
+ struct pipe_buffer *buffer,
+ size_t flags,
+ size_t offset )
+{
+ batch->winsys->batch_reloc( batch->winsys, buffer, flags, offset );
+}
+
+static INLINE void
+i915_batchbuffer_flush( struct i915_batchbuffer *batch,
+ struct pipe_fence_handle **fence )
+{
+ batch->winsys->batch_flush( batch->winsys, fence );
+}
#define BEGIN_BATCH( dwords, relocs ) \
- (i915->batch_start = i915->winsys->batch_start( i915->winsys, dwords, relocs ))
+ (i915_batchbuffer_check( i915->batch, dwords, relocs ))
#define OUT_BATCH( dword ) \
- i915->winsys->batch_dword( i915->winsys, dword )
+ i915_batchbuffer_dword( i915->batch, dword )
#define OUT_RELOC( buf, flags, delta ) \
- i915->winsys->batch_reloc( i915->winsys, buf, flags, delta )
-
-#define ADVANCE_BATCH()
+ i915_batchbuffer_reloc( i915->batch, buf, flags, delta )
#define FLUSH_BATCH(fence) do { \
- if (0) i915_dump_batchbuffer( i915 ); \
i915->winsys->batch_flush( i915->winsys, fence ); \
- i915->batch_start = NULL; \
i915->hardware_dirty = ~0; \
} while (0)
-#endif
+#endif
diff --git a/src/gallium/drivers/i915simple/i915_blit.c b/src/gallium/drivers/i915simple/i915_blit.c
index 24449e3fb3..22f91fab92 100644
--- a/src/gallium/drivers/i915simple/i915_blit.c
+++ b/src/gallium/drivers/i915simple/i915_blit.c
@@ -31,6 +31,7 @@
#include "i915_blit.h"
#include "i915_reg.h"
#include "i915_batch.h"
+#include "i915_debug.h"
#define FILE_DEBUG_FLAG DEBUG_BLIT
@@ -45,7 +46,6 @@ i915_fill_blit(struct i915_context *i915,
unsigned color)
{
unsigned BR13, CMD;
- BATCH_LOCALS;
dst_pitch *= (short) cpp;
@@ -79,7 +79,6 @@ i915_fill_blit(struct i915_context *i915,
OUT_BATCH(((y + h) << 16) | (x + w));
OUT_RELOC( dst_buffer, I915_BUFFER_ACCESS_WRITE, dst_offset);
OUT_BATCH(color);
- ADVANCE_BATCH();
}
@@ -100,7 +99,6 @@ i915_copy_blit( struct i915_context *i915,
unsigned CMD, BR13;
int dst_y2 = dst_y + h;
int dst_x2 = dst_x + w;
- BATCH_LOCALS;
I915_DBG(i915,
@@ -156,7 +154,6 @@ i915_copy_blit( struct i915_context *i915,
OUT_BATCH((src_y << 16) | src_x);
OUT_BATCH(((int) src_pitch & 0xffff));
OUT_RELOC(src_buffer, I915_BUFFER_ACCESS_READ, src_offset);
- ADVANCE_BATCH();
}
diff --git a/src/gallium/drivers/i915simple/i915_clear.c b/src/gallium/drivers/i915simple/i915_clear.c
index cde69daacc..8a2d3ca43f 100644
--- a/src/gallium/drivers/i915simple/i915_clear.c
+++ b/src/gallium/drivers/i915simple/i915_clear.c
@@ -44,4 +44,5 @@ i915_clear(struct pipe_context *pipe, struct pipe_surface *ps,
unsigned clearValue)
{
pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue);
+ ps->status = PIPE_SURFACE_STATUS_DEFINED;
}
diff --git a/src/gallium/drivers/i915simple/i915_context.c b/src/gallium/drivers/i915simple/i915_context.c
index 4bef21619c..4c01b8d5b1 100644
--- a/src/gallium/drivers/i915simple/i915_context.c
+++ b/src/gallium/drivers/i915simple/i915_context.c
@@ -50,10 +50,12 @@ static void i915_destroy( struct pipe_context *pipe )
static boolean
-i915_draw_elements( struct pipe_context *pipe,
- struct pipe_buffer *indexBuffer,
- unsigned indexSize,
- unsigned prim, unsigned start, unsigned count)
+i915_draw_range_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned min_index,
+ unsigned max_index,
+ unsigned prim, unsigned start, unsigned count)
{
struct i915_context *i915 = i915_context( pipe );
struct draw_context *draw = i915->draw;
@@ -77,7 +79,10 @@ i915_draw_elements( struct pipe_context *pipe,
void *mapped_indexes
= pipe->winsys->buffer_map(pipe->winsys, indexBuffer,
PIPE_BUFFER_USAGE_CPU_READ);
- draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes);
+ draw_set_mapped_element_buffer_range(draw, indexSize,
+ min_index,
+ max_index,
+ mapped_indexes);
}
else {
/* no index/element buffer */
@@ -86,7 +91,9 @@ i915_draw_elements( struct pipe_context *pipe,
draw_set_mapped_constant_buffer(draw,
- i915->current.constants[PIPE_SHADER_VERTEX]);
+ i915->current.constants[PIPE_SHADER_VERTEX],
+ ( i915->current.num_user_constants[PIPE_SHADER_VERTEX] *
+ 4 * sizeof(float) ));
/* draw! */
draw_arrays(i915->draw, prim, start, count);
@@ -100,12 +107,23 @@ i915_draw_elements( struct pipe_context *pipe,
}
if (indexBuffer) {
pipe->winsys->buffer_unmap(pipe->winsys, indexBuffer);
- draw_set_mapped_element_buffer(draw, 0, NULL);
+ draw_set_mapped_element_buffer_range(draw, 0, start, start + count - 1, NULL);
}
return TRUE;
}
+static boolean
+i915_draw_elements( struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned prim, unsigned start, unsigned count)
+{
+ return i915_draw_range_elements( pipe, indexBuffer,
+ indexSize,
+ 0, 0xffffffff,
+ prim, start, count );
+}
static boolean i915_draw_arrays( struct pipe_context *pipe,
unsigned prim, unsigned start, unsigned count)
@@ -136,13 +154,14 @@ struct pipe_context *i915_create_context( struct pipe_screen *screen,
i915->pipe.draw_arrays = i915_draw_arrays;
i915->pipe.draw_elements = i915_draw_elements;
+ i915->pipe.draw_range_elements = i915_draw_range_elements;
/*
* Create drawing context and plug our rendering stage into it.
*/
i915->draw = draw_create();
assert(i915->draw);
- if (!GETENV("I915_NO_VBUF")) {
+ if (!debug_get_bool_option("I915_NO_VBUF", FALSE)) {
draw_set_rasterize_stage(i915->draw, i915_draw_vbuf_stage(i915));
}
else {
@@ -162,7 +181,8 @@ struct pipe_context *i915_create_context( struct pipe_screen *screen,
/* Batch stream debugging is a bit hacked up at the moment:
*/
- i915->batch_start = NULL;
+ i915->batch = i915_winsys->batch_get(i915_winsys);
+ i915->batch->winsys = i915_winsys;
return &i915->pipe;
}
diff --git a/src/gallium/drivers/i915simple/i915_context.h b/src/gallium/drivers/i915simple/i915_context.h
index 53fc5ed079..892a88fd2c 100644
--- a/src/gallium/drivers/i915simple/i915_context.h
+++ b/src/gallium/drivers/i915simple/i915_context.h
@@ -178,6 +178,8 @@ struct i915_rasterizer_state {
struct i915_sampler_state {
unsigned state[3];
const struct pipe_sampler_state *templ;
+ unsigned minlod;
+ unsigned maxlod;
};
@@ -209,6 +211,8 @@ struct i915_texture {
struct pipe_buffer *buffer;
};
+struct i915_batchbuffer;
+
struct i915_context
{
struct pipe_context pipe;
@@ -241,10 +245,12 @@ struct i915_context
unsigned num_vertex_elements;
unsigned num_vertex_buffers;
- unsigned *batch_start;
+ struct i915_batchbuffer *batch;
/** Vertex buffer */
struct pipe_buffer *vbo;
+ size_t vbo_offset;
+ unsigned vbo_flushed;
struct i915_state current;
unsigned hardware_dirty;
diff --git a/src/gallium/drivers/i915simple/i915_debug.c b/src/gallium/drivers/i915simple/i915_debug.c
index 9b9111167f..5e26d1b905 100644
--- a/src/gallium/drivers/i915simple/i915_debug.c
+++ b/src/gallium/drivers/i915simple/i915_debug.c
@@ -861,8 +861,9 @@ void
i915_dump_batchbuffer( struct i915_context *i915 )
{
struct debug_stream stream;
- unsigned *start = i915->batch_start;
- unsigned *end = i915->winsys->batch_start( i915->winsys, 0, 0 );
+ /* TODO fix me */
+ unsigned *start = 0;/*i915->batch_start;*/
+ unsigned *end = 0;/*i915->winsys->batch_start( i915->winsys, 0, 0 );*/
unsigned long bytes = (unsigned long) (end - start) * 4;
boolean done = FALSE;
diff --git a/src/gallium/drivers/i915simple/i915_flush.c b/src/gallium/drivers/i915simple/i915_flush.c
index 7d23e6b6b9..472e0ab774 100644
--- a/src/gallium/drivers/i915simple/i915_flush.c
+++ b/src/gallium/drivers/i915simple/i915_flush.c
@@ -62,12 +62,12 @@ static void i915_flush( struct pipe_context *pipe,
assert(BEGIN_BATCH(1, 0));
}
OUT_BATCH( flush );
- ADVANCE_BATCH();
}
/* If there are no flags, just flush pending commands to hardware:
*/
FLUSH_BATCH(fence);
+ i915->vbo_flushed = 1;
}
diff --git a/src/gallium/drivers/i915simple/i915_fpc_translate.c b/src/gallium/drivers/i915simple/i915_fpc_translate.c
index 3ccf74c72c..23cd909337 100644
--- a/src/gallium/drivers/i915simple/i915_fpc_translate.c
+++ b/src/gallium/drivers/i915simple/i915_fpc_translate.c
@@ -676,7 +676,7 @@ i915_translate_instruction(struct i915_fp_compile *p,
break;
case TGSI_OPCODE_MOV:
- /* aka TGSI_OPCODE_SWZ */
+ case TGSI_OPCODE_SWZ:
emit_simple_arith(p, inst, A0_MOV, 1);
break;
@@ -943,8 +943,8 @@ i915_translate_instructions(struct i915_fp_compile *p,
if (parse.FullToken.FullDeclaration.Declaration.File
== TGSI_FILE_CONSTANT) {
uint i;
- for (i = parse.FullToken.FullDeclaration.u.DeclarationRange.First;
- i <= parse.FullToken.FullDeclaration.u.DeclarationRange.Last;
+ for (i = parse.FullToken.FullDeclaration.DeclarationRange.First;
+ i <= parse.FullToken.FullDeclaration.DeclarationRange.Last;
i++) {
assert(ifs->constant_flags[i] == 0x0);
ifs->constant_flags[i] = I915_CONSTFLAG_USER;
@@ -954,8 +954,8 @@ i915_translate_instructions(struct i915_fp_compile *p,
else if (parse.FullToken.FullDeclaration.Declaration.File
== TGSI_FILE_TEMPORARY) {
uint i;
- for (i = parse.FullToken.FullDeclaration.u.DeclarationRange.First;
- i <= parse.FullToken.FullDeclaration.u.DeclarationRange.Last;
+ for (i = parse.FullToken.FullDeclaration.DeclarationRange.First;
+ i <= parse.FullToken.FullDeclaration.DeclarationRange.Last;
i++) {
assert(i < I915_MAX_TEMPORARY);
/* XXX just use shader->info->file_mask[TGSI_FILE_TEMPORARY] */
diff --git a/src/gallium/drivers/i915simple/i915_prim_vbuf.c b/src/gallium/drivers/i915simple/i915_prim_vbuf.c
index 7fb2adbb53..aef3682bbf 100644
--- a/src/gallium/drivers/i915simple/i915_prim_vbuf.c
+++ b/src/gallium/drivers/i915simple/i915_prim_vbuf.c
@@ -38,6 +38,7 @@
*/
+#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
#include "pipe/p_debug.h"
#include "pipe/p_util.h"
@@ -62,8 +63,21 @@ struct i915_vbuf_render {
/** Vertex size in bytes */
unsigned vertex_size;
+ /** Software primitive */
+ unsigned prim;
+
/** Hardware primitive */
unsigned hwprim;
+
+ /** Genereate a vertex list */
+ unsigned fallback;
+
+ /* Stuff for the vbo */
+ struct pipe_buffer *vbo;
+ size_t vbo_size;
+ size_t vbo_offset;
+ void *vbo_ptr;
+ size_t vbo_alloc_size;
};
@@ -95,8 +109,8 @@ i915_vbuf_render_get_vertex_info( struct vbuf_render *render )
static void *
i915_vbuf_render_allocate_vertices( struct vbuf_render *render,
- ushort vertex_size,
- ushort nr_vertices )
+ ushort vertex_size,
+ ushort nr_vertices )
{
struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
struct i915_context *i915 = i915_render->i915;
@@ -105,14 +119,31 @@ i915_vbuf_render_allocate_vertices( struct vbuf_render *render,
/* FIXME: handle failure */
assert(!i915->vbo);
- i915->vbo = winsys->buffer_create(winsys, 64, I915_BUFFER_USAGE_LIT_VERTEX,
- size);
-
+
+ if (i915_render->vbo_size > size + i915_render->vbo_offset && !i915->vbo_flushed) {
+ } else {
+ i915->vbo_flushed = 0;
+ pipe_buffer_reference(winsys, &i915_render->vbo, NULL);
+ }
+
+ if (!i915_render->vbo) {
+ i915_render->vbo_size = MAX2(size, i915_render->vbo_alloc_size);
+ i915_render->vbo_offset = 0;
+ i915_render->vbo = winsys->buffer_create(winsys,
+ 64,
+ I915_BUFFER_USAGE_LIT_VERTEX,
+ i915_render->vbo_size);
+ i915_render->vbo_ptr = winsys->buffer_map(winsys,
+ i915_render->vbo,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ winsys->buffer_unmap(winsys, i915_render->vbo);
+ }
+
+ i915->vbo = i915_render->vbo;
+ i915->vbo_offset = i915_render->vbo_offset;
i915->dirty |= I915_NEW_VBO;
-
- return winsys->buffer_map(winsys,
- i915->vbo,
- PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ return (unsigned char *)i915_render->vbo_ptr + i915->vbo_offset;
}
@@ -121,18 +152,51 @@ i915_vbuf_render_set_primitive( struct vbuf_render *render,
unsigned prim )
{
struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
-
+ i915_render->prim = prim;
+
switch(prim) {
case PIPE_PRIM_POINTS:
i915_render->hwprim = PRIM3D_POINTLIST;
+ i915_render->fallback = 0;
return TRUE;
case PIPE_PRIM_LINES:
i915_render->hwprim = PRIM3D_LINELIST;
+ i915_render->fallback = 0;
+ return TRUE;
+ case PIPE_PRIM_LINE_LOOP:
+ i915_render->hwprim = PRIM3D_LINELIST;
+ i915_render->fallback = PIPE_PRIM_LINE_LOOP;
+ return TRUE;
+ case PIPE_PRIM_LINE_STRIP:
+ i915_render->hwprim = PRIM3D_LINESTRIP;
+ i915_render->fallback = 0;
return TRUE;
case PIPE_PRIM_TRIANGLES:
i915_render->hwprim = PRIM3D_TRILIST;
+ i915_render->fallback = 0;
+ return TRUE;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ i915_render->hwprim = PRIM3D_TRISTRIP;
+ i915_render->fallback = 0;
+ return TRUE;
+ case PIPE_PRIM_TRIANGLE_FAN:
+ i915_render->hwprim = PRIM3D_TRIFAN;
+ i915_render->fallback = 0;
+ return TRUE;
+ case PIPE_PRIM_QUADS:
+ i915_render->hwprim = PRIM3D_TRILIST;
+ i915_render->fallback = PIPE_PRIM_QUADS;
+ return TRUE;
+ case PIPE_PRIM_QUAD_STRIP:
+ i915_render->hwprim = PRIM3D_TRILIST;
+ i915_render->fallback = PIPE_PRIM_QUAD_STRIP;
+ return TRUE;
+ case PIPE_PRIM_POLYGON:
+ i915_render->hwprim = PRIM3D_POLY;
+ i915_render->fallback = 0;
return TRUE;
default:
+ assert((int)"Error unkown primtive type" & 0);
/* Actually, can handle a lot more just fine... Fixme.
*/
return FALSE;
@@ -140,6 +204,205 @@ i915_vbuf_render_set_primitive( struct vbuf_render *render,
}
+
+/**
+ * Used for fallbacks in draw_arrays
+ */
+static void
+draw_arrays_generate_indices( struct vbuf_render *render,
+ unsigned start, uint nr,
+ unsigned type )
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+ unsigned i;
+ unsigned end = start + nr;
+ switch(type) {
+ case 0:
+ for (i = start; i+1 < end; i += 2)
+ OUT_BATCH( (i+0) | (i+1) << 16 );
+ if (i < end)
+ OUT_BATCH( i );
+ break;
+ case PIPE_PRIM_LINE_LOOP:
+ if (nr >= 2) {
+ for (i = start + 1; i < end; i++)
+ OUT_BATCH( (i-0) | (i+0) << 16 );
+ OUT_BATCH( (i-0) | ( start) << 16 );
+ }
+ break;
+ case PIPE_PRIM_QUADS:
+ for (i = start; i + 3 < end; i += 4) {
+ OUT_BATCH( (i+0) | (i+1) << 16 );
+ OUT_BATCH( (i+3) | (i+1) << 16 );
+ OUT_BATCH( (i+2) | (i+3) << 16 );
+ }
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ for (i = start; i + 3 < end; i += 2) {
+ OUT_BATCH( (i+0) | (i+1) << 16 );
+ OUT_BATCH( (i+3) | (i+2) << 16 );
+ OUT_BATCH( (i+0) | (i+3) << 16 );
+ }
+ break;
+ default:
+ assert(0);
+ }
+}
+
+static unsigned
+draw_arrays_calc_nr_indices( uint nr, unsigned type )
+{
+ switch (type) {
+ case 0:
+ return nr;
+ case PIPE_PRIM_LINE_LOOP:
+ if (nr >= 2)
+ return nr * 2;
+ else
+ return 0;
+ case PIPE_PRIM_QUADS:
+ return (nr / 4) * 6;
+ case PIPE_PRIM_QUAD_STRIP:
+ return ((nr - 2) / 2) * 6;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+static void
+draw_arrays_fallback( struct vbuf_render *render,
+ unsigned start,
+ uint nr )
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+ unsigned nr_indices;
+
+ if (i915->dirty)
+ i915_update_derived( i915 );
+
+ if (i915->hardware_dirty)
+ i915_emit_hardware_state( i915 );
+
+ nr_indices = draw_arrays_calc_nr_indices( nr, i915_render->fallback );
+ if (!nr_indices)
+ return;
+
+ if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) {
+ FLUSH_BATCH(NULL);
+
+ /* Make sure state is re-emitted after a flush:
+ */
+ i915_update_derived( i915 );
+ i915_emit_hardware_state( i915 );
+ i915->vbo_flushed = 1;
+
+ if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) {
+ assert(0);
+ goto out;
+ }
+ }
+ OUT_BATCH( _3DPRIMITIVE |
+ PRIM_INDIRECT |
+ i915_render->hwprim |
+ PRIM_INDIRECT_ELTS |
+ nr_indices );
+
+ draw_arrays_generate_indices( render, start, nr, i915_render->fallback );
+
+out:
+ return;
+}
+
+static void
+i915_vbuf_render_draw_arrays( struct vbuf_render *render,
+ unsigned start,
+ uint nr )
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+
+ if (i915_render->fallback) {
+ draw_arrays_fallback( render, start, nr );
+ return;
+ }
+
+ /* JB: TODO submit direct cmds */
+ draw_arrays_fallback( render, start, nr );
+}
+
+/**
+ * Used for normal and fallback emitting of indices
+ * If type is zero normal operation assumed.
+ */
+static void
+draw_generate_indices( struct vbuf_render *render,
+ const ushort *indices,
+ uint nr_indices,
+ unsigned type )
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+ unsigned i;
+
+ switch(type) {
+ case 0:
+ for (i = 0; i + 1 < nr_indices; i += 2) {
+ OUT_BATCH( indices[i] | indices[i+1] << 16 );
+ }
+ if (i < nr_indices) {
+ OUT_BATCH( indices[i] );
+ }
+ break;
+ case PIPE_PRIM_LINE_LOOP:
+ if (nr_indices >= 2) {
+ for (i = 1; i < nr_indices; i++)
+ OUT_BATCH( indices[i-1] | indices[i] << 16 );
+ OUT_BATCH( indices[i-1] | indices[0] << 16 );
+ }
+ break;
+ case PIPE_PRIM_QUADS:
+ for (i = 0; i + 3 < nr_indices; i += 4) {
+ OUT_BATCH( indices[i+0] | indices[i+1] << 16 );
+ OUT_BATCH( indices[i+3] | indices[i+1] << 16 );
+ OUT_BATCH( indices[i+2] | indices[i+3] << 16 );
+ }
+ break;
+ case PIPE_PRIM_QUAD_STRIP:
+ for (i = 0; i + 3 < nr_indices; i += 2) {
+ OUT_BATCH( indices[i+0] | indices[i+1] << 16 );
+ OUT_BATCH( indices[i+3] | indices[i+2] << 16 );
+ OUT_BATCH( indices[i+0] | indices[i+3] << 16 );
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+}
+
+static unsigned
+draw_calc_nr_indices( uint nr_indices, unsigned type )
+{
+ switch (type) {
+ case 0:
+ return nr_indices;
+ case PIPE_PRIM_LINE_LOOP:
+ if (nr_indices >= 2)
+ return nr_indices * 2;
+ else
+ return 0;
+ case PIPE_PRIM_QUADS:
+ return (nr_indices / 4) * 6;
+ case PIPE_PRIM_QUAD_STRIP:
+ return ((nr_indices - 2) / 2) * 6;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
static void
i915_vbuf_render_draw( struct vbuf_render *render,
const ushort *indices,
@@ -147,13 +410,14 @@ i915_vbuf_render_draw( struct vbuf_render *render,
{
struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
struct i915_context *i915 = i915_render->i915;
- unsigned i;
+ unsigned save_nr_indices;
- assert(nr_indices);
+ save_nr_indices = nr_indices;
+
+ nr_indices = draw_calc_nr_indices( nr_indices, i915_render->fallback );
+ if (!nr_indices)
+ return;
- /* this seems to be bogus, since we validate state right after this */
- /*assert((i915->dirty & ~I915_NEW_VBO) == 0);*/
-
if (i915->dirty)
i915_update_derived( i915 );
@@ -167,25 +431,26 @@ i915_vbuf_render_draw( struct vbuf_render *render,
*/
i915_update_derived( i915 );
i915_emit_hardware_state( i915 );
+ i915->vbo_flushed = 1;
if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) {
assert(0);
- return;
+ goto out;
}
}
OUT_BATCH( _3DPRIMITIVE |
- PRIM_INDIRECT |
- i915_render->hwprim |
- PRIM_INDIRECT_ELTS |
- nr_indices );
- for (i = 0; i + 1 < nr_indices; i += 2) {
- OUT_BATCH( indices[i] |
- (indices[i + 1] << 16) );
- }
- if (i < nr_indices) {
- OUT_BATCH( indices[i] );
- }
+ PRIM_INDIRECT |
+ i915_render->hwprim |
+ PRIM_INDIRECT_ELTS |
+ nr_indices );
+ draw_generate_indices( render,
+ indices,
+ save_nr_indices,
+ i915_render->fallback );
+
+out:
+ return;
}
@@ -197,11 +462,13 @@ i915_vbuf_render_release_vertices( struct vbuf_render *render,
{
struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
struct i915_context *i915 = i915_render->i915;
- struct pipe_winsys *winsys = i915->pipe.winsys;
+ size_t size = (size_t)vertex_size * (size_t)vertices_used;
assert(i915->vbo);
- winsys->buffer_unmap(winsys, i915->vbo);
- pipe_buffer_reference(winsys, &i915->vbo, NULL);
+
+ i915_render->vbo_offset += size;
+ i915->vbo = NULL;
+ i915->dirty |= I915_NEW_VBO;
}
@@ -220,6 +487,7 @@ static struct vbuf_render *
i915_vbuf_render_create( struct i915_context *i915 )
{
struct i915_vbuf_render *i915_render = CALLOC_STRUCT(i915_vbuf_render);
+ struct pipe_winsys *winsys = i915->pipe.winsys;
i915_render->i915 = i915;
@@ -229,14 +497,27 @@ i915_vbuf_render_create( struct i915_context *i915 )
* batch buffer.
*/
i915_render->base.max_indices = 16*1024;
-
+
i915_render->base.get_vertex_info = i915_vbuf_render_get_vertex_info;
i915_render->base.allocate_vertices = i915_vbuf_render_allocate_vertices;
i915_render->base.set_primitive = i915_vbuf_render_set_primitive;
i915_render->base.draw = i915_vbuf_render_draw;
+ i915_render->base.draw_arrays = i915_vbuf_render_draw_arrays;
i915_render->base.release_vertices = i915_vbuf_render_release_vertices;
i915_render->base.destroy = i915_vbuf_render_destroy;
-
+
+ i915_render->vbo_alloc_size = 128 * 4096;
+ i915_render->vbo_size = i915_render->vbo_alloc_size;
+ i915_render->vbo_offset = 0;
+ i915_render->vbo = winsys->buffer_create(winsys,
+ 64,
+ I915_BUFFER_USAGE_LIT_VERTEX,
+ i915_render->vbo_size);
+ i915_render->vbo_ptr = winsys->buffer_map(winsys,
+ i915_render->vbo,
+ PIPE_BUFFER_USAGE_CPU_WRITE);
+ winsys->buffer_unmap(winsys, i915_render->vbo);
+
return &i915_render->base;
}
@@ -258,6 +539,8 @@ struct draw_stage *i915_draw_vbuf_stage( struct i915_context *i915 )
render->destroy(render);
return NULL;
}
-
+ /** TODO JB: this shouldn't be here */
+ draw_set_render(i915->draw, render);
+
return stage;
}
diff --git a/src/gallium/drivers/i915simple/i915_state.c b/src/gallium/drivers/i915simple/i915_state.c
index e6c4671700..dbb33f2695 100644
--- a/src/gallium/drivers/i915simple/i915_state.c
+++ b/src/gallium/drivers/i915simple/i915_state.c
@@ -41,7 +41,6 @@
#include "i915_state_inlines.h"
#include "i915_fpc.h"
-
/* The i915 (and related graphics cores) do not support GL_CLAMP. The
* Intel drivers for "other operating systems" implement GL_CLAMP as
* GL_CLAMP_TO_EDGE, so the same is done here.
@@ -178,6 +177,7 @@ static void i915_bind_blend_state(struct pipe_context *pipe,
void *blend)
{
struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
i915->blend = (struct i915_blend_state*)blend;
@@ -194,6 +194,7 @@ static void i915_set_blend_color( struct pipe_context *pipe,
const struct pipe_blend_color *blend_color )
{
struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
i915->blend_color = *blend_color;
@@ -250,11 +251,17 @@ i915_create_sampler_state(struct pipe_context *pipe,
if (sampler->normalized_coords)
cso->state[1] |= SS3_NORMALIZED_COORDS;
- if (0) /* XXX not tested yet */
{
int minlod = (int) (16.0 * sampler->min_lod);
+ int maxlod = (int) (16.0 * sampler->max_lod);
minlod = CLAMP(minlod, 0, 16 * 11);
- cso->state[1] |= (minlod << SS3_MIN_LOD_SHIFT);
+ maxlod = CLAMP(maxlod, 0, 16 * 11);
+
+ if (minlod > maxlod)
+ maxlod = minlod;
+
+ cso->minlod = minlod;
+ cso->maxlod = maxlod;
}
{
@@ -280,6 +287,8 @@ static void i915_bind_sampler_states(struct pipe_context *pipe,
!memcmp(i915->sampler, sampler, num * sizeof(void *)))
return;
+ draw_flush(i915->draw);
+
for (i = 0; i < num; ++i)
i915->sampler[i] = sampler[i];
for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
@@ -398,6 +407,7 @@ static void i915_bind_depth_stencil_state(struct pipe_context *pipe,
void *depth_stencil)
{
struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
i915->depth_stencil = (const struct i915_depth_stencil_state *)depth_stencil;
@@ -415,6 +425,7 @@ static void i915_set_scissor_state( struct pipe_context *pipe,
const struct pipe_scissor_state *scissor )
{
struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
memcpy( &i915->scissor, scissor, sizeof(*scissor) );
i915->dirty |= I915_NEW_SCISSOR;
@@ -451,6 +462,7 @@ static void
i915_bind_fs_state(struct pipe_context *pipe, void *shader)
{
struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
i915->fs = (struct i915_fragment_shader*) shader;
@@ -506,6 +518,7 @@ static void i915_set_constant_buffer(struct pipe_context *pipe,
{
struct i915_context *i915 = i915_context(pipe);
struct pipe_winsys *ws = pipe->winsys;
+ draw_flush(i915->draw);
assert(shader < PIPE_SHADER_TYPES);
assert(index == 0);
@@ -574,6 +587,7 @@ static void i915_set_framebuffer_state(struct pipe_context *pipe,
const struct pipe_framebuffer_state *fb)
{
struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
i915->framebuffer = *fb; /* struct copy */
@@ -586,6 +600,7 @@ static void i915_set_clip_state( struct pipe_context *pipe,
const struct pipe_clip_state *clip )
{
struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
draw_set_clip_state(i915->draw, clip);
@@ -698,6 +713,10 @@ static void i915_set_vertex_buffers(struct pipe_context *pipe,
const struct pipe_vertex_buffer *buffers)
{
struct i915_context *i915 = i915_context(pipe);
+ /* Because we change state before the draw_set_vertex_buffers call
+ * we need a flush here, just to be sure.
+ */
+ draw_flush(i915->draw);
memcpy(i915->vertex_buffer, buffers, count * sizeof(buffers[0]));
i915->num_vertex_buffers = count;
@@ -711,6 +730,11 @@ static void i915_set_vertex_elements(struct pipe_context *pipe,
const struct pipe_vertex_element *elements)
{
struct i915_context *i915 = i915_context(pipe);
+ /* Because we change state before the draw_set_vertex_buffers call
+ * we need a flush here, just to be sure.
+ */
+ draw_flush(i915->draw);
+
i915->num_vertex_elements = count;
/* pass-through to draw module */
draw_set_vertex_elements(i915->draw, count, elements);
diff --git a/src/gallium/drivers/i915simple/i915_state_emit.c b/src/gallium/drivers/i915simple/i915_state_emit.c
index 6f947d4346..bc801a82f0 100644
--- a/src/gallium/drivers/i915simple/i915_state_emit.c
+++ b/src/gallium/drivers/i915simple/i915_state_emit.c
@@ -211,33 +211,43 @@ i915_emit_hardware_state(struct i915_context *i915 )
struct pipe_surface *depth_surface = i915->framebuffer.zsbuf;
if (cbuf_surface) {
- unsigned pitch = (cbuf_surface->pitch * cbuf_surface->cpp);
+ unsigned cpitch = (cbuf_surface->pitch * cbuf_surface->cpp);
+ unsigned ctile = BUF_3D_USE_FENCE;
+#if 0
+ if (!((cpitch - 1) & cpitch) && cpitch >= 512)
+ ctile = BUF_3D_TILED_SURFACE;
+#endif
OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
OUT_BATCH(BUF_3D_ID_COLOR_BACK |
- BUF_3D_PITCH(pitch) | /* pitch in bytes */
- BUF_3D_USE_FENCE);
+ BUF_3D_PITCH(cpitch) | /* pitch in bytes */
+ ctile);
OUT_RELOC(cbuf_surface->buffer,
I915_BUFFER_ACCESS_WRITE,
- 0);
+ cbuf_surface->offset);
}
/* What happens if no zbuf??
*/
if (depth_surface) {
unsigned zpitch = (depth_surface->pitch * depth_surface->cpp);
-
+ unsigned ztile = BUF_3D_USE_FENCE;
+#if 0
+ if (!((zpitch - 1) & zpitch) && zpitch >= 512)
+ ztile = BUF_3D_TILED_SURFACE;
+#endif
+
OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
OUT_BATCH(BUF_3D_ID_DEPTH |
BUF_3D_PITCH(zpitch) | /* pitch in bytes */
- BUF_3D_USE_FENCE);
+ ztile);
OUT_RELOC(depth_surface->buffer,
I915_BUFFER_ACCESS_WRITE,
- 0);
+ depth_surface->offset);
}
{
@@ -376,6 +386,7 @@ i915_emit_hardware_state(struct i915_context *i915 )
{
uint w, h;
boolean k = framebuffer_size(&i915->framebuffer, &w, &h);
+ (void)k;
assert(k);
OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
diff --git a/src/gallium/drivers/i915simple/i915_state_immediate.c b/src/gallium/drivers/i915simple/i915_state_immediate.c
index dfbbcab624..2501f2d7cb 100644
--- a/src/gallium/drivers/i915simple/i915_state_immediate.c
+++ b/src/gallium/drivers/i915simple/i915_state_immediate.c
@@ -54,7 +54,7 @@ static void upload_S0S1(struct i915_context *i915)
/* INTEL_NEW_VBO */
/* TODO: re-use vertex buffers here? */
- LIS0 = 0;
+ LIS0 = i915->vbo_offset;
/* INTEL_NEW_VERTEX_SIZE -- do this where the vertex size is calculated!
*/
@@ -156,8 +156,12 @@ const struct i915_tracked_state i915_upload_S5 = {
*/
static void upload_S6( struct i915_context *i915 )
{
- unsigned LIS6 = (S6_COLOR_WRITE_ENABLE |
- (2 << S6_TRISTRIP_PV_SHIFT));
+ unsigned LIS6 = (2 << S6_TRISTRIP_PV_SHIFT);
+
+ /* I915_NEW_FRAMEBUFFER
+ */
+ if (i915->framebuffer.cbufs[0])
+ LIS6 |= S6_COLOR_WRITE_ENABLE;
/* I915_NEW_BLEND
*/
@@ -174,7 +178,7 @@ static void upload_S6( struct i915_context *i915 )
}
const struct i915_tracked_state i915_upload_S6 = {
- I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL,
+ I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL | I915_NEW_FRAMEBUFFER,
upload_S6
};
diff --git a/src/gallium/drivers/i915simple/i915_state_sampler.c b/src/gallium/drivers/i915simple/i915_state_sampler.c
index 982eec4a1b..24440843f3 100644
--- a/src/gallium/drivers/i915simple/i915_state_sampler.c
+++ b/src/gallium/drivers/i915simple/i915_state_sampler.c
@@ -35,6 +35,35 @@
#include "i915_state.h"
+/*
+ * A note about min_lod & max_lod.
+ *
+ * There is a circular dependancy between the sampler state
+ * and the map state to be submitted to hw.
+ *
+ * Two condition must be meet:
+ * min_lod =< max_lod == true
+ * max_lod =< last_level == true
+ *
+ *
+ * This is all fine and dandy if it where for the fact that max_lod
+ * is set on the map state instead of the sampler state. That is
+ * the max_lod we submit on map is:
+ * max_lod = MIN2(last_level, max_lod);
+ *
+ * So we need to update the map state when we change samplers and
+ * we need to be change the sampler state when map state is changed.
+ * The first part is done by calling i915_update_texture in
+ * i915_update_samplers and the second part is done else where in
+ * code tracking the state changes.
+ */
+
+static void
+i915_update_texture(struct i915_context *i915,
+ uint unit,
+ const struct i915_texture *tex,
+ const struct i915_sampler_state *sampler,
+ uint state[6]);
/**
* Compute i915 texture sampling state.
*
@@ -50,6 +79,7 @@ static void update_sampler(struct i915_context *i915,
unsigned state[3] )
{
const struct pipe_texture *pt = &tex->base;
+ unsigned minlod, lastlod;
/* Need to do this after updating the maps, which call the
* intel_finalize_mipmap_tree and hence can update firstLevel:
@@ -95,6 +125,15 @@ static void update_sampler(struct i915_context *i915,
}
#endif
+ /* See note at the top of file */
+ minlod = sampler->minlod;
+ lastlod = pt->last_level << 4;
+
+ if (lastlod < minlod) {
+ minlod = lastlod;
+ }
+
+ state[1] |= (sampler->minlod << SS3_MIN_LOD_SHIFT);
state[1] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
}
@@ -112,18 +151,23 @@ void i915_update_samplers( struct i915_context *i915 )
/* could also examine the fragment program? */
if (i915->texture[unit]) {
update_sampler( i915,
- unit,
- i915->sampler[unit], /* sampler state */
- i915->texture[unit], /* texture */
- i915->current.sampler[unit] /* the result */
- );
-
- i915->current.sampler_enable_nr++;
- i915->current.sampler_enable_flags |= (1 << unit);
+ unit,
+ i915->sampler[unit], /* sampler state */
+ i915->texture[unit], /* texture */
+ i915->current.sampler[unit] /* the result */
+ );
+ i915_update_texture( i915,
+ unit,
+ i915->texture[unit], /* texture */
+ i915->sampler[unit], /* sampler state */
+ i915->current.texbuffer[unit] );
+
+ i915->current.sampler_enable_nr++;
+ i915->current.sampler_enable_flags |= (1 << unit);
}
}
- i915->hardware_dirty |= I915_HW_SAMPLER;
+ i915->hardware_dirty |= I915_HW_SAMPLER | I915_HW_MAP;
}
@@ -168,7 +212,7 @@ translate_texture_format(enum pipe_format pipeFormat)
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
#endif
case PIPE_FORMAT_S8Z24_UNORM:
- return (MAPSURF_32BIT | MT_32BIT_xL824);
+ return (MAPSURF_32BIT | MT_32BIT_xI824);
default:
debug_printf("i915: translate_texture_format() bad image format %x\n",
pipeFormat);
@@ -179,14 +223,17 @@ translate_texture_format(enum pipe_format pipeFormat)
static void
-i915_update_texture(struct i915_context *i915, uint unit,
+i915_update_texture(struct i915_context *i915,
+ uint unit,
+ const struct i915_texture *tex,
+ const struct i915_sampler_state *sampler,
uint state[6])
{
- const struct i915_texture *tex = i915->texture[unit];
const struct pipe_texture *pt = &tex->base;
uint format, pitch;
const uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0];
const uint num_levels = pt->last_level;
+ unsigned max_lod = num_levels * 4;
assert(tex);
assert(width);
@@ -207,16 +254,19 @@ i915_update_texture(struct i915_context *i915, uint unit,
| MS3_USE_FENCE_REGS);
/*
- * XXX sampler->max_lod should be used to program the MAX_LOD field below.
- * Also, when min_filter != mag_filter and there's just one mipmap level,
+ * XXX When min_filter != mag_filter and there's just one mipmap level,
* set max_lod = 1 to make sure i915 chooses between min/mag filtering.
*/
+ /* See note at the top of file */
+ if (max_lod > (sampler->maxlod >> 2))
+ max_lod = sampler->maxlod >> 2;
+
/* MS4 state */
state[1] =
((((pitch / 4) - 1) << MS4_PITCH_SHIFT)
| MS4_CUBE_FACE_ENA_MASK
- | ((num_levels * 4) << MS4_MAX_LOD_SHIFT)
+ | ((max_lod) << MS4_MAX_LOD_SHIFT)
| ((depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
}
@@ -231,7 +281,11 @@ i915_update_textures(struct i915_context *i915)
/* determine unit enable/disable by looking for a bound texture */
/* could also examine the fragment program? */
if (i915->texture[unit]) {
- i915_update_texture(i915, unit, i915->current.texbuffer[unit]);
+ i915_update_texture( i915,
+ unit,
+ i915->texture[unit], /* texture */
+ i915->sampler[unit], /* sampler state */
+ i915->current.texbuffer[unit] );
}
}
diff --git a/src/gallium/drivers/i915simple/i915_texture.c b/src/gallium/drivers/i915simple/i915_texture.c
index df11ba0544..9cd32e3919 100644
--- a/src/gallium/drivers/i915simple/i915_texture.c
+++ b/src/gallium/drivers/i915simple/i915_texture.c
@@ -42,12 +42,58 @@
#include "i915_debug.h"
#include "i915_screen.h"
+/*
+ * Helper function and arrays
+ */
+
+/**
+ * Initial offset for Cube map.
+ */
+static const int initial_offsets[6][2] = {
+ {0, 0},
+ {0, 2},
+ {1, 0},
+ {1, 2},
+ {1, 1},
+ {1, 3}
+};
+
+/**
+ * Step offsets for Cube map.
+ */
+static const int step_offsets[6][2] = {
+ {0, 2},
+ {0, 2},
+ {-1, 2},
+ {-1, 2},
+ {-1, 1},
+ {-1, 1}
+};
static unsigned minify( unsigned d )
{
return MAX2(1, d>>1);
}
+static unsigned
+power_of_two(unsigned x)
+{
+ unsigned value = 1;
+ while (value <= x)
+ value = value << 1;
+ return value;
+}
+
+static unsigned
+round_up(unsigned n, unsigned multiple)
+{
+ return (n + multiple - 1) & ~(multiple - 1);
+}
+
+
+/*
+ * More advanced helper funcs
+ */
static void
@@ -86,7 +132,6 @@ i915_miptree_set_level_info(struct i915_texture *tex,
tex->image_offset[level][0] = 0;
}
-
static void
i915_miptree_set_image_offset(struct i915_texture *tex,
unsigned level, unsigned img, unsigned x, unsigned y)
@@ -99,57 +144,51 @@ i915_miptree_set_image_offset(struct i915_texture *tex,
tex->image_offset[level][img] = (x + y * tex->pitch);
/*
- DBG("%s level %d img %d pos %d,%d image_offset %x\n",
+ printf("%s level %d img %d pos %d,%d image_offset %x\n",
__FUNCTION__, level, img, x, y, tex->image_offset[level][img]);
*/
}
-/* Hack it up to use the old winsys->surface_alloc_storage()
- * method for now:
+/*
+ * Layout functions
+ */
+
+
+/**
+ * Special case to deal with display targets.
*/
static boolean
-i915_displaytarget_layout(struct pipe_screen *screen,
- struct i915_texture *tex)
+i915_displaytarget_layout(struct i915_texture *tex)
{
- struct pipe_winsys *ws = screen->winsys;
- struct pipe_surface surf;
- unsigned flags = (PIPE_BUFFER_USAGE_CPU_READ |
- PIPE_BUFFER_USAGE_CPU_WRITE |
- PIPE_BUFFER_USAGE_GPU_READ |
- PIPE_BUFFER_USAGE_GPU_WRITE);
-
-
- memset(&surf, 0, sizeof(surf));
-
- ws->surface_alloc_storage( ws,
- &surf,
- tex->base.width[0],
- tex->base.height[0],
- tex->base.format,
- flags,
- tex->base.tex_usage);
-
- /* Now extract the goodies:
- */
+ struct pipe_texture *pt = &tex->base;
+
+ if (pt->last_level > 0 || pt->cpp != 4)
+ return 0;
+
i915_miptree_set_level_info( tex, 0, 1, 0, 0,
tex->base.width[0],
tex->base.height[0],
1 );
i915_miptree_set_image_offset( tex, 0, 0, 0, 0 );
- tex->buffer = surf.buffer;
- tex->pitch = surf.pitch;
- tex->total_height = 0;
+ if (tex->base.width[0] >= 128) {
+ tex->pitch = power_of_two(tex->base.width[0] * pt->cpp) / pt->cpp;
+ tex->total_height = round_up(tex->base.height[0], 8);
+ } else {
+ tex->pitch = round_up(tex->base.width[0], 64 / pt->cpp);
+ tex->total_height = tex->base.height[0];
+ }
+ /*
+ printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
+ tex->base.width[0], tex->base.height[0], pt->cpp,
+ tex->pitch, tex->total_height, tex->pitch * tex->total_height * 4);
+ */
- return tex->buffer != NULL;
+ return 1;
}
-
-
-
-
static void
i945_miptree_layout_2d( struct i915_texture *tex )
{
@@ -161,6 +200,12 @@ i945_miptree_layout_2d( struct i915_texture *tex )
unsigned width = pt->width[0];
unsigned height = pt->height[0];
+#if 0 /* used for tiled display targets */
+ if (pt->last_level == 0 && pt->cpp == 4)
+ if (i915_displaytarget_layout(tex))
+ return;
+#endif
+
tex->pitch = pt->width[0];
/* May need to adjust pitch to accomodate the placement of
@@ -179,7 +224,7 @@ i945_miptree_layout_2d( struct i915_texture *tex )
/* Pitch must be a whole number of dwords, even though we
* express it in texels.
*/
- tex->pitch = align_int(tex->pitch * pt->cpp, 4) / pt->cpp;
+ tex->pitch = align_int(tex->pitch * pt->cpp, 64) / pt->cpp;
tex->total_height = 0;
for (level = 0; level <= pt->last_level; level++) {
@@ -212,25 +257,108 @@ i945_miptree_layout_2d( struct i915_texture *tex )
}
}
+static void
+i945_miptree_layout_cube(struct i915_texture *tex)
+{
+ struct pipe_texture *pt = &tex->base;
+ unsigned level;
-static const int initial_offsets[6][2] = {
- {0, 0},
- {0, 2},
- {1, 0},
- {1, 2},
- {1, 1},
- {1, 3}
-};
+ const unsigned dim = pt->width[0];
+ unsigned face;
+ unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0];
-static const int step_offsets[6][2] = {
- {0, 2},
- {0, 2},
- {-1, 2},
- {-1, 2},
- {-1, 1},
- {-1, 1}
-};
+ /*
+ printf("%s %i, %i\n", __FUNCTION__, pt->width[0], pt->height[0]);
+ */
+
+ assert(lvlWidth == lvlHeight); /* cubemap images are square */
+
+ /*
+ * XXX Should only be used for compressed formats. But lets
+ * keep this code active just in case.
+ *
+ * Depending on the size of the largest images, pitch can be
+ * determined either by the old-style packing of cubemap faces,
+ * or the final row of 4x4, 2x2 and 1x1 faces below this.
+ */
+ if (dim > 32)
+ tex->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
+ else
+ tex->pitch = 14 * 8;
+
+ /*
+ * XXX The 4 is only needed for compressed formats. See above.
+ */
+ tex->total_height = dim * 4 + 4;
+
+ /* Set all the levels to effectively occupy the whole rectangular region.
+ */
+ for (level = 0; level <= pt->last_level; level++) {
+ i915_miptree_set_level_info(tex, level, 6, 0, 0, lvlWidth, lvlHeight, 1);
+ lvlWidth /= 2;
+ lvlHeight /= 2;
+ }
+ for (face = 0; face < 6; face++) {
+ unsigned x = initial_offsets[face][0] * dim;
+ unsigned y = initial_offsets[face][1] * dim;
+ unsigned d = dim;
+
+#if 0 /* Fix and enable this code for compressed formats */
+ if (dim == 4 && face >= 4) {
+ y = tex->total_height - 4;
+ x = (face - 4) * 8;
+ }
+ else if (dim < 4 && (face > 0)) {
+ y = tex->total_height - 4;
+ x = face * 8;
+ }
+#endif
+
+ for (level = 0; level <= pt->last_level; level++) {
+ i915_miptree_set_image_offset(tex, level, face, x, y);
+
+ d >>= 1;
+
+#if 0 /* Fix and enable this code for compressed formats */
+ switch (d) {
+ case 4:
+ switch (face) {
+ case PIPE_TEX_FACE_POS_X:
+ case PIPE_TEX_FACE_NEG_X:
+ x += step_offsets[face][0] * d;
+ y += step_offsets[face][1] * d;
+ break;
+ case PIPE_TEX_FACE_POS_Y:
+ case PIPE_TEX_FACE_NEG_Y:
+ y += 12;
+ x -= 8;
+ break;
+ case PIPE_TEX_FACE_POS_Z:
+ case PIPE_TEX_FACE_NEG_Z:
+ y = tex->total_height - 4;
+ x = (face - 4) * 8;
+ break;
+ }
+ case 2:
+ y = tex->total_height - 4;
+ x = 16 + face * 8;
+ break;
+
+ case 1:
+ x += 48;
+ break;
+ default:
+#endif
+ x += step_offsets[face][0] * d;
+ y += step_offsets[face][1] * d;
+#if 0
+ break;
+ }
+#endif
+ }
+ }
+}
static boolean
i915_miptree_layout(struct i915_texture * tex)
@@ -363,99 +491,15 @@ i945_miptree_layout(struct i915_texture * tex)
unsigned level;
switch (pt->target) {
- case PIPE_TEXTURE_CUBE:{
- const unsigned dim = pt->width[0];
- unsigned face;
- unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0];
-
- assert(lvlWidth == lvlHeight); /* cubemap images are square */
-
- /* Depending on the size of the largest images, pitch can be
- * determined either by the old-style packing of cubemap faces,
- * or the final row of 4x4, 2x2 and 1x1 faces below this.
- */
- if (dim > 32)
- tex->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
- else
- tex->pitch = 14 * 8;
-
- tex->total_height = dim * 4 + 4;
-
- /* Set all the levels to effectively occupy the whole rectangular region.
- */
- for (level = 0; level <= pt->last_level; level++) {
- i915_miptree_set_level_info(tex, level, 6,
- 0, 0,
- lvlWidth, lvlHeight, 1);
- lvlWidth /= 2;
- lvlHeight /= 2;
- }
-
-
- for (face = 0; face < 6; face++) {
- unsigned x = initial_offsets[face][0] * dim;
- unsigned y = initial_offsets[face][1] * dim;
- unsigned d = dim;
-
- if (dim == 4 && face >= 4) {
- y = tex->total_height - 4;
- x = (face - 4) * 8;
- }
- else if (dim < 4 && (face > 0)) {
- y = tex->total_height - 4;
- x = face * 8;
- }
-
- for (level = 0; level <= pt->last_level; level++) {
- i915_miptree_set_image_offset(tex, level, face, x, y);
-
- d >>= 1;
-
- switch (d) {
- case 4:
- switch (face) {
- case PIPE_TEX_FACE_POS_X:
- case PIPE_TEX_FACE_NEG_X:
- x += step_offsets[face][0] * d;
- y += step_offsets[face][1] * d;
- break;
- case PIPE_TEX_FACE_POS_Y:
- case PIPE_TEX_FACE_NEG_Y:
- y += 12;
- x -= 8;
- break;
- case PIPE_TEX_FACE_POS_Z:
- case PIPE_TEX_FACE_NEG_Z:
- y = tex->total_height - 4;
- x = (face - 4) * 8;
- break;
- }
-
- case 2:
- y = tex->total_height - 4;
- x = 16 + face * 8;
- break;
-
- case 1:
- x += 48;
- break;
-
- default:
- x += step_offsets[face][0] * d;
- y += step_offsets[face][1] * d;
- break;
- }
- }
- }
- break;
- }
+ case PIPE_TEXTURE_CUBE:
+ i945_miptree_layout_cube(tex);
+ break;
case PIPE_TEXTURE_3D:{
unsigned width = pt->width[0];
unsigned height = pt->height[0];
unsigned depth = pt->depth[0];
unsigned pack_x_pitch, pack_x_nr;
unsigned pack_y_pitch;
- unsigned level;
tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
tex->total_height = 0;
@@ -532,39 +576,32 @@ i915_texture_create(struct pipe_screen *screen,
struct pipe_winsys *ws = screen->winsys;
struct i915_texture *tex = CALLOC_STRUCT(i915_texture);
- if (!tex)
+ if (!tex)
return NULL;
tex->base = *templat;
tex->base.refcount = 1;
tex->base.screen = screen;
- if (tex->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
- if (!i915_displaytarget_layout(screen, tex))
- goto fail;
- }
- else {
- if (i915screen->is_i945) {
- if (!i945_miptree_layout(tex))
- goto fail;
- }
- else {
- if (!i915_miptree_layout(tex))
- goto fail;
- }
-
- tex->buffer = ws->buffer_create(ws, 64,
- PIPE_BUFFER_USAGE_PIXEL,
- tex->pitch * tex->base.cpp *
- tex->total_height);
-
- if (!tex->buffer)
- goto fail;
+ if (i915screen->is_i945) {
+ if (!i945_miptree_layout(tex))
+ goto fail;
+ } else {
+ if (!i915_miptree_layout(tex))
+ goto fail;
}
+ tex->buffer = ws->buffer_create(ws, 64,
+ PIPE_BUFFER_USAGE_PIXEL,
+ tex->pitch * tex->base.cpp *
+ tex->total_height);
+
+ if (!tex->buffer)
+ goto fail;
+
return &tex->base;
- fail:
+fail:
FREE(tex);
return NULL;
}
@@ -600,11 +637,6 @@ i915_texture_release(struct pipe_screen *screen,
*pt = NULL;
}
-
-
-/*
- * XXX note: same as code in sp_surface.c
- */
static struct pipe_surface *
i915_get_tex_surface(struct pipe_screen *screen,
struct pipe_texture *pt,
@@ -629,10 +661,10 @@ i915_get_tex_surface(struct pipe_screen *screen,
assert(zslice == 0);
}
- ps = ws->surface_alloc(ws);
+ ps = CALLOC_STRUCT(pipe_surface);
if (ps) {
- assert(ps->refcount);
- assert(ps->winsys);
+ ps->refcount = 1;
+ ps->winsys = ws;
pipe_texture_reference(&ps->texture, pt);
pipe_buffer_reference(ws, &ps->buffer, tex->buffer);
ps->format = pt->format;
@@ -642,11 +674,11 @@ i915_get_tex_surface(struct pipe_screen *screen,
ps->pitch = tex->pitch;
ps->offset = offset;
ps->usage = flags;
+ ps->status = PIPE_SURFACE_STATUS_DEFINED;
}
return ps;
}
-
void
i915_init_texture_functions(struct i915_context *i915)
{
diff --git a/src/gallium/drivers/i915simple/i915_winsys.h b/src/gallium/drivers/i915simple/i915_winsys.h
index 5e16543f4e..9afaa16a62 100644
--- a/src/gallium/drivers/i915simple/i915_winsys.h
+++ b/src/gallium/drivers/i915simple/i915_winsys.h
@@ -55,6 +55,7 @@ extern "C" {
* etc.
*/
+struct i915_batchbuffer;
struct pipe_buffer;
struct pipe_fence_handle;
struct pipe_winsys;
@@ -75,20 +76,10 @@ struct pipe_screen;
struct i915_winsys {
/**
- * Reserve space on batch buffer.
- *
- * Returns a null pointer if there is insufficient space in the batch buffer
- * to hold the requested number of dwords and relocations.
- *
- * The number of dwords should also include the number of relocations.
+ * Get the current batch buffer from the winsys.
*/
- unsigned *(*batch_start)( struct i915_winsys *sws,
- unsigned dwords,
- unsigned relocs );
-
- void (*batch_dword)( struct i915_winsys *sws,
- unsigned dword );
-
+ struct i915_batchbuffer *(*batch_get)( struct i915_winsys *sws );
+
/**
* Emit a relocation to a buffer.
*
@@ -103,7 +94,10 @@ struct i915_winsys {
struct pipe_buffer *buf,
unsigned access_flags,
unsigned delta );
-
+
+ /**
+ * Flush the batch.
+ */
void (*batch_flush)( struct i915_winsys *sws,
struct pipe_fence_handle **fence );
};