14a49301eSmrg/**************************************************************************
27ec681f3Smrg *
3af69d88dSmrg * Copyright 2007 VMware, Inc.
44a49301eSmrg * All Rights Reserved.
54a49301eSmrg *
64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a
74a49301eSmrg * copy of this software and associated documentation files (the
84a49301eSmrg * "Software"), to deal in the Software without restriction, including
94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish,
104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to
114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to
124a49301eSmrg * the following conditions:
137ec681f3Smrg *
144a49301eSmrg * The above copyright notice and this permission notice (including the
154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions
164a49301eSmrg * of the Software.
177ec681f3Smrg *
184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
257ec681f3Smrg *
264a49301eSmrg **************************************************************************/
274a49301eSmrg
28af69d88dSmrg/* Authors:  Keith Whitwell <keithw@vmware.com>
294a49301eSmrg */
304a49301eSmrg
317ec681f3Smrg#include "compiler/nir/nir_builder.h"
324a49301eSmrg#include "draw/draw_context.h"
337ec681f3Smrg#include "nir/nir_to_tgsi.h"
347ec681f3Smrg#include "tgsi/tgsi_parse.h"
35af69d88dSmrg#include "util/u_helpers.h"
36cdc920a0Smrg#include "util/u_inlines.h"
374a49301eSmrg#include "util/u_math.h"
384a49301eSmrg#include "util/u_memory.h"
393464ebd5Sriastradh#include "util/u_transfer.h"
407ec681f3Smrg#include "nir.h"
414a49301eSmrg
424a49301eSmrg#include "i915_context.h"
434a49301eSmrg#include "i915_fpc.h"
447ec681f3Smrg#include "i915_reg.h"
453464ebd5Sriastradh#include "i915_resource.h"
46af69d88dSmrg#include "i915_state.h"
477ec681f3Smrg#include "i915_state_inlines.h"
484a49301eSmrg
494a49301eSmrg/* The i915 (and related graphics cores) do not support GL_CLAMP.  The
504a49301eSmrg * Intel drivers for "other operating systems" implement GL_CLAMP as
514a49301eSmrg * GL_CLAMP_TO_EDGE, so the same is done here.
524a49301eSmrg */
534a49301eSmrgstatic unsigned
544a49301eSmrgtranslate_wrap_mode(unsigned wrap)
554a49301eSmrg{
564a49301eSmrg   switch (wrap) {
574a49301eSmrg   case PIPE_TEX_WRAP_REPEAT:
584a49301eSmrg      return TEXCOORDMODE_WRAP;
594a49301eSmrg   case PIPE_TEX_WRAP_CLAMP:
607ec681f3Smrg      return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */
614a49301eSmrg   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
624a49301eSmrg      return TEXCOORDMODE_CLAMP_EDGE;
634a49301eSmrg   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
644a49301eSmrg      return TEXCOORDMODE_CLAMP_BORDER;
653464ebd5Sriastradh   case PIPE_TEX_WRAP_MIRROR_REPEAT:
664a49301eSmrg      return TEXCOORDMODE_MIRROR;
674a49301eSmrg   default:
684a49301eSmrg      return TEXCOORDMODE_WRAP;
694a49301eSmrg   }
704a49301eSmrg}
714a49301eSmrg
727ec681f3Smrgstatic unsigned
737ec681f3Smrgtranslate_img_filter(unsigned filter)
744a49301eSmrg{
754a49301eSmrg   switch (filter) {
764a49301eSmrg   case PIPE_TEX_FILTER_NEAREST:
774a49301eSmrg      return FILTER_NEAREST;
784a49301eSmrg   case PIPE_TEX_FILTER_LINEAR:
794a49301eSmrg      return FILTER_LINEAR;
804a49301eSmrg   default:
814a49301eSmrg      assert(0);
824a49301eSmrg      return FILTER_NEAREST;
834a49301eSmrg   }
844a49301eSmrg}
854a49301eSmrg
867ec681f3Smrgstatic unsigned
877ec681f3Smrgtranslate_mip_filter(unsigned filter)
884a49301eSmrg{
894a49301eSmrg   switch (filter) {
904a49301eSmrg   case PIPE_TEX_MIPFILTER_NONE:
914a49301eSmrg      return MIPFILTER_NONE;
924a49301eSmrg   case PIPE_TEX_MIPFILTER_NEAREST:
934a49301eSmrg      return MIPFILTER_NEAREST;
944a49301eSmrg   case PIPE_TEX_MIPFILTER_LINEAR:
954a49301eSmrg      return MIPFILTER_LINEAR;
964a49301eSmrg   default:
974a49301eSmrg      assert(0);
984a49301eSmrg      return MIPFILTER_NONE;
994a49301eSmrg   }
1004a49301eSmrg}
1014a49301eSmrg
1027ec681f3Smrgstatic uint32_t
1037ec681f3Smrgi915_remap_lis6_blend_dst_alpha(uint32_t lis6, uint32_t normal, uint32_t inv)
1047ec681f3Smrg{
1057ec681f3Smrg   uint32_t src = (lis6 >> S6_CBUF_SRC_BLEND_FACT_SHIFT) & BLENDFACT_MASK;
1067ec681f3Smrg   lis6 &= ~SRC_BLND_FACT(BLENDFACT_MASK);
1077ec681f3Smrg   if (src == BLENDFACT_DST_ALPHA)
1087ec681f3Smrg      src = normal;
1097ec681f3Smrg   else if (src == BLENDFACT_INV_DST_ALPHA)
1107ec681f3Smrg      src = inv;
1117ec681f3Smrg   lis6 |= SRC_BLND_FACT(src);
1127ec681f3Smrg
1137ec681f3Smrg   uint32_t dst = (lis6 >> S6_CBUF_DST_BLEND_FACT_SHIFT) & BLENDFACT_MASK;
1147ec681f3Smrg   lis6 &= ~DST_BLND_FACT(BLENDFACT_MASK);
1157ec681f3Smrg   if (dst == BLENDFACT_DST_ALPHA)
1167ec681f3Smrg      dst = normal;
1177ec681f3Smrg   else if (dst == BLENDFACT_INV_DST_ALPHA)
1187ec681f3Smrg      dst = inv;
1197ec681f3Smrg   lis6 |= DST_BLND_FACT(dst);
1207ec681f3Smrg
1217ec681f3Smrg   return lis6;
1227ec681f3Smrg}
1237ec681f3Smrg
1247ec681f3Smrgstatic uint32_t
1257ec681f3Smrgi915_remap_iab_blend_dst_alpha(uint32_t iab, uint32_t normal, uint32_t inv)
1267ec681f3Smrg{
1277ec681f3Smrg   uint32_t src = (iab >> IAB_SRC_FACTOR_SHIFT) & BLENDFACT_MASK;
1287ec681f3Smrg   iab &= ~SRC_BLND_FACT(BLENDFACT_MASK);
1297ec681f3Smrg   if (src == BLENDFACT_DST_ALPHA)
1307ec681f3Smrg      src = normal;
1317ec681f3Smrg   else if (src == BLENDFACT_INV_DST_ALPHA)
1327ec681f3Smrg      src = inv;
1337ec681f3Smrg   iab |= SRC_ABLND_FACT(src);
1347ec681f3Smrg
1357ec681f3Smrg   uint32_t dst = (iab >> IAB_DST_FACTOR_SHIFT) & BLENDFACT_MASK;
1367ec681f3Smrg   iab &= ~DST_BLND_FACT(BLENDFACT_MASK);
1377ec681f3Smrg   if (dst == BLENDFACT_DST_ALPHA)
1387ec681f3Smrg      dst = normal;
1397ec681f3Smrg   else if (dst == BLENDFACT_INV_DST_ALPHA)
1407ec681f3Smrg      dst = inv;
1417ec681f3Smrg   iab |= DST_ABLND_FACT(dst);
1427ec681f3Smrg
1437ec681f3Smrg   return iab;
1447ec681f3Smrg}
1457ec681f3Smrg
1464a49301eSmrg/* None of this state is actually used for anything yet.
1474a49301eSmrg */
1484a49301eSmrgstatic void *
1494a49301eSmrgi915_create_blend_state(struct pipe_context *pipe,
1504a49301eSmrg                        const struct pipe_blend_state *blend)
1514a49301eSmrg{
1527ec681f3Smrg   struct i915_blend_state *cso_data = CALLOC_STRUCT(i915_blend_state);
1534a49301eSmrg
1544a49301eSmrg   {
1557ec681f3Smrg      unsigned eqRGB = blend->rt[0].rgb_func;
156cdc920a0Smrg      unsigned srcRGB = blend->rt[0].rgb_src_factor;
157cdc920a0Smrg      unsigned dstRGB = blend->rt[0].rgb_dst_factor;
1584a49301eSmrg
1597ec681f3Smrg      unsigned eqA = blend->rt[0].alpha_func;
1607ec681f3Smrg      unsigned srcA = blend->rt[0].alpha_src_factor;
1617ec681f3Smrg      unsigned dstA = blend->rt[0].alpha_dst_factor;
1624a49301eSmrg
1634a49301eSmrg      /* Special handling for MIN/MAX filter modes handled at
1647ec681f3Smrg       * frontend level.
1654a49301eSmrg       */
1664a49301eSmrg
1677ec681f3Smrg      if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) {
1684a49301eSmrg
169af69d88dSmrg         cso_data->iab = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
1707ec681f3Smrg                          IAB_MODIFY_ENABLE | IAB_ENABLE | IAB_MODIFY_FUNC |
1717ec681f3Smrg                          IAB_MODIFY_SRC_FACTOR | IAB_MODIFY_DST_FACTOR |
1724a49301eSmrg                          SRC_ABLND_FACT(i915_translate_blend_factor(srcA)) |
1734a49301eSmrg                          DST_ABLND_FACT(i915_translate_blend_factor(dstA)) |
1744a49301eSmrg                          (i915_translate_blend_func(eqA) << IAB_FUNC_SHIFT));
1757ec681f3Smrg      } else {
1767ec681f3Smrg         cso_data->iab =
1777ec681f3Smrg            (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | IAB_MODIFY_ENABLE | 0);
1784a49301eSmrg      }
1794a49301eSmrg   }
1804a49301eSmrg
1817ec681f3Smrg   cso_data->modes4 |=
1827ec681f3Smrg      (_3DSTATE_MODES_4_CMD | ENABLE_LOGIC_OP_FUNC |
1837ec681f3Smrg       LOGIC_OP_FUNC(i915_translate_logic_op(blend->logicop_func)));
1844a49301eSmrg
1854a49301eSmrg   if (blend->logicop_enable)
1864a49301eSmrg      cso_data->LIS5 |= S5_LOGICOP_ENABLE;
1874a49301eSmrg
1884a49301eSmrg   if (blend->dither)
1894a49301eSmrg      cso_data->LIS5 |= S5_COLOR_DITHER_ENABLE;
1904a49301eSmrg
191af69d88dSmrg   /* We potentially do some fixup at emission for non-BGRA targets */
192cdc920a0Smrg   if ((blend->rt[0].colormask & PIPE_MASK_R) == 0)
1934a49301eSmrg      cso_data->LIS5 |= S5_WRITEDISABLE_RED;
1944a49301eSmrg
195cdc920a0Smrg   if ((blend->rt[0].colormask & PIPE_MASK_G) == 0)
1964a49301eSmrg      cso_data->LIS5 |= S5_WRITEDISABLE_GREEN;
1974a49301eSmrg
198cdc920a0Smrg   if ((blend->rt[0].colormask & PIPE_MASK_B) == 0)
1994a49301eSmrg      cso_data->LIS5 |= S5_WRITEDISABLE_BLUE;
2004a49301eSmrg
201cdc920a0Smrg   if ((blend->rt[0].colormask & PIPE_MASK_A) == 0)
2024a49301eSmrg      cso_data->LIS5 |= S5_WRITEDISABLE_ALPHA;
2034a49301eSmrg
204cdc920a0Smrg   if (blend->rt[0].blend_enable) {
205cdc920a0Smrg      unsigned funcRGB = blend->rt[0].rgb_func;
2067ec681f3Smrg      unsigned srcRGB = blend->rt[0].rgb_src_factor;
2077ec681f3Smrg      unsigned dstRGB = blend->rt[0].rgb_dst_factor;
2084a49301eSmrg
2097ec681f3Smrg      cso_data->LIS6 |=
2107ec681f3Smrg         (S6_CBUF_BLEND_ENABLE |
2117ec681f3Smrg          SRC_BLND_FACT(i915_translate_blend_factor(srcRGB)) |
2127ec681f3Smrg          DST_BLND_FACT(i915_translate_blend_factor(dstRGB)) |
2137ec681f3Smrg          (i915_translate_blend_func(funcRGB) << S6_CBUF_BLEND_FUNC_SHIFT));
2144a49301eSmrg   }
2154a49301eSmrg
2167ec681f3Smrg   cso_data->LIS6_alpha_in_g = i915_remap_lis6_blend_dst_alpha(
2177ec681f3Smrg      cso_data->LIS6, BLENDFACT_DST_COLR, BLENDFACT_INV_DST_COLR);
2187ec681f3Smrg   cso_data->LIS6_alpha_is_x = i915_remap_lis6_blend_dst_alpha(
2197ec681f3Smrg      cso_data->LIS6, BLENDFACT_ONE, BLENDFACT_ZERO);
2207ec681f3Smrg
2217ec681f3Smrg   cso_data->iab_alpha_in_g = i915_remap_iab_blend_dst_alpha(
2227ec681f3Smrg      cso_data->iab, BLENDFACT_DST_COLR, BLENDFACT_INV_DST_COLR);
2237ec681f3Smrg   cso_data->iab_alpha_is_x = i915_remap_iab_blend_dst_alpha(
2247ec681f3Smrg      cso_data->iab, BLENDFACT_ONE, BLENDFACT_ZERO);
2257ec681f3Smrg
2264a49301eSmrg   return cso_data;
2274a49301eSmrg}
2284a49301eSmrg
2297ec681f3Smrgstatic void
2307ec681f3Smrgi915_bind_blend_state(struct pipe_context *pipe, void *blend)
2314a49301eSmrg{
2324a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
233af69d88dSmrg
234af69d88dSmrg   if (i915->blend == blend)
235af69d88dSmrg      return;
2364a49301eSmrg
2377ec681f3Smrg   i915->blend = (struct i915_blend_state *)blend;
2384a49301eSmrg
2394a49301eSmrg   i915->dirty |= I915_NEW_BLEND;
2404a49301eSmrg}
2414a49301eSmrg
2427ec681f3Smrgstatic void
2437ec681f3Smrgi915_delete_blend_state(struct pipe_context *pipe, void *blend)
2444a49301eSmrg{
2454a49301eSmrg   FREE(blend);
2464a49301eSmrg}
2474a49301eSmrg
2487ec681f3Smrgstatic void
2497ec681f3Smrgi915_set_blend_color(struct pipe_context *pipe,
2507ec681f3Smrg                     const struct pipe_blend_color *blend_color)
2514a49301eSmrg{
2524a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
253af69d88dSmrg
254af69d88dSmrg   if (!blend_color)
255af69d88dSmrg      return;
2564a49301eSmrg
2574a49301eSmrg   i915->blend_color = *blend_color;
2584a49301eSmrg
2594a49301eSmrg   i915->dirty |= I915_NEW_BLEND;
2604a49301eSmrg}
2614a49301eSmrg
2627ec681f3Smrgstatic void
2637ec681f3Smrgi915_set_stencil_ref(struct pipe_context *pipe,
2647ec681f3Smrg                     const struct pipe_stencil_ref stencil_ref)
265cdc920a0Smrg{
266cdc920a0Smrg   struct i915_context *i915 = i915_context(pipe);
267cdc920a0Smrg
2687ec681f3Smrg   i915->stencil_ref = stencil_ref;
269cdc920a0Smrg
270cdc920a0Smrg   i915->dirty |= I915_NEW_DEPTH_STENCIL;
271cdc920a0Smrg}
272cdc920a0Smrg
2734a49301eSmrgstatic void *
2744a49301eSmrgi915_create_sampler_state(struct pipe_context *pipe,
2754a49301eSmrg                          const struct pipe_sampler_state *sampler)
2764a49301eSmrg{
2777ec681f3Smrg   struct i915_sampler_state *cso = CALLOC_STRUCT(i915_sampler_state);
2784a49301eSmrg   const unsigned ws = sampler->wrap_s;
2794a49301eSmrg   const unsigned wt = sampler->wrap_t;
2804a49301eSmrg   const unsigned wr = sampler->wrap_r;
2814a49301eSmrg   unsigned minFilt, magFilt;
2824a49301eSmrg   unsigned mipFilt;
2834a49301eSmrg
284af69d88dSmrg   cso->templ = *sampler;
2854a49301eSmrg
2864a49301eSmrg   mipFilt = translate_mip_filter(sampler->min_mip_filter);
2877ec681f3Smrg   minFilt = translate_img_filter(sampler->min_img_filter);
2887ec681f3Smrg   magFilt = translate_img_filter(sampler->mag_img_filter);
289af69d88dSmrg
290cdc920a0Smrg   if (sampler->max_anisotropy > 1)
291cdc920a0Smrg      minFilt = magFilt = FILTER_ANISOTROPIC;
292cdc920a0Smrg
293cdc920a0Smrg   if (sampler->max_anisotropy > 2) {
2944a49301eSmrg      cso->state[0] |= SS2_MAX_ANISO_4;
2954a49301eSmrg   }
2964a49301eSmrg
2974a49301eSmrg   {
2987ec681f3Smrg      int b = (int)(sampler->lod_bias * 16.0);
2994a49301eSmrg      b = CLAMP(b, -256, 255);
3004a49301eSmrg      cso->state[0] |= ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK);
3014a49301eSmrg   }
3024a49301eSmrg
3034a49301eSmrg   /* Shadow:
3044a49301eSmrg    */
3057ec681f3Smrg   if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
3067ec681f3Smrg      cso->state[0] |= (SS2_SHADOW_ENABLE | i915_translate_shadow_compare_func(
3077ec681f3Smrg                                               sampler->compare_func));
3084a49301eSmrg
3094a49301eSmrg      minFilt = FILTER_4X4_FLAT;
3104a49301eSmrg      magFilt = FILTER_4X4_FLAT;
3114a49301eSmrg   }
3124a49301eSmrg
3137ec681f3Smrg   cso->state[0] |=
3147ec681f3Smrg      ((minFilt << SS2_MIN_FILTER_SHIFT) | (mipFilt << SS2_MIP_FILTER_SHIFT) |
3157ec681f3Smrg       (magFilt << SS2_MAG_FILTER_SHIFT));
3164a49301eSmrg
3177ec681f3Smrg   cso->state[1] |= ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) |
3187ec681f3Smrg                     (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) |
3197ec681f3Smrg                     (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT));
3204a49301eSmrg
3214a49301eSmrg   if (sampler->normalized_coords)
3224a49301eSmrg      cso->state[1] |= SS3_NORMALIZED_COORDS;
3234a49301eSmrg
3244a49301eSmrg   {
3257ec681f3Smrg      int minlod = (int)(16.0 * sampler->min_lod);
3267ec681f3Smrg      int maxlod = (int)(16.0 * sampler->max_lod);
3274a49301eSmrg      minlod = CLAMP(minlod, 0, 16 * 11);
3284a49301eSmrg      maxlod = CLAMP(maxlod, 0, 16 * 11);
3294a49301eSmrg
3304a49301eSmrg      if (minlod > maxlod)
331af69d88dSmrg         maxlod = minlod;
3324a49301eSmrg
3334a49301eSmrg      cso->minlod = minlod;
3344a49301eSmrg      cso->maxlod = maxlod;
3354a49301eSmrg   }
3364a49301eSmrg
3374a49301eSmrg   {
338af69d88dSmrg      ubyte r = float_to_ubyte(sampler->border_color.f[0]);
339af69d88dSmrg      ubyte g = float_to_ubyte(sampler->border_color.f[1]);
340af69d88dSmrg      ubyte b = float_to_ubyte(sampler->border_color.f[2]);
341af69d88dSmrg      ubyte a = float_to_ubyte(sampler->border_color.f[3]);
3424a49301eSmrg      cso->state[2] = I915PACKCOLOR8888(r, g, b, a);
3434a49301eSmrg   }
3444a49301eSmrg   return cso;
3454a49301eSmrg}
3464a49301eSmrg
347af69d88dSmrgstatic void
3487ec681f3Smrgi915_bind_sampler_states(struct pipe_context *pipe,
3497ec681f3Smrg                         enum pipe_shader_type shader, unsigned start,
3507ec681f3Smrg                         unsigned num, void **samplers)
3513464ebd5Sriastradh{
3527ec681f3Smrg   if (shader != PIPE_SHADER_FRAGMENT) {
3537ec681f3Smrg      assert(num == 0);
354af69d88dSmrg      return;
355af69d88dSmrg   }
356af69d88dSmrg
3574a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
3584a49301eSmrg   unsigned i;
3594a49301eSmrg
3604a49301eSmrg   /* Check for no-op */
3614a49301eSmrg   if (num == i915->num_samplers &&
3627ec681f3Smrg       !memcmp(i915->fragment_sampler + start, samplers, num * sizeof(void *)))
3634a49301eSmrg      return;
3644a49301eSmrg
3654a49301eSmrg   for (i = 0; i < num; ++i)
366af69d88dSmrg      i915->fragment_sampler[i + start] = samplers[i];
3674a49301eSmrg
368af69d88dSmrg   /* find highest non-null samplers[] entry */
369af69d88dSmrg   {
370af69d88dSmrg      unsigned j = MAX2(i915->num_samplers, start + num);
371af69d88dSmrg      while (j > 0 && i915->fragment_sampler[j - 1] == NULL)
372af69d88dSmrg         j--;
373af69d88dSmrg      i915->num_samplers = j;
374af69d88dSmrg   }
3754a49301eSmrg
3764a49301eSmrg   i915->dirty |= I915_NEW_SAMPLER;
3774a49301eSmrg}
3784a49301eSmrg
379af69d88dSmrgstatic void
3807ec681f3Smrgi915_delete_sampler_state(struct pipe_context *pipe, void *sampler)
3814a49301eSmrg{
3824a49301eSmrg   FREE(sampler);
3834a49301eSmrg}
3844a49301eSmrg
3857ec681f3Smrg/** XXX move someday?  Or consolidate all these simple state setters
3867ec681f3Smrg * into one file.
387af69d88dSmrg */
388af69d88dSmrg
3897ec681f3Smrgstatic uint32_t
3907ec681f3Smrgi915_get_modes4_stencil(const struct pipe_stencil_state *stencil)
3917ec681f3Smrg{
3927ec681f3Smrg   int testmask = stencil->valuemask & 0xff;
3937ec681f3Smrg   int writemask = stencil->writemask & 0xff;
394af69d88dSmrg
3957ec681f3Smrg   return (_3DSTATE_MODES_4_CMD | ENABLE_STENCIL_TEST_MASK |
3967ec681f3Smrg           STENCIL_TEST_MASK(testmask) | ENABLE_STENCIL_WRITE_MASK |
3977ec681f3Smrg           STENCIL_WRITE_MASK(writemask));
398af69d88dSmrg}
399af69d88dSmrg
4007ec681f3Smrgstatic uint32_t
4017ec681f3Smrgi915_get_lis5_stencil(const struct pipe_stencil_state *stencil)
402af69d88dSmrg{
4037ec681f3Smrg   int test = i915_translate_compare_func(stencil->func);
4047ec681f3Smrg   int fop = i915_translate_stencil_op(stencil->fail_op);
4057ec681f3Smrg   int dfop = i915_translate_stencil_op(stencil->zfail_op);
4067ec681f3Smrg   int dpop = i915_translate_stencil_op(stencil->zpass_op);
4077ec681f3Smrg
4087ec681f3Smrg   return (S5_STENCIL_TEST_ENABLE | S5_STENCIL_WRITE_ENABLE |
4097ec681f3Smrg           (test << S5_STENCIL_TEST_FUNC_SHIFT) |
4107ec681f3Smrg           (fop << S5_STENCIL_FAIL_SHIFT) |
4117ec681f3Smrg           (dfop << S5_STENCIL_PASS_Z_FAIL_SHIFT) |
4127ec681f3Smrg           (dpop << S5_STENCIL_PASS_Z_PASS_SHIFT));
413af69d88dSmrg}
414af69d88dSmrg
4157ec681f3Smrgstatic uint32_t
4167ec681f3Smrgi915_get_bfo(const struct pipe_stencil_state *stencil)
4177ec681f3Smrg{
4187ec681f3Smrg   int test = i915_translate_compare_func(stencil->func);
4197ec681f3Smrg   int fop = i915_translate_stencil_op(stencil->fail_op);
4207ec681f3Smrg   int dfop = i915_translate_stencil_op(stencil->zfail_op);
4217ec681f3Smrg   int dpop = i915_translate_stencil_op(stencil->zpass_op);
4227ec681f3Smrg
4237ec681f3Smrg   return (_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_FUNCS |
4247ec681f3Smrg           BFO_ENABLE_STENCIL_TWO_SIDE | BFO_ENABLE_STENCIL_REF |
4257ec681f3Smrg           BFO_STENCIL_TWO_SIDE | (test << BFO_STENCIL_TEST_SHIFT) |
4267ec681f3Smrg           (fop << BFO_STENCIL_FAIL_SHIFT) |
4277ec681f3Smrg           (dfop << BFO_STENCIL_PASS_Z_FAIL_SHIFT) |
4287ec681f3Smrg           (dpop << BFO_STENCIL_PASS_Z_PASS_SHIFT));
4297ec681f3Smrg}
430af69d88dSmrg
4317ec681f3Smrgstatic uint32_t
4327ec681f3Smrgi915_get_bfm(const struct pipe_stencil_state *stencil)
4337ec681f3Smrg{
4347ec681f3Smrg   return (_3DSTATE_BACKFACE_STENCIL_MASKS | BFM_ENABLE_STENCIL_TEST_MASK |
4357ec681f3Smrg           BFM_ENABLE_STENCIL_WRITE_MASK |
4367ec681f3Smrg           ((stencil->valuemask & 0xff) << BFM_STENCIL_TEST_MASK_SHIFT) |
4377ec681f3Smrg           ((stencil->writemask & 0xff) << BFM_STENCIL_WRITE_MASK_SHIFT));
4387ec681f3Smrg}
4394a49301eSmrg
4404a49301eSmrgstatic void *
4417ec681f3Smrgi915_create_depth_stencil_state(
4427ec681f3Smrg   struct pipe_context *pipe,
4437ec681f3Smrg   const struct pipe_depth_stencil_alpha_state *depth_stencil)
4444a49301eSmrg{
4457ec681f3Smrg   struct i915_depth_stencil_state *cso =
4467ec681f3Smrg      CALLOC_STRUCT(i915_depth_stencil_state);
4474a49301eSmrg
4487ec681f3Smrg   cso->stencil_modes4_cw = i915_get_modes4_stencil(&depth_stencil->stencil[0]);
4497ec681f3Smrg   cso->stencil_modes4_ccw =
4507ec681f3Smrg      i915_get_modes4_stencil(&depth_stencil->stencil[1]);
4514a49301eSmrg
4524a49301eSmrg   if (depth_stencil->stencil[0].enabled) {
4537ec681f3Smrg      cso->stencil_LIS5_cw = i915_get_lis5_stencil(&depth_stencil->stencil[0]);
4544a49301eSmrg   }
4554a49301eSmrg
4564a49301eSmrg   if (depth_stencil->stencil[1].enabled) {
4577ec681f3Smrg      cso->bfo_cw[0] = i915_get_bfo(&depth_stencil->stencil[1]);
4587ec681f3Smrg      cso->bfo_cw[1] = i915_get_bfm(&depth_stencil->stencil[1]);
4597ec681f3Smrg
4607ec681f3Smrg      /* Precompute the backface stencil settings if front winding order is
4617ec681f3Smrg       * reversed -- HW doesn't have a bit to flip it for us.
4627ec681f3Smrg       */
4637ec681f3Smrg      cso->stencil_LIS5_ccw = i915_get_lis5_stencil(&depth_stencil->stencil[1]);
4647ec681f3Smrg      cso->bfo_ccw[0] = i915_get_bfo(&depth_stencil->stencil[0]);
4657ec681f3Smrg      cso->bfo_ccw[1] = i915_get_bfm(&depth_stencil->stencil[0]);
4667ec681f3Smrg   } else {
4674a49301eSmrg      /* This actually disables two-side stencil: The bit set is a
4684a49301eSmrg       * modify-enable bit to indicate we are changing the two-side
4694a49301eSmrg       * setting.  Then there is a symbolic zero to show that we are
4704a49301eSmrg       * setting the flag to zero/off.
4714a49301eSmrg       */
4727ec681f3Smrg      cso->bfo_cw[0] = cso->bfo_ccw[0] =
4737ec681f3Smrg         (_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0);
4747ec681f3Smrg      cso->bfo_cw[1] = cso->bfo_ccw[1] = 0;
4757ec681f3Smrg
4767ec681f3Smrg      cso->stencil_LIS5_ccw = cso->stencil_LIS5_cw;
4774a49301eSmrg   }
4784a49301eSmrg
4797ec681f3Smrg   if (depth_stencil->depth_enabled) {
4807ec681f3Smrg      int func = i915_translate_compare_func(depth_stencil->depth_func);
4814a49301eSmrg
4827ec681f3Smrg      cso->depth_LIS6 |=
4837ec681f3Smrg         (S6_DEPTH_TEST_ENABLE | (func << S6_DEPTH_TEST_FUNC_SHIFT));
4844a49301eSmrg
4857ec681f3Smrg      if (depth_stencil->depth_writemask)
486af69d88dSmrg         cso->depth_LIS6 |= S6_DEPTH_WRITE_ENABLE;
4874a49301eSmrg   }
4884a49301eSmrg
4897ec681f3Smrg   if (depth_stencil->alpha_enabled) {
4907ec681f3Smrg      int test = i915_translate_compare_func(depth_stencil->alpha_func);
4917ec681f3Smrg      ubyte refByte = float_to_ubyte(depth_stencil->alpha_ref_value);
4924a49301eSmrg
4937ec681f3Smrg      cso->depth_LIS6 |=
4947ec681f3Smrg         (S6_ALPHA_TEST_ENABLE | (test << S6_ALPHA_TEST_FUNC_SHIFT) |
4957ec681f3Smrg          (((unsigned)refByte) << S6_ALPHA_REF_SHIFT));
4964a49301eSmrg   }
4974a49301eSmrg
4984a49301eSmrg   return cso;
4994a49301eSmrg}
5004a49301eSmrg
5017ec681f3Smrgstatic void
5027ec681f3Smrgi915_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil)
5034a49301eSmrg{
5044a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
505af69d88dSmrg
506af69d88dSmrg   if (i915->depth_stencil == depth_stencil)
507af69d88dSmrg      return;
5084a49301eSmrg
5094a49301eSmrg   i915->depth_stencil = (const struct i915_depth_stencil_state *)depth_stencil;
5104a49301eSmrg
5114a49301eSmrg   i915->dirty |= I915_NEW_DEPTH_STENCIL;
5124a49301eSmrg}
5134a49301eSmrg
5147ec681f3Smrgstatic void
5157ec681f3Smrgi915_delete_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil)
5164a49301eSmrg{
5174a49301eSmrg   FREE(depth_stencil);
5184a49301eSmrg}
5194a49301eSmrg
5207ec681f3Smrgstatic void
5217ec681f3Smrgi915_set_scissor_states(struct pipe_context *pipe, unsigned start_slot,
5227ec681f3Smrg                        unsigned num_scissors,
5237ec681f3Smrg                        const struct pipe_scissor_state *scissor)
5244a49301eSmrg{
5254a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
5264a49301eSmrg
5277ec681f3Smrg   memcpy(&i915->scissor, scissor, sizeof(*scissor));
5284a49301eSmrg   i915->dirty |= I915_NEW_SCISSOR;
5294a49301eSmrg}
5304a49301eSmrg
5317ec681f3Smrgstatic void
5327ec681f3Smrgi915_set_polygon_stipple(struct pipe_context *pipe,
5337ec681f3Smrg                         const struct pipe_poly_stipple *stipple)
5344a49301eSmrg{
5354a49301eSmrg}
5364a49301eSmrg
5374a49301eSmrgstatic void *
5384a49301eSmrgi915_create_fs_state(struct pipe_context *pipe,
5394a49301eSmrg                     const struct pipe_shader_state *templ)
5404a49301eSmrg{
5414a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
5424a49301eSmrg   struct i915_fragment_shader *ifs = CALLOC_STRUCT(i915_fragment_shader);
5434a49301eSmrg   if (!ifs)
5444a49301eSmrg      return NULL;
5454a49301eSmrg
5463464ebd5Sriastradh   ifs->draw_data = draw_create_fragment_shader(i915->draw, templ);
5474a49301eSmrg
5487ec681f3Smrg   if (templ->type == PIPE_SHADER_IR_NIR) {
5497ec681f3Smrg      nir_shader *s = templ->ir.nir;
5507ec681f3Smrg
5517ec681f3Smrg      NIR_PASS_V(s, i915_nir_lower_sincos);
5527ec681f3Smrg
5537ec681f3Smrg      ifs->state.tokens = nir_to_tgsi(s, pipe->screen);
5547ec681f3Smrg   } else {
5557ec681f3Smrg      assert(templ->type == PIPE_SHADER_IR_TGSI);
5567ec681f3Smrg      /* we need to keep a local copy of the tokens */
5577ec681f3Smrg      ifs->state.tokens = tgsi_dup_tokens(templ->tokens);
5587ec681f3Smrg   }
5597ec681f3Smrg
5607ec681f3Smrg   ifs->state.type = PIPE_SHADER_IR_TGSI;
5617ec681f3Smrg
5627ec681f3Smrg   tgsi_scan_shader(ifs->state.tokens, &ifs->info);
5634a49301eSmrg
5644a49301eSmrg   /* The shader's compiled to i915 instructions here */
5654a49301eSmrg   i915_translate_fragment_program(i915, ifs);
5664a49301eSmrg
5674a49301eSmrg   return ifs;
5684a49301eSmrg}
5694a49301eSmrg
5704a49301eSmrgstatic void
5714a49301eSmrgi915_bind_fs_state(struct pipe_context *pipe, void *shader)
5724a49301eSmrg{
5734a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
574af69d88dSmrg
575af69d88dSmrg   if (i915->fs == shader)
576af69d88dSmrg      return;
5774a49301eSmrg
5787ec681f3Smrg   i915->fs = (struct i915_fragment_shader *)shader;
5797ec681f3Smrg
5807ec681f3Smrg   draw_bind_fragment_shader(i915->draw,
5817ec681f3Smrg                             (i915->fs ? i915->fs->draw_data : NULL));
5824a49301eSmrg
5837ec681f3Smrg   /* Tell draw if we need to do point sprites so we can get PNTC. */
5847ec681f3Smrg   if (i915->fs)
5857ec681f3Smrg      draw_wide_point_sprites(i915->draw, i915->fs->reads_pntc);
5863464ebd5Sriastradh
5874a49301eSmrg   i915->dirty |= I915_NEW_FS;
5884a49301eSmrg}
5894a49301eSmrg
5907ec681f3Smrgstatic void
5917ec681f3Smrgi915_delete_fs_state(struct pipe_context *pipe, void *shader)
5924a49301eSmrg{
5937ec681f3Smrg   struct i915_fragment_shader *ifs = (struct i915_fragment_shader *)shader;
594af69d88dSmrg
59501e04c3fSmrg   FREE(ifs->program);
59601e04c3fSmrg   ifs->program = NULL;
59701e04c3fSmrg   FREE((struct tgsi_token *)ifs->state.tokens);
59801e04c3fSmrg   ifs->state.tokens = NULL;
5994a49301eSmrg
600af69d88dSmrg   ifs->program_len = 0;
6014a49301eSmrg
6024a49301eSmrg   FREE(ifs);
6034a49301eSmrg}
6044a49301eSmrg
6054a49301eSmrgstatic void *
6064a49301eSmrgi915_create_vs_state(struct pipe_context *pipe,
6074a49301eSmrg                     const struct pipe_shader_state *templ)
6084a49301eSmrg{
6094a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
6104a49301eSmrg
6117ec681f3Smrg   struct pipe_shader_state from_nir = { PIPE_SHADER_IR_TGSI };
6127ec681f3Smrg   if (templ->type == PIPE_SHADER_IR_NIR) {
6137ec681f3Smrg      nir_shader *s = templ->ir.nir;
6147ec681f3Smrg
6157ec681f3Smrg      NIR_PASS_V(s, nir_lower_point_size, 1.0, 255.0);
6167ec681f3Smrg
6177ec681f3Smrg      /* The gallivm draw path doesn't support non-native-integers NIR shaders,
6187ec681f3Smrg       * st/mesa does native-integers for the screen as a whole rather than
6197ec681f3Smrg       * per-stage, and i915 FS can't do native integers.  So, convert to TGSI,
6207ec681f3Smrg       * where the draw path *does* support non-native-integers.
6217ec681f3Smrg       */
6227ec681f3Smrg      from_nir.tokens = nir_to_tgsi(s, pipe->screen);
6237ec681f3Smrg      templ = &from_nir;
6247ec681f3Smrg   }
6257ec681f3Smrg
6264a49301eSmrg   return draw_create_vertex_shader(i915->draw, templ);
6274a49301eSmrg}
6284a49301eSmrg
6297ec681f3Smrgstatic void
6307ec681f3Smrgi915_bind_vs_state(struct pipe_context *pipe, void *shader)
6314a49301eSmrg{
6324a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
6334a49301eSmrg
634af69d88dSmrg   if (i915->vs == shader)
635af69d88dSmrg      return;
636af69d88dSmrg
637af69d88dSmrg   i915->vs = shader;
6383464ebd5Sriastradh
6394a49301eSmrg   /* just pass-through to draw module */
6407ec681f3Smrg   draw_bind_vertex_shader(i915->draw, (struct draw_vertex_shader *)shader);
6414a49301eSmrg
6424a49301eSmrg   i915->dirty |= I915_NEW_VS;
6434a49301eSmrg}
6444a49301eSmrg
6457ec681f3Smrgstatic void
6467ec681f3Smrgi915_delete_vs_state(struct pipe_context *pipe, void *shader)
6474a49301eSmrg{
6484a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
6494a49301eSmrg
6504a49301eSmrg   /* just pass-through to draw module */
6517ec681f3Smrg   draw_delete_vertex_shader(i915->draw, (struct draw_vertex_shader *)shader);
6524a49301eSmrg}
6534a49301eSmrg
6547ec681f3Smrgstatic void
6557ec681f3Smrgi915_set_constant_buffer(struct pipe_context *pipe,
6567ec681f3Smrg                         enum pipe_shader_type shader, uint32_t index,
6577ec681f3Smrg                         bool take_ownership,
6587ec681f3Smrg                         const struct pipe_constant_buffer *cb)
6594a49301eSmrg{
6604a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
661af69d88dSmrg   struct pipe_resource *buf = cb ? cb->buffer : NULL;
6623464ebd5Sriastradh   unsigned new_num = 0;
6637ec681f3Smrg   bool diff = true;
6644a49301eSmrg
6653464ebd5Sriastradh   /* XXX don't support geom shaders now */
6663464ebd5Sriastradh   if (shader == PIPE_SHADER_GEOMETRY)
6673464ebd5Sriastradh      return;
6683464ebd5Sriastradh
669af69d88dSmrg   if (cb && cb->user_buffer) {
6707ec681f3Smrg      buf = i915_user_buffer_create(pipe->screen, (void *)cb->user_buffer,
6717ec681f3Smrg                                    cb->buffer_size, PIPE_BIND_CONSTANT_BUFFER);
672af69d88dSmrg   }
673af69d88dSmrg
6743464ebd5Sriastradh   /* if we have a new buffer compare it with the old one */
6754a49301eSmrg   if (buf) {
6763464ebd5Sriastradh      struct i915_buffer *ibuf = i915_buffer(buf);
6773464ebd5Sriastradh      struct pipe_resource *old_buf = i915->constants[shader];
6783464ebd5Sriastradh      struct i915_buffer *old = old_buf ? i915_buffer(old_buf) : NULL;
6793464ebd5Sriastradh      unsigned old_num = i915->current.num_user_constants[shader];
6803464ebd5Sriastradh
6817ec681f3Smrg      new_num = ibuf->b.width0 / 4 * sizeof(float);
6823464ebd5Sriastradh
6833464ebd5Sriastradh      if (old_num == new_num) {
6843464ebd5Sriastradh         if (old_num == 0)
6857ec681f3Smrg            diff = false;
6863464ebd5Sriastradh#if 0
6873464ebd5Sriastradh         /* XXX no point in running this code since st/mesa only uses user buffers */
6883464ebd5Sriastradh         /* Can't compare the buffer data since they are userbuffers */
6893464ebd5Sriastradh         else if (old && old->free_on_destroy)
6907ec681f3Smrg            diff = memcmp(old->data, ibuf->data, ibuf->b.width0);
6913464ebd5Sriastradh#else
6923464ebd5Sriastradh         (void)old;
6933464ebd5Sriastradh#endif
6944a49301eSmrg      }
6953464ebd5Sriastradh   } else {
6963464ebd5Sriastradh      diff = i915->current.num_user_constants[shader] != 0;
6974a49301eSmrg   }
6984a49301eSmrg
6997ec681f3Smrg   if (take_ownership) {
7007ec681f3Smrg      pipe_resource_reference(&i915->constants[shader], NULL);
7017ec681f3Smrg      i915->constants[shader] = buf;
7027ec681f3Smrg   } else {
7037ec681f3Smrg      pipe_resource_reference(&i915->constants[shader], buf);
7047ec681f3Smrg   }
7053464ebd5Sriastradh   i915->current.num_user_constants[shader] = new_num;
7063464ebd5Sriastradh
7073464ebd5Sriastradh   if (diff)
7087ec681f3Smrg      i915->dirty |= shader == PIPE_SHADER_VERTEX ? I915_NEW_VS_CONSTANTS
7097ec681f3Smrg                                                  : I915_NEW_FS_CONSTANTS;
7103464ebd5Sriastradh
711af69d88dSmrg   if (cb && cb->user_buffer) {
712af69d88dSmrg      pipe_resource_reference(&buf, NULL);
713af69d88dSmrg   }
7143464ebd5Sriastradh}
7153464ebd5Sriastradh
7167ec681f3Smrgstatic void
7177ec681f3Smrgi915_set_sampler_views(struct pipe_context *pipe, enum pipe_shader_type shader,
7187ec681f3Smrg                       unsigned start, unsigned num,
7197ec681f3Smrg                       unsigned unbind_num_trailing_slots,
7207ec681f3Smrg                       bool take_ownership,
7217ec681f3Smrg                       struct pipe_sampler_view **views)
7224a49301eSmrg{
7237ec681f3Smrg   if (shader != PIPE_SHADER_FRAGMENT) {
7247ec681f3Smrg      /* No support for VS samplers, because it would mean accessing the
7257ec681f3Smrg       * write-combined maps of the textures, which is very slow.  VS samplers
7267ec681f3Smrg       * are not a required feature of GL2.1 or GLES2.
7277ec681f3Smrg       */
7287ec681f3Smrg      assert(num == 0);
7297ec681f3Smrg      return;
7307ec681f3Smrg   }
7314a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
7327ec681f3Smrg   uint32_t i;
7334a49301eSmrg
7344a49301eSmrg   assert(num <= PIPE_MAX_SAMPLERS);
7354a49301eSmrg
7364a49301eSmrg   /* Check for no-op */
7377ec681f3Smrg   if (views && num == i915->num_fragment_sampler_views &&
7387ec681f3Smrg       !memcmp(i915->fragment_sampler_views, views,
7397ec681f3Smrg               num * sizeof(struct pipe_sampler_view *))) {
7407ec681f3Smrg      if (take_ownership) {
7417ec681f3Smrg         for (unsigned i = 0; i < num; i++) {
7427ec681f3Smrg            struct pipe_sampler_view *view = views[i];
7437ec681f3Smrg            pipe_sampler_view_reference(&view, NULL);
7447ec681f3Smrg         }
7457ec681f3Smrg      }
7464a49301eSmrg      return;
7477ec681f3Smrg   }
7484a49301eSmrg
749af69d88dSmrg   for (i = 0; i < num; i++) {
7507ec681f3Smrg      if (take_ownership) {
7517ec681f3Smrg         pipe_sampler_view_reference(&i915->fragment_sampler_views[i], NULL);
7527ec681f3Smrg         i915->fragment_sampler_views[i] = views[i];
7537ec681f3Smrg      } else {
7547ec681f3Smrg         pipe_sampler_view_reference(&i915->fragment_sampler_views[i], views[i]);
7557ec681f3Smrg      }
756af69d88dSmrg   }
7574a49301eSmrg
7583464ebd5Sriastradh   for (i = num; i < i915->num_fragment_sampler_views; i++)
7599f464c52Smaya      pipe_sampler_view_reference(&i915->fragment_sampler_views[i], NULL);
7604a49301eSmrg
7613464ebd5Sriastradh   i915->num_fragment_sampler_views = num;
7624a49301eSmrg
7633464ebd5Sriastradh   i915->dirty |= I915_NEW_SAMPLER_VIEW;
7644a49301eSmrg}
7654a49301eSmrg
766af69d88dSmrgstruct pipe_sampler_view *
767af69d88dSmrgi915_create_sampler_view_custom(struct pipe_context *pipe,
768af69d88dSmrg                                struct pipe_resource *texture,
769af69d88dSmrg                                const struct pipe_sampler_view *templ,
7707ec681f3Smrg                                unsigned width0, unsigned height0)
771af69d88dSmrg{
772af69d88dSmrg   struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
773af69d88dSmrg
774af69d88dSmrg   if (view) {
775af69d88dSmrg      *view = *templ;
776af69d88dSmrg      view->reference.count = 1;
777af69d88dSmrg      view->texture = NULL;
778af69d88dSmrg      pipe_resource_reference(&view->texture, texture);
779af69d88dSmrg      view->context = pipe;
780af69d88dSmrg   }
781af69d88dSmrg
782af69d88dSmrg   return view;
783af69d88dSmrg}
7844a49301eSmrg
7853464ebd5Sriastradhstatic struct pipe_sampler_view *
7863464ebd5Sriastradhi915_create_sampler_view(struct pipe_context *pipe,
7873464ebd5Sriastradh                         struct pipe_resource *texture,
7883464ebd5Sriastradh                         const struct pipe_sampler_view *templ)
7893464ebd5Sriastradh{
7903464ebd5Sriastradh   struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
7913464ebd5Sriastradh
7923464ebd5Sriastradh   if (view) {
7933464ebd5Sriastradh      *view = *templ;
7943464ebd5Sriastradh      view->reference.count = 1;
7953464ebd5Sriastradh      view->texture = NULL;
7963464ebd5Sriastradh      pipe_resource_reference(&view->texture, texture);
7973464ebd5Sriastradh      view->context = pipe;
7983464ebd5Sriastradh   }
7993464ebd5Sriastradh
8003464ebd5Sriastradh   return view;
8013464ebd5Sriastradh}
8023464ebd5Sriastradh
8033464ebd5Sriastradhstatic void
8043464ebd5Sriastradhi915_sampler_view_destroy(struct pipe_context *pipe,
8053464ebd5Sriastradh                          struct pipe_sampler_view *view)
8063464ebd5Sriastradh{
8073464ebd5Sriastradh   pipe_resource_reference(&view->texture, NULL);
8083464ebd5Sriastradh   FREE(view);
8093464ebd5Sriastradh}
8103464ebd5Sriastradh
8117ec681f3Smrgstatic void
8127ec681f3Smrgi915_set_framebuffer_state(struct pipe_context *pipe,
8137ec681f3Smrg                           const struct pipe_framebuffer_state *fb)
8144a49301eSmrg{
8154a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
8164a49301eSmrg
8174a49301eSmrg   i915->framebuffer.width = fb->width;
8184a49301eSmrg   i915->framebuffer.height = fb->height;
8194a49301eSmrg   i915->framebuffer.nr_cbufs = fb->nr_cbufs;
8207ec681f3Smrg   if (fb->nr_cbufs) {
8217ec681f3Smrg      pipe_surface_reference(&i915->framebuffer.cbufs[0], fb->cbufs[0]);
8227ec681f3Smrg
8237ec681f3Smrg      struct i915_surface *surf = i915_surface(i915->framebuffer.cbufs[0]);
8247ec681f3Smrg      if (i915->current.fixup_swizzle != surf->oc_swizzle) {
8257ec681f3Smrg         i915->current.fixup_swizzle = surf->oc_swizzle;
8267ec681f3Smrg         memcpy(i915->current.color_swizzle, surf->color_swizzle,
8277ec681f3Smrg                sizeof(surf->color_swizzle));
8287ec681f3Smrg         i915->dirty |= I915_NEW_COLOR_SWIZZLE;
8297ec681f3Smrg      }
8307ec681f3Smrg   } else {
8317ec681f3Smrg      pipe_surface_reference(&i915->framebuffer.cbufs[0], NULL);
8324a49301eSmrg   }
8334a49301eSmrg   pipe_surface_reference(&i915->framebuffer.zsbuf, fb->zsbuf);
8347ec681f3Smrg   if (fb->zsbuf)
8357ec681f3Smrg      draw_set_zs_format(i915->draw, fb->zsbuf->format);
8364a49301eSmrg
8374a49301eSmrg   i915->dirty |= I915_NEW_FRAMEBUFFER;
8384a49301eSmrg}
8394a49301eSmrg
8407ec681f3Smrgstatic void
8417ec681f3Smrgi915_set_clip_state(struct pipe_context *pipe,
8427ec681f3Smrg                    const struct pipe_clip_state *clip)
8434a49301eSmrg{
8444a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
8454a49301eSmrg
846af69d88dSmrg   i915->clip = *clip;
8473464ebd5Sriastradh
8484a49301eSmrg   draw_set_clip_state(i915->draw, clip);
8494a49301eSmrg
8504a49301eSmrg   i915->dirty |= I915_NEW_CLIP;
8514a49301eSmrg}
8524a49301eSmrg
8537ec681f3Smrg/* Called when gallium frontends notice changes to the viewport
8544a49301eSmrg * matrix:
8554a49301eSmrg */
8567ec681f3Smrgstatic void
8577ec681f3Smrgi915_set_viewport_states(struct pipe_context *pipe, unsigned start_slot,
8587ec681f3Smrg                         unsigned num_viewports,
8597ec681f3Smrg                         const struct pipe_viewport_state *viewport)
8604a49301eSmrg{
8614a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
8624a49301eSmrg
8634a49301eSmrg   i915->viewport = *viewport; /* struct copy */
8644a49301eSmrg
8654a49301eSmrg   /* pass the viewport info to the draw module */
866af69d88dSmrg   draw_set_viewport_states(i915->draw, start_slot, num_viewports,
867af69d88dSmrg                            &i915->viewport);
8684a49301eSmrg
8694a49301eSmrg   i915->dirty |= I915_NEW_VIEWPORT;
8704a49301eSmrg}
8714a49301eSmrg
8724a49301eSmrgstatic void *
8734a49301eSmrgi915_create_rasterizer_state(struct pipe_context *pipe,
8744a49301eSmrg                             const struct pipe_rasterizer_state *rasterizer)
8754a49301eSmrg{
8767ec681f3Smrg   struct i915_rasterizer_state *cso = CALLOC_STRUCT(i915_rasterizer_state);
8774a49301eSmrg
8783464ebd5Sriastradh   cso->templ = *rasterizer;
8794a49301eSmrg   cso->light_twoside = rasterizer->light_twoside;
8804a49301eSmrg   cso->ds[0].u = _3DSTATE_DEPTH_OFFSET_SCALE;
8814a49301eSmrg   cso->ds[1].f = rasterizer->offset_scale;
8824a49301eSmrg   if (rasterizer->poly_stipple_enable) {
8834a49301eSmrg      cso->st |= ST1_ENABLE;
8844a49301eSmrg   }
8854a49301eSmrg
8864a49301eSmrg   if (rasterizer->scissor)
8874a49301eSmrg      cso->sc[0] = _3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT;
8884a49301eSmrg   else
8894a49301eSmrg      cso->sc[0] = _3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT;
8904a49301eSmrg
8913464ebd5Sriastradh   switch (rasterizer->cull_face) {
8923464ebd5Sriastradh   case PIPE_FACE_NONE:
8934a49301eSmrg      cso->LIS4 |= S4_CULLMODE_NONE;
8944a49301eSmrg      break;
8953464ebd5Sriastradh   case PIPE_FACE_FRONT:
8963464ebd5Sriastradh      if (rasterizer->front_ccw)
8973464ebd5Sriastradh         cso->LIS4 |= S4_CULLMODE_CCW;
8987ec681f3Smrg      else
8993464ebd5Sriastradh         cso->LIS4 |= S4_CULLMODE_CW;
9004a49301eSmrg      break;
9013464ebd5Sriastradh   case PIPE_FACE_BACK:
9023464ebd5Sriastradh      if (rasterizer->front_ccw)
9033464ebd5Sriastradh         cso->LIS4 |= S4_CULLMODE_CW;
9047ec681f3Smrg      else
9053464ebd5Sriastradh         cso->LIS4 |= S4_CULLMODE_CCW;
9064a49301eSmrg      break;
9073464ebd5Sriastradh   case PIPE_FACE_FRONT_AND_BACK:
9084a49301eSmrg      cso->LIS4 |= S4_CULLMODE_BOTH;
9094a49301eSmrg      break;
9104a49301eSmrg   }
9114a49301eSmrg
9124a49301eSmrg   {
9134a49301eSmrg      int line_width = CLAMP((int)(rasterizer->line_width * 2), 1, 0xf);
9144a49301eSmrg
9154a49301eSmrg      cso->LIS4 |= line_width << S4_LINE_WIDTH_SHIFT;
9164a49301eSmrg
9174a49301eSmrg      if (rasterizer->line_smooth)
9187ec681f3Smrg         cso->LIS4 |= S4_LINE_ANTIALIAS_ENABLE;
9194a49301eSmrg   }
9204a49301eSmrg
9214a49301eSmrg   {
9227ec681f3Smrg      int point_size = CLAMP((int)rasterizer->point_size, 1, 0xff);
9234a49301eSmrg
9244a49301eSmrg      cso->LIS4 |= point_size << S4_POINT_WIDTH_SHIFT;
9254a49301eSmrg   }
9264a49301eSmrg
9274a49301eSmrg   if (rasterizer->flatshade) {
9287ec681f3Smrg      cso->LIS4 |=
9297ec681f3Smrg         (S4_FLATSHADE_ALPHA | S4_FLATSHADE_COLOR | S4_FLATSHADE_SPECULAR);
9304a49301eSmrg   }
9314a49301eSmrg
9327ec681f3Smrg   if (!rasterizer->flatshade_first)
9337ec681f3Smrg      cso->LIS6 |= (2 << S6_TRISTRIP_PV_SHIFT);
9344a49301eSmrg
9357ec681f3Smrg   cso->LIS7 = fui(rasterizer->offset_units);
9364a49301eSmrg
9374a49301eSmrg   return cso;
9384a49301eSmrg}
9394a49301eSmrg
9407ec681f3Smrgstatic void
9417ec681f3Smrgi915_bind_rasterizer_state(struct pipe_context *pipe, void *raster)
9424a49301eSmrg{
9434a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
9444a49301eSmrg
945af69d88dSmrg   if (i915->rasterizer == raster)
946af69d88dSmrg      return;
947af69d88dSmrg
9484a49301eSmrg   i915->rasterizer = (struct i915_rasterizer_state *)raster;
9494a49301eSmrg
9504a49301eSmrg   /* pass-through to draw module */
9517ec681f3Smrg   draw_set_rasterizer_state(
9527ec681f3Smrg      i915->draw, (i915->rasterizer ? &(i915->rasterizer->templ) : NULL),
9537ec681f3Smrg      raster);
9544a49301eSmrg
9554a49301eSmrg   i915->dirty |= I915_NEW_RASTERIZER;
9564a49301eSmrg}
9574a49301eSmrg
9587ec681f3Smrgstatic void
9597ec681f3Smrgi915_delete_rasterizer_state(struct pipe_context *pipe, void *raster)
9604a49301eSmrg{
9614a49301eSmrg   FREE(raster);
9624a49301eSmrg}
9634a49301eSmrg
9647ec681f3Smrgstatic void
9657ec681f3Smrgi915_set_vertex_buffers(struct pipe_context *pipe, unsigned start_slot,
9667ec681f3Smrg                        unsigned count, unsigned unbind_num_trailing_slots,
9677ec681f3Smrg                        bool take_ownership,
9687ec681f3Smrg                        const struct pipe_vertex_buffer *buffers)
9694a49301eSmrg{
9704a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
9713464ebd5Sriastradh   struct draw_context *draw = i915->draw;
9724a49301eSmrg
9737ec681f3Smrg   util_set_vertex_buffers_count(i915->vertex_buffers, &i915->nr_vertex_buffers,
9747ec681f3Smrg                                 buffers, start_slot, count,
9757ec681f3Smrg                                 unbind_num_trailing_slots, take_ownership);
9764a49301eSmrg
9774a49301eSmrg   /* pass-through to draw module */
9787ec681f3Smrg   draw_set_vertex_buffers(draw, start_slot, count, unbind_num_trailing_slots,
9797ec681f3Smrg                           buffers);
9803464ebd5Sriastradh}
9813464ebd5Sriastradh
9823464ebd5Sriastradhstatic void *
9837ec681f3Smrgi915_create_vertex_elements_state(struct pipe_context *pipe, unsigned count,
9843464ebd5Sriastradh                                  const struct pipe_vertex_element *attribs)
9853464ebd5Sriastradh{
9863464ebd5Sriastradh   struct i915_velems_state *velems;
9873464ebd5Sriastradh   assert(count <= PIPE_MAX_ATTRIBS);
9887ec681f3Smrg   velems =
9897ec681f3Smrg      (struct i915_velems_state *)MALLOC(sizeof(struct i915_velems_state));
9903464ebd5Sriastradh   if (velems) {
9913464ebd5Sriastradh      velems->count = count;
9923464ebd5Sriastradh      memcpy(velems->velem, attribs, sizeof(*attribs) * count);
9933464ebd5Sriastradh   }
9943464ebd5Sriastradh   return velems;
9954a49301eSmrg}
9964a49301eSmrg
9973464ebd5Sriastradhstatic void
9987ec681f3Smrgi915_bind_vertex_elements_state(struct pipe_context *pipe, void *velems)
9994a49301eSmrg{
10004a49301eSmrg   struct i915_context *i915 = i915_context(pipe);
10017ec681f3Smrg   struct i915_velems_state *i915_velems = (struct i915_velems_state *)velems;
10023464ebd5Sriastradh
1003af69d88dSmrg   if (i915->velems == velems)
1004af69d88dSmrg      return;
1005af69d88dSmrg
1006af69d88dSmrg   i915->velems = velems;
10074a49301eSmrg
10084a49301eSmrg   /* pass-through to draw module */
10093464ebd5Sriastradh   if (i915_velems) {
10107ec681f3Smrg      draw_set_vertex_elements(i915->draw, i915_velems->count,
10117ec681f3Smrg                               i915_velems->velem);
10123464ebd5Sriastradh   }
10134a49301eSmrg}
10144a49301eSmrg
10153464ebd5Sriastradhstatic void
10163464ebd5Sriastradhi915_delete_vertex_elements_state(struct pipe_context *pipe, void *velems)
10173464ebd5Sriastradh{
10187ec681f3Smrg   FREE(velems);
10193464ebd5Sriastradh}
10203464ebd5Sriastradh
10213464ebd5Sriastradhstatic void
10227ec681f3Smrgi915_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
10233464ebd5Sriastradh{
10243464ebd5Sriastradh}
10254a49301eSmrg
10264a49301eSmrgvoid
10277ec681f3Smrgi915_init_state_functions(struct i915_context *i915)
10284a49301eSmrg{
10294a49301eSmrg   i915->base.create_blend_state = i915_create_blend_state;
10304a49301eSmrg   i915->base.bind_blend_state = i915_bind_blend_state;
10314a49301eSmrg   i915->base.delete_blend_state = i915_delete_blend_state;
10324a49301eSmrg
10334a49301eSmrg   i915->base.create_sampler_state = i915_create_sampler_state;
1034af69d88dSmrg   i915->base.bind_sampler_states = i915_bind_sampler_states;
10354a49301eSmrg   i915->base.delete_sampler_state = i915_delete_sampler_state;
10364a49301eSmrg
10377ec681f3Smrg   i915->base.create_depth_stencil_alpha_state =
10387ec681f3Smrg      i915_create_depth_stencil_state;
10394a49301eSmrg   i915->base.bind_depth_stencil_alpha_state = i915_bind_depth_stencil_state;
10407ec681f3Smrg   i915->base.delete_depth_stencil_alpha_state =
10417ec681f3Smrg      i915_delete_depth_stencil_state;
10424a49301eSmrg
10434a49301eSmrg   i915->base.create_rasterizer_state = i915_create_rasterizer_state;
10444a49301eSmrg   i915->base.bind_rasterizer_state = i915_bind_rasterizer_state;
10454a49301eSmrg   i915->base.delete_rasterizer_state = i915_delete_rasterizer_state;
10464a49301eSmrg   i915->base.create_fs_state = i915_create_fs_state;
10474a49301eSmrg   i915->base.bind_fs_state = i915_bind_fs_state;
10484a49301eSmrg   i915->base.delete_fs_state = i915_delete_fs_state;
10494a49301eSmrg   i915->base.create_vs_state = i915_create_vs_state;
10504a49301eSmrg   i915->base.bind_vs_state = i915_bind_vs_state;
10514a49301eSmrg   i915->base.delete_vs_state = i915_delete_vs_state;
10523464ebd5Sriastradh   i915->base.create_vertex_elements_state = i915_create_vertex_elements_state;
10533464ebd5Sriastradh   i915->base.bind_vertex_elements_state = i915_bind_vertex_elements_state;
10543464ebd5Sriastradh   i915->base.delete_vertex_elements_state = i915_delete_vertex_elements_state;
10554a49301eSmrg
10564a49301eSmrg   i915->base.set_blend_color = i915_set_blend_color;
1057cdc920a0Smrg   i915->base.set_stencil_ref = i915_set_stencil_ref;
10584a49301eSmrg   i915->base.set_clip_state = i915_set_clip_state;
10593464ebd5Sriastradh   i915->base.set_sample_mask = i915_set_sample_mask;
10604a49301eSmrg   i915->base.set_constant_buffer = i915_set_constant_buffer;
10614a49301eSmrg   i915->base.set_framebuffer_state = i915_set_framebuffer_state;
10624a49301eSmrg
10634a49301eSmrg   i915->base.set_polygon_stipple = i915_set_polygon_stipple;
1064af69d88dSmrg   i915->base.set_scissor_states = i915_set_scissor_states;
1065af69d88dSmrg   i915->base.set_sampler_views = i915_set_sampler_views;
10663464ebd5Sriastradh   i915->base.create_sampler_view = i915_create_sampler_view;
10673464ebd5Sriastradh   i915->base.sampler_view_destroy = i915_sampler_view_destroy;
1068af69d88dSmrg   i915->base.set_viewport_states = i915_set_viewport_states;
10694a49301eSmrg   i915->base.set_vertex_buffers = i915_set_vertex_buffers;
10704a49301eSmrg}
1071