#include "draw/draw_context.h"
-#include "pipe/internal/p_winsys_screen.h"
-#include "pipe/p_inlines.h"
+#include "util/u_inlines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
+#include "util/u_transfer.h"
#include "tgsi/tgsi_parse.h"
#include "i915_context.h"
#include "i915_reg.h"
-#include "i915_state.h"
#include "i915_state_inlines.h"
#include "i915_fpc.h"
+#include "i915_resource.h"
/* The i915 (and related graphics cores) do not support GL_CLAMP. The
* Intel drivers for "other operating systems" implement GL_CLAMP as
return TEXCOORDMODE_CLAMP_EDGE;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
return TEXCOORDMODE_CLAMP_BORDER;
- /*
- case PIPE_TEX_WRAP_MIRRORED_REPEAT:
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
return TEXCOORDMODE_MIRROR;
- */
default:
return TEXCOORDMODE_WRAP;
}
struct i915_blend_state *cso_data = CALLOC_STRUCT( i915_blend_state );
{
- unsigned eqRGB = blend->rgb_func;
- unsigned srcRGB = blend->rgb_src_factor;
- unsigned dstRGB = blend->rgb_dst_factor;
+ unsigned eqRGB = blend->rt[0].rgb_func;
+ unsigned srcRGB = blend->rt[0].rgb_src_factor;
+ unsigned dstRGB = blend->rt[0].rgb_dst_factor;
- unsigned eqA = blend->alpha_func;
- unsigned srcA = blend->alpha_src_factor;
- unsigned dstA = blend->alpha_dst_factor;
+ unsigned eqA = blend->rt[0].alpha_func;
+ unsigned srcA = blend->rt[0].alpha_src_factor;
+ unsigned dstA = blend->rt[0].alpha_dst_factor;
/* Special handling for MIN/MAX filter modes handled at
* state_tracker level.
if (blend->dither)
cso_data->LIS5 |= S5_COLOR_DITHER_ENABLE;
- if ((blend->colormask & PIPE_MASK_R) == 0)
+ /* XXX here take the target fixup into account */
+ if ((blend->rt[0].colormask & PIPE_MASK_R) == 0)
cso_data->LIS5 |= S5_WRITEDISABLE_RED;
- if ((blend->colormask & PIPE_MASK_G) == 0)
+ if ((blend->rt[0].colormask & PIPE_MASK_G) == 0)
cso_data->LIS5 |= S5_WRITEDISABLE_GREEN;
- if ((blend->colormask & PIPE_MASK_B) == 0)
+ if ((blend->rt[0].colormask & PIPE_MASK_B) == 0)
cso_data->LIS5 |= S5_WRITEDISABLE_BLUE;
- if ((blend->colormask & PIPE_MASK_A) == 0)
+ if ((blend->rt[0].colormask & PIPE_MASK_A) == 0)
cso_data->LIS5 |= S5_WRITEDISABLE_ALPHA;
- if (blend->blend_enable) {
- unsigned funcRGB = blend->rgb_func;
- unsigned srcRGB = blend->rgb_src_factor;
- unsigned dstRGB = blend->rgb_dst_factor;
+ if (blend->rt[0].blend_enable) {
+ unsigned funcRGB = blend->rt[0].rgb_func;
+ unsigned srcRGB = blend->rt[0].rgb_src_factor;
+ unsigned dstRGB = blend->rt[0].rgb_dst_factor;
cso_data->LIS6 |= (S6_CBUF_BLEND_ENABLE |
SRC_BLND_FACT(i915_translate_blend_factor(srcRGB)) |
}
static void i915_set_blend_color( struct pipe_context *pipe,
- const struct pipe_blend_color *blend_color )
+ const struct pipe_blend_color *blend_color )
{
struct i915_context *i915 = i915_context(pipe);
draw_flush(i915->draw);
i915->dirty |= I915_NEW_BLEND;
}
+static void i915_set_stencil_ref( struct pipe_context *pipe,
+ const struct pipe_stencil_ref *stencil_ref )
+{
+ struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
+
+ i915->stencil_ref = *stencil_ref;
+
+ i915->dirty |= I915_NEW_DEPTH_STENCIL;
+}
+
static void *
i915_create_sampler_state(struct pipe_context *pipe,
const struct pipe_sampler_state *sampler)
minFilt = translate_img_filter( sampler->min_img_filter );
magFilt = translate_img_filter( sampler->mag_img_filter );
- if (sampler->max_anisotropy > 1.0)
+ if (sampler->max_anisotropy > 1)
minFilt = magFilt = FILTER_ANISOTROPIC;
- if (sampler->max_anisotropy > 2.0) {
+ if (sampler->max_anisotropy > 2) {
cso->state[0] |= SS2_MAX_ANISO_4;
}
if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE)
{
cso->state[0] |= (SS2_SHADOW_ENABLE |
- i915_translate_compare_func(sampler->compare_func));
+ i915_translate_shadow_compare_func(sampler->compare_func));
minFilt = FILTER_4X4_FLAT;
magFilt = FILTER_4X4_FLAT;
return cso;
}
+static void i915_fixup_bind_sampler_states(struct pipe_context *pipe,
+ unsigned num, void **sampler)
+{
+ struct i915_context *i915 = i915_context(pipe);
+
+ i915->saved_nr_samplers = num;
+ memcpy(&i915->saved_samplers, sampler, sizeof(void *) * num);
+
+ i915->saved_bind_sampler_states(pipe, num, sampler);
+}
+
static void i915_bind_sampler_states(struct pipe_context *pipe,
unsigned num, void **sampler)
{
struct i915_context *i915 = i915_context(pipe);
unsigned i;
- assert(num <= PIPE_MAX_SAMPLERS);
-
/* Check for no-op */
if (num == i915->num_samplers &&
!memcmp(i915->sampler, sampler, num * sizeof(void *)))
int fop = i915_translate_stencil_op(depth_stencil->stencil[0].fail_op);
int dfop = i915_translate_stencil_op(depth_stencil->stencil[0].zfail_op);
int dpop = i915_translate_stencil_op(depth_stencil->stencil[0].zpass_op);
- int ref = depth_stencil->stencil[0].ref_value & 0xff;
cso->stencil_LIS5 |= (S5_STENCIL_TEST_ENABLE |
S5_STENCIL_WRITE_ENABLE |
- (ref << S5_STENCIL_REF_SHIFT) |
(test << S5_STENCIL_TEST_FUNC_SHIFT) |
(fop << S5_STENCIL_FAIL_SHIFT) |
(dfop << S5_STENCIL_PASS_Z_FAIL_SHIFT) |
int fop = i915_translate_stencil_op(depth_stencil->stencil[1].fail_op);
int dfop = i915_translate_stencil_op(depth_stencil->stencil[1].zfail_op);
int dpop = i915_translate_stencil_op(depth_stencil->stencil[1].zpass_op);
- int ref = depth_stencil->stencil[1].ref_value & 0xff;
int tmask = depth_stencil->stencil[1].valuemask & 0xff;
int wmask = depth_stencil->stencil[1].writemask & 0xff;
BFO_ENABLE_STENCIL_TWO_SIDE |
BFO_ENABLE_STENCIL_REF |
BFO_STENCIL_TWO_SIDE |
- (ref << BFO_STENCIL_REF_SHIFT) |
(test << BFO_STENCIL_TEST_SHIFT) |
(fop << BFO_STENCIL_FAIL_SHIFT) |
(dfop << BFO_STENCIL_PASS_Z_FAIL_SHIFT) |
if (!ifs)
return NULL;
+ ifs->draw_data = draw_create_fragment_shader(i915->draw, templ);
ifs->state.tokens = tgsi_dup_tokens(templ->tokens);
tgsi_scan_shader(templ->tokens, &ifs->info);
return ifs;
}
+static void
+i915_fixup_bind_fs_state(struct pipe_context *pipe, void *shader)
+{
+ struct i915_context *i915 = i915_context(pipe);
+ draw_flush(i915->draw);
+
+ i915->saved_fs = shader;
+
+ i915->saved_bind_fs_state(pipe, shader);
+}
+
static void
i915_bind_fs_state(struct pipe_context *pipe, void *shader)
{
i915->fs = (struct i915_fragment_shader*) shader;
+ draw_bind_fragment_shader(i915->draw, (i915->fs ? i915->fs->draw_data : NULL));
+
i915->dirty |= I915_NEW_FS;
}
{
struct i915_fragment_shader *ifs = (struct i915_fragment_shader *) shader;
- if (ifs->program)
+ if (ifs->program) {
FREE(ifs->program);
+ ifs->program = NULL;
+ FREE((struct tgsi_token *)ifs->state.tokens);
+ ifs->state.tokens = NULL;
+ }
ifs->program_len = 0;
- FREE((struct tgsi_token *)ifs->state.tokens);
-
FREE(ifs);
}
{
struct i915_context *i915 = i915_context(pipe);
+ i915->saved_vs = shader;
+
/* just pass-through to draw module */
draw_bind_vertex_shader(i915->draw, (struct draw_vertex_shader *) shader);
static void i915_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_resource *buf)
{
struct i915_context *i915 = i915_context(pipe);
- struct pipe_screen *screen = pipe->screen;
- draw_flush(i915->draw);
+ unsigned new_num = 0;
+ boolean diff = TRUE;
- assert(shader < PIPE_SHADER_TYPES);
- assert(index == 0);
-
- /* Make a copy of shader constants.
- * During fragment program translation we may add additional
- * constants to the array.
- *
- * We want to consider the situation where some user constants
- * (ex: a material color) may change frequently but the shader program
- * stays the same. In that case we should only be updating the first
- * N constants, leaving any extras from shader translation alone.
- */
+
+ /* XXX don't support geom shaders now */
+ if (shader == PIPE_SHADER_GEOMETRY)
+ return;
+
+ /* if we have a new buffer compare it with the old one */
if (buf) {
- void *mapped;
- if (buf->buffer && buf->buffer->size &&
- (mapped = pipe_buffer_map(screen, buf->buffer,
- PIPE_BUFFER_USAGE_CPU_READ))) {
- memcpy(i915->current.constants[shader], mapped, buf->buffer->size);
- pipe_buffer_unmap(screen, buf->buffer);
- i915->current.num_user_constants[shader]
- = buf->buffer->size / (4 * sizeof(float));
- }
- else {
- i915->current.num_user_constants[shader] = 0;
+ struct i915_buffer *ibuf = i915_buffer(buf);
+ struct pipe_resource *old_buf = i915->constants[shader];
+ struct i915_buffer *old = old_buf ? i915_buffer(old_buf) : NULL;
+ unsigned old_num = i915->current.num_user_constants[shader];
+
+ new_num = ibuf->b.b.width0 / 4 * sizeof(float);
+
+ if (old_num == new_num) {
+ if (old_num == 0)
+ diff = FALSE;
+#if 0
+ /* XXX no point in running this code since st/mesa only uses user buffers */
+ /* Can't compare the buffer data since they are userbuffers */
+ else if (old && old->free_on_destroy)
+ diff = memcmp(old->data, ibuf->data, ibuf->b.b.width0);
+#else
+ (void)old;
+#endif
}
+ } else {
+ diff = i915->current.num_user_constants[shader] != 0;
}
- i915->dirty |= I915_NEW_CONSTANTS;
+ /*
+ * flush before updateing the state.
+ */
+ if (diff && shader == PIPE_SHADER_FRAGMENT)
+ draw_flush(i915->draw);
+
+ pipe_resource_reference(&i915->constants[shader], buf);
+ i915->current.num_user_constants[shader] = new_num;
+
+ if (diff)
+ i915->dirty |= shader == PIPE_SHADER_VERTEX ? I915_NEW_VS_CONSTANTS : I915_NEW_FS_CONSTANTS;
}
-static void i915_set_sampler_textures(struct pipe_context *pipe,
+static void
+i915_fixup_set_fragment_sampler_views(struct pipe_context *pipe,
unsigned num,
- struct pipe_texture **texture)
+ struct pipe_sampler_view **views)
+{
+ struct i915_context *i915 = i915_context(pipe);
+ int i;
+
+ for (i = 0; i < num; i++)
+ pipe_sampler_view_reference(&i915->saved_sampler_views[i],
+ views[i]);
+
+ for (i = num; i < i915->saved_nr_sampler_views; i++)
+ pipe_sampler_view_reference(&i915->saved_sampler_views[i],
+ NULL);
+
+ i915->saved_nr_sampler_views = num;
+
+ i915->saved_set_sampler_views(pipe, num, views);
+}
+
+static void i915_set_fragment_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_SAMPLERS);
/* Check for no-op */
- if (num == i915->num_textures &&
- !memcmp(i915->texture, texture, num * sizeof(struct pipe_texture *)))
+ if (num == i915->num_fragment_sampler_views &&
+ !memcmp(i915->fragment_sampler_views, views, num * sizeof(struct pipe_sampler_view *)))
return;
/* Fixes wrong texture in texobj with VBUF */
draw_flush(i915->draw);
for (i = 0; i < num; i++)
- pipe_texture_reference((struct pipe_texture **) &i915->texture[i],
- texture[i]);
+ pipe_sampler_view_reference(&i915->fragment_sampler_views[i],
+ views[i]);
+
+ for (i = num; i < i915->num_fragment_sampler_views; i++)
+ pipe_sampler_view_reference(&i915->fragment_sampler_views[i],
+ NULL);
+
+ i915->num_fragment_sampler_views = num;
+
+ i915->dirty |= I915_NEW_SAMPLER_VIEW;
+}
- for (i = num; i < i915->num_textures; i++)
- pipe_texture_reference((struct pipe_texture **) &i915->texture[i],
- NULL);
- i915->num_textures = num;
+static struct pipe_sampler_view *
+i915_create_sampler_view(struct pipe_context *pipe,
+ struct pipe_resource *texture,
+ const struct pipe_sampler_view *templ)
+{
+ struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
+
+ if (view) {
+ *view = *templ;
+ view->reference.count = 1;
+ view->texture = NULL;
+ pipe_resource_reference(&view->texture, texture);
+ view->context = pipe;
+ }
- i915->dirty |= I915_NEW_TEXTURE;
+ return view;
}
+static void
+i915_sampler_view_destroy(struct pipe_context *pipe,
+ struct pipe_sampler_view *view)
+{
+ pipe_resource_reference(&view->texture, NULL);
+ FREE(view);
+}
+
static void i915_set_framebuffer_state(struct pipe_context *pipe,
const struct pipe_framebuffer_state *fb)
i915->framebuffer.height = fb->height;
i915->framebuffer.nr_cbufs = fb->nr_cbufs;
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
- pipe_surface_reference(&i915->framebuffer.cbufs[i], fb->cbufs[i]);
+ pipe_surface_reference(&i915->framebuffer.cbufs[i],
+ i < fb->nr_cbufs ? fb->cbufs[i] : NULL);
}
pipe_surface_reference(&i915->framebuffer.zsbuf, fb->zsbuf);
struct i915_context *i915 = i915_context(pipe);
draw_flush(i915->draw);
+ i915->saved_clip = *clip;
+
draw_set_clip_state(i915->draw, clip);
i915->dirty |= I915_NEW_CLIP;
{
struct i915_rasterizer_state *cso = CALLOC_STRUCT( i915_rasterizer_state );
- cso->templ = rasterizer;
+ cso->templ = *rasterizer;
cso->color_interp = rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
cso->light_twoside = rasterizer->light_twoside;
cso->ds[0].u = _3DSTATE_DEPTH_OFFSET_SCALE;
else
cso->sc[0] = _3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT;
- switch (rasterizer->cull_mode) {
- case PIPE_WINDING_NONE:
+ switch (rasterizer->cull_face) {
+ case PIPE_FACE_NONE:
cso->LIS4 |= S4_CULLMODE_NONE;
break;
- case PIPE_WINDING_CW:
- cso->LIS4 |= S4_CULLMODE_CW;
+ case PIPE_FACE_FRONT:
+ if (rasterizer->front_ccw)
+ cso->LIS4 |= S4_CULLMODE_CCW;
+ else
+ cso->LIS4 |= S4_CULLMODE_CW;
break;
- case PIPE_WINDING_CCW:
- cso->LIS4 |= S4_CULLMODE_CCW;
+ case PIPE_FACE_BACK:
+ if (rasterizer->front_ccw)
+ cso->LIS4 |= S4_CULLMODE_CW;
+ else
+ cso->LIS4 |= S4_CULLMODE_CCW;
break;
- case PIPE_WINDING_BOTH:
+ case PIPE_FACE_FRONT_AND_BACK:
cso->LIS4 |= S4_CULLMODE_BOTH;
break;
}
/* pass-through to draw module */
draw_set_rasterizer_state(i915->draw,
- (i915->rasterizer ? i915->rasterizer->templ : NULL));
+ (i915->rasterizer ? &(i915->rasterizer->templ) : NULL),
+ raster);
i915->dirty |= I915_NEW_RASTERIZER;
}
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);
+ struct draw_context *draw = i915->draw;
+ int i;
- memcpy(i915->vertex_buffer, buffers, count * sizeof(buffers[0]));
- i915->num_vertex_buffers = count;
+ util_copy_vertex_buffers(i915->saved_vertex_buffers,
+ &i915->saved_nr_vertex_buffers,
+ buffers, count);
+#if 0
+ /* XXX doesn't look like this is needed */
+ /* unmap old */
+ for (i = 0; i < i915->num_vertex_buffers; i++) {
+ draw_set_mapped_vertex_buffer(draw, i, NULL);
+ }
+#endif
/* pass-through to draw module */
- draw_set_vertex_buffers(i915->draw, count, buffers);
+ draw_set_vertex_buffers(draw, count, buffers);
+
+ /* map new */
+ for (i = 0; i < count; i++) {
+ void *buf = i915_buffer(buffers[i].buffer)->data;
+ draw_set_mapped_vertex_buffer(draw, i, buf);
+ }
+}
+
+static void *
+i915_create_vertex_elements_state(struct pipe_context *pipe,
+ unsigned count,
+ const struct pipe_vertex_element *attribs)
+{
+ struct i915_velems_state *velems;
+ assert(count <= PIPE_MAX_ATTRIBS);
+ velems = (struct i915_velems_state *) MALLOC(sizeof(struct i915_velems_state));
+ if (velems) {
+ velems->count = count;
+ memcpy(velems->velem, attribs, sizeof(*attribs) * count);
+ }
+ return velems;
}
-static void i915_set_vertex_elements(struct pipe_context *pipe,
- unsigned count,
- const struct pipe_vertex_element *elements)
+static void
+i915_bind_vertex_elements_state(struct pipe_context *pipe,
+ void *velems)
{
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);
+ struct i915_velems_state *i915_velems = (struct i915_velems_state *) velems;
+
+ i915->saved_velems = velems;
- i915->num_vertex_elements = count;
/* pass-through to draw module */
- draw_set_vertex_elements(i915->draw, count, elements);
+ if (i915_velems) {
+ draw_set_vertex_elements(i915->draw,
+ i915_velems->count, i915_velems->velem);
+ }
+}
+
+static void
+i915_delete_vertex_elements_state(struct pipe_context *pipe, void *velems)
+{
+ FREE( velems );
}
+static void i915_set_index_buffer(struct pipe_context *pipe,
+ const struct pipe_index_buffer *ib)
+{
+ struct i915_context *i915 = i915_context(pipe);
+
+ if (ib)
+ memcpy(&i915->index_buffer, ib, sizeof(i915->index_buffer));
+ else
+ memset(&i915->index_buffer, 0, sizeof(i915->index_buffer));
+
+ /* pass-through to draw module */
+ draw_set_index_buffer(i915->draw, ib);
+}
+
+static void
+i915_set_sample_mask(struct pipe_context *pipe,
+ unsigned sample_mask)
+{
+}
void
i915_init_state_functions( struct i915_context *i915 )
i915->base.create_vs_state = i915_create_vs_state;
i915->base.bind_vs_state = i915_bind_vs_state;
i915->base.delete_vs_state = i915_delete_vs_state;
+ i915->base.create_vertex_elements_state = i915_create_vertex_elements_state;
+ i915->base.bind_vertex_elements_state = i915_bind_vertex_elements_state;
+ i915->base.delete_vertex_elements_state = i915_delete_vertex_elements_state;
i915->base.set_blend_color = i915_set_blend_color;
+ i915->base.set_stencil_ref = i915_set_stencil_ref;
i915->base.set_clip_state = i915_set_clip_state;
+ i915->base.set_sample_mask = i915_set_sample_mask;
i915->base.set_constant_buffer = i915_set_constant_buffer;
i915->base.set_framebuffer_state = i915_set_framebuffer_state;
i915->base.set_polygon_stipple = i915_set_polygon_stipple;
i915->base.set_scissor_state = i915_set_scissor_state;
- i915->base.set_fragment_sampler_textures = i915_set_sampler_textures;
+ i915->base.set_fragment_sampler_views = i915_set_fragment_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;
i915->base.set_vertex_buffers = i915_set_vertex_buffers;
- i915->base.set_vertex_elements = i915_set_vertex_elements;
+ i915->base.set_index_buffer = i915_set_index_buffer;
+ i915->base.redefine_user_buffer = u_default_redefine_user_buffer;
+}
+
+void
+i915_init_fixup_state_functions( struct i915_context *i915 )
+{
+ i915->saved_bind_fs_state = i915->base.bind_fs_state;
+ i915->base.bind_fs_state = i915_fixup_bind_fs_state;
+ i915->saved_bind_sampler_states = i915->base.bind_fragment_sampler_states;
+ i915->base.bind_fragment_sampler_states = i915_fixup_bind_sampler_states;
+ i915->saved_set_sampler_views = i915->base.set_fragment_sampler_views;
+ i915->base.set_fragment_sampler_views = i915_fixup_set_fragment_sampler_views;
}