+/*
+ * Copyright 2008 Ben Skeggs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
-#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+#include "tgsi/tgsi_parse.h"
#include "nv50_context.h"
-#include "nv50_state.h"
+#include "nv50_texture.h"
#include "nouveau/nouveau_stateobj.h"
so_data(so, 1);
so_method(so, tesla, NV50TCL_BLEND_EQUATION_RGB, 5);
so_data (so, nvgl_blend_eqn(cso->rgb_func));
- so_data (so, nvgl_blend_func(cso->rgb_src_factor));
- so_data (so, nvgl_blend_func(cso->rgb_dst_factor));
+ so_data (so, 0x4000 | nvgl_blend_func(cso->rgb_src_factor));
+ so_data (so, 0x4000 | nvgl_blend_func(cso->rgb_dst_factor));
so_data (so, nvgl_blend_eqn(cso->alpha_func));
- so_data (so, nvgl_blend_func(cso->alpha_src_factor));
+ so_data (so, 0x4000 | nvgl_blend_func(cso->alpha_src_factor));
so_method(so, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1);
- so_data (so, nvgl_blend_func(cso->alpha_dst_factor));
+ so_data (so, 0x4000 | nvgl_blend_func(cso->alpha_dst_factor));
}
if (cso->logicop_enable == 0 ) {
FREE(bso);
}
+static INLINE unsigned
+wrap_mode(unsigned wrap)
+{
+ switch (wrap) {
+ case PIPE_TEX_WRAP_REPEAT:
+ return NV50TSC_1_0_WRAPS_REPEAT;
+ case PIPE_TEX_WRAP_MIRROR_REPEAT:
+ return NV50TSC_1_0_WRAPS_MIRROR_REPEAT;
+ case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
+ return NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE;
+ case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
+ return NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER;
+ case PIPE_TEX_WRAP_CLAMP:
+ return NV50TSC_1_0_WRAPS_CLAMP;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
+ return NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_EDGE;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
+ return NV50TSC_1_0_WRAPS_MIRROR_CLAMP_TO_BORDER;
+ case PIPE_TEX_WRAP_MIRROR_CLAMP:
+ return NV50TSC_1_0_WRAPS_MIRROR_CLAMP;
+ default:
+ NOUVEAU_ERR("unknown wrap mode: %d\n", wrap);
+ return NV50TSC_1_0_WRAPS_REPEAT;
+ }
+}
static void *
nv50_sampler_state_create(struct pipe_context *pipe,
const struct pipe_sampler_state *cso)
{
- return NULL;
+ unsigned *tsc = CALLOC(8, sizeof(unsigned));
+
+ tsc[0] = (0x00024000 |
+ (wrap_mode(cso->wrap_s) << 0) |
+ (wrap_mode(cso->wrap_t) << 3) |
+ (wrap_mode(cso->wrap_r) << 6));
+
+ switch (cso->mag_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ tsc[1] |= NV50TSC_1_1_MAGF_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ tsc[1] |= NV50TSC_1_1_MAGF_NEAREST;
+ break;
+ }
+
+ switch (cso->min_img_filter) {
+ case PIPE_TEX_FILTER_LINEAR:
+ tsc[1] |= NV50TSC_1_1_MINF_LINEAR;
+ break;
+ case PIPE_TEX_FILTER_NEAREST:
+ default:
+ tsc[1] |= NV50TSC_1_1_MINF_NEAREST;
+ break;
+ }
+
+ switch (cso->min_mip_filter) {
+ case PIPE_TEX_MIPFILTER_LINEAR:
+ tsc[1] |= NV50TSC_1_1_MIPF_LINEAR;
+ break;
+ case PIPE_TEX_MIPFILTER_NEAREST:
+ tsc[1] |= NV50TSC_1_1_MIPF_NEAREST;
+ break;
+ case PIPE_TEX_MIPFILTER_NONE:
+ default:
+ tsc[1] |= NV50TSC_1_1_MIPF_NONE;
+ break;
+ }
+
+ if (cso->max_anisotropy >= 16.0)
+ tsc[0] |= (7 << 20);
+ else
+ if (cso->max_anisotropy >= 12.0)
+ tsc[0] |= (6 << 20);
+ else
+ if (cso->max_anisotropy >= 10.0)
+ tsc[0] |= (5 << 20);
+ else
+ if (cso->max_anisotropy >= 8.0)
+ tsc[0] |= (4 << 20);
+ else
+ if (cso->max_anisotropy >= 6.0)
+ tsc[0] |= (3 << 20);
+ else
+ if (cso->max_anisotropy >= 4.0)
+ tsc[0] |= (2 << 20);
+ else
+ if (cso->max_anisotropy >= 2.0)
+ tsc[0] |= (1 << 20);
+
+ if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
+ tsc[0] |= (1 << 8);
+ tsc[0] |= (nvgl_comparison_op(cso->compare_func) & 0x7);
+ }
+
+ return (void *)tsc;
}
static void
nv50_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler)
{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ int i;
+
+ nv50->sampler_nr = nr;
+ for (i = 0; i < nv50->sampler_nr; i++)
+ nv50->sampler[i] = sampler[i];
+
+ nv50->dirty |= NV50_NEW_SAMPLER;
}
static void
nv50_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
{
+ FREE(hwcso);
}
static void
nv50_set_sampler_texture(struct pipe_context *pipe, unsigned nr,
struct pipe_texture **pt)
{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ int i;
+
+ for (i = 0; i < nr; i++)
+ pipe_texture_reference((void *)&nv50->miptree[i], pt[i]);
+ for (i = nr; i < nv50->miptree_nr; i++)
+ pipe_texture_reference((void *)&nv50->miptree[i], NULL);
+
+ nv50->miptree_nr = nr;
+ nv50->dirty |= NV50_NEW_TEXTURE;
}
static void *
struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
struct nv50_rasterizer_stateobj *rso =
CALLOC_STRUCT(nv50_rasterizer_stateobj);
- unsigned i;
/*XXX: ignored
* - light_twosize
so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1);
so_data (so, 1);
so_method(so, tesla, NV50TCL_LINE_STIPPLE_PATTERN, 1);
- so_data (so, (cso->line_stipple_pattern << 16) |
+ so_data (so, (cso->line_stipple_pattern << 8) |
cso->line_stipple_factor);
} else {
so_method(so, tesla, NV50TCL_LINE_STIPPLE_ENABLE, 1);
so_method(so, tesla, NV50TCL_POLYGON_OFFSET_FACTOR, 1);
so_data (so, fui(cso->offset_scale));
so_method(so, tesla, NV50TCL_POLYGON_OFFSET_UNITS, 1);
- so_data (so, fui(cso->offset_units * 2));
+ so_data (so, fui(cso->offset_units));
}
rso->pipe = *cso;
so_data (so, 0);
}
+ /*XXX: yes, I know they're backwards.. header needs fixing */
if (cso->stencil[0].enabled) {
- so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 5);
+ so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 5);
so_data (so, 1);
so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op));
so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
so_data (so, nvgl_comparison_op(cso->stencil[0].func));
- so_method(so, tesla, NV50TCL_STENCIL_FRONT_FUNC_REF, 3);
+ so_method(so, tesla, NV50TCL_STENCIL_BACK_FUNC_REF, 3);
so_data (so, cso->stencil[0].ref_value);
- so_data (so, cso->stencil[0].write_mask);
- so_data (so, cso->stencil[0].value_mask);
+ so_data (so, cso->stencil[0].writemask);
+ so_data (so, cso->stencil[0].valuemask);
} else {
- so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 1);
+ so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 1);
so_data (so, 0);
}
if (cso->stencil[1].enabled) {
- so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 8);
+ so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 8);
so_data (so, 1);
so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op));
so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
so_data (so, nvgl_comparison_op(cso->stencil[1].func));
so_data (so, cso->stencil[1].ref_value);
- so_data (so, cso->stencil[1].write_mask);
- so_data (so, cso->stencil[1].value_mask);
+ so_data (so, cso->stencil[1].writemask);
+ so_data (so, cso->stencil[1].valuemask);
} else {
- so_method(so, tesla, NV50TCL_STENCIL_BACK_ENABLE, 1);
+ so_method(so, tesla, NV50TCL_STENCIL_FRONT_ENABLE, 1);
so_data (so, 0);
}
nv50_vp_state_create(struct pipe_context *pipe,
const struct pipe_shader_state *cso)
{
- return NULL;
+ struct nv50_program *p = CALLOC_STRUCT(nv50_program);
+
+ p->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ p->type = PIPE_SHADER_VERTEX;
+ tgsi_scan_shader(p->pipe.tokens, &p->info);
+ return (void *)p;
}
static void
nv50_vp_state_bind(struct pipe_context *pipe, void *hwcso)
{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->vertprog = hwcso;
+ nv50->dirty |= NV50_NEW_VERTPROG;
}
static void
nv50_vp_state_delete(struct pipe_context *pipe, void *hwcso)
{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nv50_program *p = hwcso;
+
+ nv50_program_destroy(nv50, p);
+ FREE((void*)p->pipe.tokens);
+ FREE(p);
}
static void *
nv50_fp_state_create(struct pipe_context *pipe,
const struct pipe_shader_state *cso)
{
- return NULL;
+ struct nv50_program *p = CALLOC_STRUCT(nv50_program);
+
+ p->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ p->type = PIPE_SHADER_FRAGMENT;
+ tgsi_scan_shader(p->pipe.tokens, &p->info);
+ return (void *)p;
}
static void
nv50_fp_state_bind(struct pipe_context *pipe, void *hwcso)
{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->fragprog = hwcso;
+ nv50->dirty |= NV50_NEW_FRAGPROG;
}
static void
nv50_fp_state_delete(struct pipe_context *pipe, void *hwcso)
{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nv50_program *p = hwcso;
+
+ nv50_program_destroy(nv50, p);
+ FREE((void*)p->pipe.tokens);
+ FREE(p);
}
static void
nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
const struct pipe_constant_buffer *buf )
{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ if (shader == PIPE_SHADER_VERTEX) {
+ nv50->constbuf[PIPE_SHADER_VERTEX] = buf->buffer;
+ nv50->dirty |= NV50_NEW_VERTPROG_CB;
+ } else
+ if (shader == PIPE_SHADER_FRAGMENT) {
+ nv50->constbuf[PIPE_SHADER_FRAGMENT] = buf->buffer;
+ nv50->dirty |= NV50_NEW_FRAGPROG_CB;
+ }
}
static void
nv50_set_vertex_buffers(struct pipe_context *pipe, unsigned count,
const struct pipe_vertex_buffer *vb)
{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ memcpy(nv50->vtxbuf, vb, sizeof(*vb) * count);
+ nv50->vtxbuf_nr = count;
+
+ nv50->dirty |= NV50_NEW_ARRAYS;
}
static void
nv50_set_vertex_elements(struct pipe_context *pipe, unsigned count,
const struct pipe_vertex_element *ve)
{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ memcpy(nv50->vtxelt, ve, sizeof(*ve) * count);
+ nv50->vtxelt_nr = count;
+
+ nv50->dirty |= NV50_NEW_ARRAYS;
}
void