diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index 1b30309bb58..ff6d715b72a 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -79,6 +79,11 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) else draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0, NULL, 0); + if (i915->num_vertex_sampler_views > 0) + i915_prepare_vertex_sampling(i915, + i915->num_vertex_sampler_views, + i915->vertex_sampler_views); + /* * Do the drawing */ @@ -86,6 +91,9 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) if (mapped_indices) draw_set_mapped_index_buffer(draw, NULL); + + if (i915->num_vertex_sampler_views > 0) + i915_cleanup_vertex_sampling(i915); } diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h index dacd0a669c1..7f67f5f1340 100644 --- a/src/gallium/drivers/i915/i915_context.h +++ b/src/gallium/drivers/i915/i915_context.h @@ -225,6 +225,7 @@ struct i915_context { */ const struct i915_blend_state *blend; const struct i915_sampler_state *sampler[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_state *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS]; const struct i915_depth_stencil_state *depth_stencil; const struct i915_rasterizer_state *rasterizer; @@ -238,13 +239,19 @@ struct i915_context { struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_index_buffer index_buffer; unsigned dirty; + struct pipe_resource *mapped_vs_tex[PIPE_MAX_VERTEX_SAMPLERS]; + struct i915_winsys_buffer* mapped_vs_tex_buffer[PIPE_MAX_VERTEX_SAMPLERS]; + unsigned num_samplers; unsigned num_fragment_sampler_views; + unsigned num_vertex_samplers; + unsigned num_vertex_sampler_views; struct i915_winsys_batchbuffer *batch; @@ -360,6 +367,16 @@ struct draw_stage *i915_draw_render_stage( struct i915_context *i915 ); struct draw_stage *i915_draw_vbuf_stage( struct i915_context *i915 ); +/*********************************************************************** + * i915_state.c: + */ +void i915_prepare_vertex_sampling(struct i915_context *i915, + unsigned num, + struct pipe_sampler_view **views); +void i915_cleanup_vertex_sampling(struct i915_context *i915); + + + /*********************************************************************** * i915_state_emit.c: */ diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index cc818351577..7d9b8653ea6 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -99,79 +99,6 @@ i915_get_name(struct pipe_screen *screen) return buffer; } -static int -i915_get_param(struct pipe_screen *screen, enum pipe_cap cap) -{ - struct i915_screen *is = i915_screen(screen); - - switch (cap) { - /* Supported features (boolean caps). */ - case PIPE_CAP_ANISOTROPIC_FILTER: - case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: - case PIPE_CAP_NPOT_TEXTURES: - case PIPE_CAP_POINT_SPRITE: - case PIPE_CAP_PRIMITIVE_RESTART: /* draw module */ - case PIPE_CAP_TEXTURE_SHADOW_MAP: - case PIPE_CAP_TWO_SIDED_STENCIL: - case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: - case PIPE_CAP_BLEND_EQUATION_SEPARATE: - return 1; - - /* Unsupported features (boolean caps). */ - case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: - case PIPE_CAP_DEPTH_CLAMP: - case PIPE_CAP_INDEP_BLEND_ENABLE: - case PIPE_CAP_INDEP_BLEND_FUNC: - case PIPE_CAP_TGSI_INSTANCEID: - case PIPE_CAP_SHADER_STENCIL_EXPORT: - case PIPE_CAP_TEXTURE_MIRROR_CLAMP: - case PIPE_CAP_TEXTURE_SWIZZLE: - case PIPE_CAP_TIMER_QUERY: - case PIPE_CAP_SM3: - case PIPE_CAP_SEAMLESS_CUBE_MAP: - case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: - case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL: - case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: - case PIPE_CAP_CONDITIONAL_RENDER: - case PIPE_CAP_TEXTURE_BARRIER: - return 0; - - /* Features we can lie about (boolean caps). */ - case PIPE_CAP_GLSL: - case PIPE_CAP_OCCLUSION_QUERY: - return is->debug.lie ? 1 : 0; - - /* Texturing. */ - case PIPE_CAP_MAX_COMBINED_SAMPLERS: - return 8; - case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return I915_MAX_TEXTURE_2D_LEVELS; - case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return I915_MAX_TEXTURE_3D_LEVELS; - case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return I915_MAX_TEXTURE_2D_LEVELS; - case PIPE_CAP_MIN_TEXEL_OFFSET: - case PIPE_CAP_MAX_TEXEL_OFFSET: - return 0; - - /* Render targets. */ - case PIPE_CAP_MAX_RENDER_TARGETS: - return 1; - - /* Fragment coordinate conventions. */ - case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: - case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: - return 1; - case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: - case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: - return 0; - - default: - debug_printf("%s: Unknown cap %u.\n", __FUNCTION__, cap); - return 0; - } -} - static int i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap cap) { @@ -179,7 +106,10 @@ i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_sha case PIPE_SHADER_VERTEX: switch (cap) { case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: - return 0; + if (debug_get_bool_option("DRAW_USE_LLVM", TRUE)) + return PIPE_MAX_VERTEX_SAMPLERS; + else + return 0; default: return draw_get_shader_param(shader, cap); } @@ -225,12 +155,91 @@ i915_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_sha debug_printf("%s: Unknown cap %u.\n", __FUNCTION__, cap); return 0; } + break; default: return 0; } } +static int +i915_get_param(struct pipe_screen *screen, enum pipe_cap cap) +{ + struct i915_screen *is = i915_screen(screen); + + switch (cap) { + /* Supported features (boolean caps). */ + case PIPE_CAP_ANISOTROPIC_FILTER: + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + case PIPE_CAP_NPOT_TEXTURES: + case PIPE_CAP_POINT_SPRITE: + case PIPE_CAP_PRIMITIVE_RESTART: /* draw module */ + case PIPE_CAP_TEXTURE_SHADOW_MAP: + case PIPE_CAP_TWO_SIDED_STENCIL: + case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: + case PIPE_CAP_BLEND_EQUATION_SEPARATE: + return 1; + + /* Unsupported features (boolean caps). */ + case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: + case PIPE_CAP_DEPTH_CLAMP: + case PIPE_CAP_INDEP_BLEND_ENABLE: + case PIPE_CAP_INDEP_BLEND_FUNC: + case PIPE_CAP_TGSI_INSTANCEID: + case PIPE_CAP_SHADER_STENCIL_EXPORT: + case PIPE_CAP_TEXTURE_MIRROR_CLAMP: + case PIPE_CAP_TEXTURE_SWIZZLE: + case PIPE_CAP_TIMER_QUERY: + case PIPE_CAP_SM3: + case PIPE_CAP_SEAMLESS_CUBE_MAP: + case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: + case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL: + case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: + case PIPE_CAP_CONDITIONAL_RENDER: + case PIPE_CAP_TEXTURE_BARRIER: + return 0; + + /* Features we can lie about (boolean caps). */ + case PIPE_CAP_GLSL: + case PIPE_CAP_OCCLUSION_QUERY: + return is->debug.lie ? 1 : 0; + + /* Texturing. */ + case PIPE_CAP_MAX_COMBINED_SAMPLERS: + return i915_get_shader_param(screen, + PIPE_SHADER_VERTEX, + PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS) + + i915_get_shader_param(screen, + PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS); + case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: + return I915_MAX_TEXTURE_2D_LEVELS; + case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: + return I915_MAX_TEXTURE_3D_LEVELS; + case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: + return I915_MAX_TEXTURE_2D_LEVELS; + case PIPE_CAP_MIN_TEXEL_OFFSET: + case PIPE_CAP_MAX_TEXEL_OFFSET: + return 0; + + /* Render targets. */ + case PIPE_CAP_MAX_RENDER_TARGETS: + return 1; + + /* Fragment coordinate conventions. */ + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; + + default: + debug_printf("%s: Unknown cap %u.\n", __FUNCTION__, cap); + return 0; + } +} + static float i915_get_paramf(struct pipe_screen *screen, enum pipe_cap cap) { diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c index 345c109a995..f6e531062fe 100644 --- a/src/gallium/drivers/i915/i915_state.c +++ b/src/gallium/drivers/i915/i915_state.c @@ -299,7 +299,38 @@ static void i915_fixup_bind_sampler_states(struct pipe_context *pipe, i915->saved_bind_sampler_states(pipe, num, sampler); } -static void i915_bind_sampler_states(struct pipe_context *pipe, +static void +i915_bind_vertex_sampler_states(struct pipe_context *pipe, + unsigned num_samplers, + void **samplers) +{ + struct i915_context *i915 = i915_context(pipe); + unsigned i; + + assert(num_samplers <= PIPE_MAX_VERTEX_SAMPLERS); + + /* Check for no-op */ + if (num_samplers == i915->num_vertex_samplers && + !memcmp(i915->vertex_samplers, samplers, num_samplers * sizeof(void *))) + return; + + draw_flush(i915->draw); + + for (i = 0; i < num_samplers; ++i) + i915->vertex_samplers[i] = samplers[i]; + for (i = num_samplers; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) + i915->vertex_samplers[i] = NULL; + + i915->num_vertex_samplers = num_samplers; + + draw_set_samplers(i915->draw, + i915->vertex_samplers, + i915->num_vertex_samplers); +} + + + +static void i915_bind_fragment_sampler_states(struct pipe_context *pipe, unsigned num, void **sampler) { struct i915_context *i915 = i915_context(pipe); @@ -329,6 +360,76 @@ static void i915_delete_sampler_state(struct pipe_context *pipe, } +/** + * Called during state validation when LP_NEW_SAMPLER_VIEW is set. + */ +void +i915_prepare_vertex_sampling(struct i915_context *i915, + unsigned num, + struct pipe_sampler_view **views) +{ + struct i915_winsys *iws = i915->iws; + unsigned i,j; + uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS]; + uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS]; + const void* data[PIPE_MAX_TEXTURE_LEVELS]; + + assert(num <= PIPE_MAX_VERTEX_SAMPLERS); + if (!num) + return; + + for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { + struct pipe_sampler_view *view = i < num ? views[i] : NULL; + + if (view) { + struct pipe_resource *tex = view->texture; + struct i915_texture *i915_tex = i915_texture(tex); + void* addr; + + /* We're referencing the texture's internal data, so save a + * reference to it. + */ + pipe_resource_reference(&i915->mapped_vs_tex[i], tex); + + i915->mapped_vs_tex_buffer[i] = i915_tex->buffer; + addr = iws->buffer_map(iws, + i915_tex->buffer, + FALSE /* read only */); + + /* Setup array of mipmap level pointers */ + /* FIXME: handle 3D textures? */ + for (j = view->u.tex.first_level; j <= tex->last_level; j++) { + unsigned offset = i915_texture_offset(i915_tex, j , 0 /* FIXME depth */); + data[j] = addr + offset; + row_stride[j] = i915_tex->stride; + img_stride[j] = 0; /* FIXME */; + } + + draw_set_mapped_texture(i915->draw, + i, + tex->width0, tex->height0, tex->depth0, + view->u.tex.first_level, tex->last_level, + row_stride, img_stride, data); + } else + i915->mapped_vs_tex[i] = NULL; + } +} + +void +i915_cleanup_vertex_sampling(struct i915_context *i915) +{ + struct i915_winsys *iws = i915->iws; + unsigned i; + for (i = 0; i < Elements(i915->mapped_vs_tex); i++) { + if (i915->mapped_vs_tex_buffer[i]) { + iws->buffer_unmap(iws, i915->mapped_vs_tex_buffer[i]); + pipe_resource_reference(&i915->mapped_vs_tex[i], NULL); + } + } +} + + + /** XXX move someday? Or consolidate all these simple state setters * into one file. */ @@ -652,6 +753,37 @@ static void i915_set_fragment_sampler_views(struct pipe_context *pipe, i915->dirty |= I915_NEW_SAMPLER_VIEW; } +static void +i915_set_vertex_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) +{ + struct i915_context *i915 = i915_context(pipe); + uint i; + + assert(num <= PIPE_MAX_VERTEX_SAMPLERS); + + /* Check for no-op */ + if (num == i915->num_vertex_sampler_views && + !memcmp(i915->vertex_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) { + return; + } + + draw_flush(i915->draw); + + for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { + struct pipe_sampler_view *view = i < num ? views[i] : NULL; + + pipe_sampler_view_reference(&i915->vertex_sampler_views[i], view); + } + + i915->num_vertex_sampler_views = num; + + draw_set_sampler_views(i915->draw, + i915->vertex_sampler_views, + i915->num_vertex_sampler_views); +} + static struct pipe_sampler_view * i915_create_sampler_view(struct pipe_context *pipe, @@ -918,7 +1050,8 @@ i915_init_state_functions( struct i915_context *i915 ) i915->base.delete_blend_state = i915_delete_blend_state; i915->base.create_sampler_state = i915_create_sampler_state; - i915->base.bind_fragment_sampler_states = i915_bind_sampler_states; + i915->base.bind_fragment_sampler_states = i915_bind_fragment_sampler_states; + i915->base.bind_vertex_sampler_states = i915_bind_vertex_sampler_states; i915->base.delete_sampler_state = i915_delete_sampler_state; i915->base.create_depth_stencil_alpha_state = i915_create_depth_stencil_state; @@ -948,6 +1081,7 @@ i915_init_state_functions( struct i915_context *i915 ) i915->base.set_polygon_stipple = i915_set_polygon_stipple; i915->base.set_scissor_state = i915_set_scissor_state; i915->base.set_fragment_sampler_views = i915_set_fragment_sampler_views; + i915->base.set_vertex_sampler_views = i915_set_vertex_sampler_views; i915->base.create_sampler_view = i915_create_sampler_view; i915->base.sampler_view_destroy = i915_sampler_view_destroy; i915->base.set_viewport_state = i915_set_viewport_state;