+
+static uint8
+translate_comparison_func(unsigned func)
+{
+ switch (func) {
+ case PIPE_FUNC_NEVER:
+ return SVGA3D_COMPARISON_NEVER;
+ case PIPE_FUNC_LESS:
+ return SVGA3D_COMPARISON_LESS;
+ case PIPE_FUNC_EQUAL:
+ return SVGA3D_COMPARISON_EQUAL;
+ case PIPE_FUNC_LEQUAL:
+ return SVGA3D_COMPARISON_LESS_EQUAL;
+ case PIPE_FUNC_GREATER:
+ return SVGA3D_COMPARISON_GREATER;
+ case PIPE_FUNC_NOTEQUAL:
+ return SVGA3D_COMPARISON_NOT_EQUAL;
+ case PIPE_FUNC_GEQUAL:
+ return SVGA3D_COMPARISON_GREATER_EQUAL;
+ case PIPE_FUNC_ALWAYS:
+ return SVGA3D_COMPARISON_ALWAYS;
+ default:
+ assert(!"Invalid comparison function");
+ return SVGA3D_COMPARISON_ALWAYS;
+ }
+}
+
+
+/**
+ * Translate filtering state to vgpu10 format.
+ */
+static SVGA3dFilter
+translate_filter_mode(unsigned img_filter,
+ unsigned min_filter,
+ unsigned mag_filter,
+ boolean anisotropic,
+ boolean compare)
+{
+ SVGA3dFilter mode = 0;
+
+ if (img_filter == PIPE_TEX_FILTER_LINEAR)
+ mode |= SVGA3D_FILTER_MIP_LINEAR;
+ if (min_filter == PIPE_TEX_FILTER_LINEAR)
+ mode |= SVGA3D_FILTER_MIN_LINEAR;
+ if (mag_filter == PIPE_TEX_FILTER_LINEAR)
+ mode |= SVGA3D_FILTER_MAG_LINEAR;
+ if (anisotropic)
+ mode |= SVGA3D_FILTER_ANISOTROPIC;
+ if (compare)
+ mode |= SVGA3D_FILTER_COMPARE;
+
+ return mode;
+}
+
+
+/**
+ * Define a vgpu10 sampler state.
+ */
+static void
+define_sampler_state_object(struct svga_context *svga,
+ struct svga_sampler_state *ss,
+ const struct pipe_sampler_state *ps)
+{
+ uint8_t max_aniso = (uint8_t) 255; /* XXX fix me */
+ boolean anisotropic;
+ uint8 compare_func;
+ SVGA3dFilter filter;
+ SVGA3dRGBAFloat bcolor;
+ unsigned try;
+ float min_lod, max_lod;
+
+ assert(svga_have_vgpu10(svga));
+
+ anisotropic = ss->aniso_level > 1.0f;
+
+ filter = translate_filter_mode(ps->min_mip_filter,
+ ps->min_img_filter,
+ ps->mag_img_filter,
+ anisotropic,
+ ss->compare_mode);
+
+ compare_func = translate_comparison_func(ss->compare_func);
+
+ COPY_4V(bcolor.value, ps->border_color.f);
+
+ assert(ps->min_lod <= ps->max_lod);
+
+ if (ps->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
+ /* just use the base level image */
+ min_lod = max_lod = 0.0f;
+ }
+ else {
+ min_lod = ps->min_lod;
+ max_lod = ps->max_lod;
+ }
+
+ /* If shadow comparisons are enabled, create two sampler states: one
+ * with the given shadow compare mode, another with shadow comparison off.
+ * We need the later because in some cases, we have to do the shadow
+ * compare in the shader. So, we don't want to do it twice.
+ */
+ STATIC_ASSERT(PIPE_TEX_COMPARE_NONE == 0);
+ STATIC_ASSERT(PIPE_TEX_COMPARE_R_TO_TEXTURE == 1);
+ ss->id[1] = SVGA3D_INVALID_ID;
+
+ unsigned i;
+ for (i = 0; i <= ss->compare_mode; i++) {
+ ss->id[i] = util_bitmask_add(svga->sampler_object_id_bm);
+
+ /* Loop in case command buffer is full and we need to flush and retry */
+ for (try = 0; try < 2; try++) {
+ enum pipe_error ret =
+ SVGA3D_vgpu10_DefineSamplerState(svga->swc,
+ ss->id[i],
+ filter,
+ ss->addressu,
+ ss->addressv,
+ ss->addressw,
+ ss->lod_bias, /* float */
+ max_aniso,
+ compare_func,
+ bcolor,
+ min_lod, /* float */
+ max_lod); /* float */
+ if (ret == PIPE_OK)
+ break;
+ svga_context_flush(svga, NULL);
+ }
+
+ /* turn off the shadow compare option for second iteration */
+ filter &= ~SVGA3D_FILTER_COMPARE;
+ }
+}
+
+