Subversion Repositories Kolibri OS

Rev

Rev 3291 | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright © 2006,2008,2011 Intel Corporation
  3.  * Copyright © 2007 Red Hat, Inc.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the "Software"),
  7.  * to deal in the Software without restriction, including without limitation
  8.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9.  * and/or sell copies of the Software, and to permit persons to whom the
  10.  * Software is furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the next
  13.  * paragraph) shall be included in all copies or substantial portions of the
  14.  * Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22.  * SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Wang Zhenyu <zhenyu.z.wang@sna.com>
  26.  *    Eric Anholt <eric@anholt.net>
  27.  *    Carl Worth <cworth@redhat.com>
  28.  *    Keith Packard <keithp@keithp.com>
  29.  *    Chris Wilson <chris@chris-wilson.co.uk>
  30.  *
  31.  */
  32.  
  33. #ifdef HAVE_CONFIG_H
  34. #include "config.h"
  35. #endif
  36.  
  37. #include "sna.h"
  38. #include "sna_reg.h"
  39. #include "sna_render.h"
  40. #include "sna_render_inline.h"
  41. //#include "sna_video.h"
  42.  
  43. #include "brw/brw.h"
  44. #include "gen5_render.h"
  45. #include "gen4_source.h"
  46. #include "gen4_vertex.h"
  47.  
  48. #define NO_COMPOSITE 0
  49. #define NO_COMPOSITE_SPANS 0
  50.  
  51. #define PREFER_BLT_FILL 1
  52.  
  53. #define DBG_NO_STATE_CACHE 0
  54. #define DBG_NO_SURFACE_CACHE 0
  55.  
  56. #define MAX_3D_SIZE 8192
  57.  
  58. #define GEN5_GRF_BLOCKS(nreg)    ((nreg + 15) / 16 - 1)
  59.  
  60. /* Set up a default static partitioning of the URB, which is supposed to
  61.  * allow anything we would want to do, at potentially lower performance.
  62.  */
  63. #define URB_CS_ENTRY_SIZE     1
  64. #define URB_CS_ENTRIES        0
  65.  
  66. #define URB_VS_ENTRY_SIZE     1
  67. #define URB_VS_ENTRIES        256 /* minimum of 8 */
  68.  
  69. #define URB_GS_ENTRY_SIZE     0
  70. #define URB_GS_ENTRIES        0
  71.  
  72. #define URB_CLIP_ENTRY_SIZE   0
  73. #define URB_CLIP_ENTRIES      0
  74.  
  75. #define URB_SF_ENTRY_SIZE     2
  76. #define URB_SF_ENTRIES        64
  77.  
  78. /*
  79.  * this program computes dA/dx and dA/dy for the texture coordinates along
  80.  * with the base texture coordinate. It was extracted from the Mesa driver
  81.  */
  82.  
  83. #define SF_KERNEL_NUM_GRF  16
  84. #define SF_MAX_THREADS     48
  85.  
  86. #define PS_KERNEL_NUM_GRF   32
  87. #define PS_MAX_THREADS      72
  88.  
  89. static const uint32_t ps_kernel_packed_static[][4] = {
  90. #include "exa_wm_xy.g5b"
  91. #include "exa_wm_src_affine.g5b"
  92. #include "exa_wm_src_sample_argb.g5b"
  93. #include "exa_wm_yuv_rgb.g5b"
  94. #include "exa_wm_write.g5b"
  95. };
  96.  
  97. static const uint32_t ps_kernel_planar_static[][4] = {
  98. #include "exa_wm_xy.g5b"
  99. #include "exa_wm_src_affine.g5b"
  100. #include "exa_wm_src_sample_planar.g5b"
  101. #include "exa_wm_yuv_rgb.g5b"
  102. #include "exa_wm_write.g5b"
  103. };
  104.  
  105. #define NOKERNEL(kernel_enum, func, masked) \
  106.     [kernel_enum] = {func, 0, masked}
  107. #define KERNEL(kernel_enum, kernel, masked) \
  108.     [kernel_enum] = {&kernel, sizeof(kernel), masked}
  109. static const struct wm_kernel_info {
  110.         const void *data;
  111.         unsigned int size;
  112.         bool has_mask;
  113. } wm_kernels[] = {
  114.         NOKERNEL(WM_KERNEL, brw_wm_kernel__affine, false),
  115.         NOKERNEL(WM_KERNEL_P, brw_wm_kernel__projective, false),
  116.  
  117.         NOKERNEL(WM_KERNEL_MASK, brw_wm_kernel__affine_mask, true),
  118.         NOKERNEL(WM_KERNEL_MASK_P, brw_wm_kernel__projective_mask, true),
  119.  
  120.         NOKERNEL(WM_KERNEL_MASKCA, brw_wm_kernel__affine_mask_ca, true),
  121.         NOKERNEL(WM_KERNEL_MASKCA_P, brw_wm_kernel__projective_mask_ca, true),
  122.  
  123.         NOKERNEL(WM_KERNEL_MASKSA, brw_wm_kernel__affine_mask_sa, true),
  124.         NOKERNEL(WM_KERNEL_MASKSA_P, brw_wm_kernel__projective_mask_sa, true),
  125.  
  126.         NOKERNEL(WM_KERNEL_OPACITY, brw_wm_kernel__affine_opacity, true),
  127.         NOKERNEL(WM_KERNEL_OPACITY_P, brw_wm_kernel__projective_opacity, true),
  128.  
  129.         KERNEL(WM_KERNEL_VIDEO_PLANAR, ps_kernel_planar_static, false),
  130.         KERNEL(WM_KERNEL_VIDEO_PACKED, ps_kernel_packed_static, false),
  131. };
  132. #undef KERNEL
  133.  
  134. static const struct blendinfo {
  135.         bool src_alpha;
  136.         uint32_t src_blend;
  137.         uint32_t dst_blend;
  138. } gen5_blend_op[] = {
  139.         /* Clear */     {0, GEN5_BLENDFACTOR_ZERO, GEN5_BLENDFACTOR_ZERO},
  140.         /* Src */       {0, GEN5_BLENDFACTOR_ONE, GEN5_BLENDFACTOR_ZERO},
  141.         /* Dst */       {0, GEN5_BLENDFACTOR_ZERO, GEN5_BLENDFACTOR_ONE},
  142.         /* Over */      {1, GEN5_BLENDFACTOR_ONE, GEN5_BLENDFACTOR_INV_SRC_ALPHA},
  143.         /* OverReverse */ {0, GEN5_BLENDFACTOR_INV_DST_ALPHA, GEN5_BLENDFACTOR_ONE},
  144.         /* In */        {0, GEN5_BLENDFACTOR_DST_ALPHA, GEN5_BLENDFACTOR_ZERO},
  145.         /* InReverse */ {1, GEN5_BLENDFACTOR_ZERO, GEN5_BLENDFACTOR_SRC_ALPHA},
  146.         /* Out */       {0, GEN5_BLENDFACTOR_INV_DST_ALPHA, GEN5_BLENDFACTOR_ZERO},
  147.         /* OutReverse */ {1, GEN5_BLENDFACTOR_ZERO, GEN5_BLENDFACTOR_INV_SRC_ALPHA},
  148.         /* Atop */      {1, GEN5_BLENDFACTOR_DST_ALPHA, GEN5_BLENDFACTOR_INV_SRC_ALPHA},
  149.         /* AtopReverse */ {1, GEN5_BLENDFACTOR_INV_DST_ALPHA, GEN5_BLENDFACTOR_SRC_ALPHA},
  150.         /* Xor */       {1, GEN5_BLENDFACTOR_INV_DST_ALPHA, GEN5_BLENDFACTOR_INV_SRC_ALPHA},
  151.         /* Add */       {0, GEN5_BLENDFACTOR_ONE, GEN5_BLENDFACTOR_ONE},
  152. };
  153.  
  154. /**
  155.  * Highest-valued BLENDFACTOR used in gen5_blend_op.
  156.  *
  157.  * This leaves out GEN5_BLENDFACTOR_INV_DST_COLOR,
  158.  * GEN5_BLENDFACTOR_INV_CONST_{COLOR,ALPHA},
  159.  * GEN5_BLENDFACTOR_INV_SRC1_{COLOR,ALPHA}
  160.  */
  161. #define GEN5_BLENDFACTOR_COUNT (GEN5_BLENDFACTOR_INV_DST_ALPHA + 1)
  162.  
  163. #define BLEND_OFFSET(s, d) \
  164.         (((s) * GEN5_BLENDFACTOR_COUNT + (d)) * 64)
  165.  
  166. #define SAMPLER_OFFSET(sf, se, mf, me, k) \
  167.         ((((((sf) * EXTEND_COUNT + (se)) * FILTER_COUNT + (mf)) * EXTEND_COUNT + (me)) * KERNEL_COUNT + (k)) * 64)
  168.  
  169. static bool
  170. gen5_emit_pipelined_pointers(struct sna *sna,
  171.                              const struct sna_composite_op *op,
  172.                              int blend, int kernel);
  173.  
  174. #define OUT_BATCH(v) batch_emit(sna, v)
  175. #define OUT_VERTEX(x,y) vertex_emit_2s(sna, x,y)
  176. #define OUT_VERTEX_F(v) vertex_emit(sna, v)
  177.  
  178. static inline bool too_large(int width, int height)
  179. {
  180.         return width > MAX_3D_SIZE || height > MAX_3D_SIZE;
  181. }
  182.  
  183. static int
  184. gen5_choose_composite_kernel(int op, bool has_mask, bool is_ca, bool is_affine)
  185. {
  186.         int base;
  187.  
  188.         if (has_mask) {
  189.                 if (is_ca) {
  190.                         if (gen5_blend_op[op].src_alpha)
  191.                                 base = WM_KERNEL_MASKSA;
  192.                         else
  193.                                 base = WM_KERNEL_MASKCA;
  194.                 } else
  195.                         base = WM_KERNEL_MASK;
  196.         } else
  197.                 base = WM_KERNEL;
  198.  
  199.         return base + !is_affine;
  200. }
  201.  
  202. static bool gen5_magic_ca_pass(struct sna *sna,
  203.                                const struct sna_composite_op *op)
  204. {
  205.         struct gen5_render_state *state = &sna->render_state.gen5;
  206.  
  207.         if (!op->need_magic_ca_pass)
  208.                 return false;
  209.  
  210.         assert(sna->render.vertex_index > sna->render.vertex_start);
  211.  
  212.         DBG(("%s: CA fixup\n", __FUNCTION__));
  213.         assert(op->mask.bo != NULL);
  214.         assert(op->has_component_alpha);
  215.  
  216.         gen5_emit_pipelined_pointers
  217.                 (sna, op, PictOpAdd,
  218.                  gen5_choose_composite_kernel(PictOpAdd,
  219.                                               true, true, op->is_affine));
  220.  
  221.         OUT_BATCH(GEN5_3DPRIMITIVE |
  222.                   GEN5_3DPRIMITIVE_VERTEX_SEQUENTIAL |
  223.                   (_3DPRIM_RECTLIST << GEN5_3DPRIMITIVE_TOPOLOGY_SHIFT) |
  224.                   (0 << 9) |
  225.                   4);
  226.         OUT_BATCH(sna->render.vertex_index - sna->render.vertex_start);
  227.         OUT_BATCH(sna->render.vertex_start);
  228.         OUT_BATCH(1);   /* single instance */
  229.         OUT_BATCH(0);   /* start instance location */
  230.         OUT_BATCH(0);   /* index buffer offset, ignored */
  231.  
  232.         state->last_primitive = sna->kgem.nbatch;
  233.         return true;
  234. }
  235.  
  236. static uint32_t gen5_get_blend(int op,
  237.                                bool has_component_alpha,
  238.                                uint32_t dst_format)
  239. {
  240.         uint32_t src, dst;
  241.  
  242.     src = GEN5_BLENDFACTOR_ONE; //gen6_blend_op[op].src_blend;
  243.     dst = GEN5_BLENDFACTOR_INV_SRC_ALPHA; //gen6_blend_op[op].dst_blend;
  244. #if 0
  245.         /* If there's no dst alpha channel, adjust the blend op so that we'll treat
  246.          * it as always 1.
  247.          */
  248.         if (PICT_FORMAT_A(dst_format) == 0) {
  249.                 if (src == GEN5_BLENDFACTOR_DST_ALPHA)
  250.                         src = GEN5_BLENDFACTOR_ONE;
  251.                 else if (src == GEN5_BLENDFACTOR_INV_DST_ALPHA)
  252.                         src = GEN5_BLENDFACTOR_ZERO;
  253.         }
  254.  
  255.         /* If the source alpha is being used, then we should only be in a
  256.          * case where the source blend factor is 0, and the source blend
  257.          * value is the mask channels multiplied by the source picture's alpha.
  258.          */
  259.         if (has_component_alpha && gen5_blend_op[op].src_alpha) {
  260.                 if (dst == GEN5_BLENDFACTOR_SRC_ALPHA)
  261.                         dst = GEN5_BLENDFACTOR_SRC_COLOR;
  262.                 else if (dst == GEN5_BLENDFACTOR_INV_SRC_ALPHA)
  263.                         dst = GEN5_BLENDFACTOR_INV_SRC_COLOR;
  264.         }
  265. #endif
  266.  
  267.         DBG(("blend op=%d, dst=%x [A=%d] => src=%d, dst=%d => offset=%x\n",
  268.              op, dst_format, PICT_FORMAT_A(dst_format),
  269.              src, dst, BLEND_OFFSET(src, dst)));
  270.         return BLEND_OFFSET(src, dst);
  271. }
  272.  
  273. static uint32_t gen5_get_card_format(PictFormat format)
  274. {
  275.         switch (format) {
  276.         default:
  277.                 return -1;
  278.         case PICT_a8r8g8b8:
  279.                 return GEN5_SURFACEFORMAT_B8G8R8A8_UNORM;
  280.         case PICT_x8r8g8b8:
  281.                 return GEN5_SURFACEFORMAT_B8G8R8X8_UNORM;
  282.         case PICT_a8:
  283.                 return GEN5_SURFACEFORMAT_A8_UNORM;
  284.         }
  285. }
  286.  
  287. static uint32_t gen5_get_dest_format(PictFormat format)
  288. {
  289.         switch (format) {
  290.         default:
  291.                 return -1;
  292.         case PICT_a8r8g8b8:
  293.         case PICT_x8r8g8b8:
  294.                 return GEN5_SURFACEFORMAT_B8G8R8A8_UNORM;
  295.         case PICT_a8:
  296.                 return GEN5_SURFACEFORMAT_A8_UNORM;
  297.         }
  298. }
  299. typedef struct gen5_surface_state_padded {
  300.         struct gen5_surface_state state;
  301.         char pad[32 - sizeof(struct gen5_surface_state)];
  302. } gen5_surface_state_padded;
  303.  
  304. static void null_create(struct sna_static_stream *stream)
  305. {
  306.         /* A bunch of zeros useful for legacy border color and depth-stencil */
  307.         sna_static_stream_map(stream, 64, 64);
  308. }
  309.  
  310. static void
  311. sampler_state_init(struct gen5_sampler_state *sampler_state,
  312.                    sampler_filter_t filter,
  313.                    sampler_extend_t extend)
  314. {
  315.         sampler_state->ss0.lod_preclamp = 1;    /* GL mode */
  316.  
  317.         /* We use the legacy mode to get the semantics specified by
  318.          * the Render extension. */
  319.         sampler_state->ss0.border_color_mode = GEN5_BORDER_COLOR_MODE_LEGACY;
  320.  
  321.         switch (filter) {
  322.         default:
  323.         case SAMPLER_FILTER_NEAREST:
  324.                 sampler_state->ss0.min_filter = GEN5_MAPFILTER_NEAREST;
  325.                 sampler_state->ss0.mag_filter = GEN5_MAPFILTER_NEAREST;
  326.                 break;
  327.         case SAMPLER_FILTER_BILINEAR:
  328.                 sampler_state->ss0.min_filter = GEN5_MAPFILTER_LINEAR;
  329.                 sampler_state->ss0.mag_filter = GEN5_MAPFILTER_LINEAR;
  330.                 break;
  331.         }
  332.  
  333.         switch (extend) {
  334.         default:
  335.         case SAMPLER_EXTEND_NONE:
  336.                 sampler_state->ss1.r_wrap_mode = GEN5_TEXCOORDMODE_CLAMP_BORDER;
  337.                 sampler_state->ss1.s_wrap_mode = GEN5_TEXCOORDMODE_CLAMP_BORDER;
  338.                 sampler_state->ss1.t_wrap_mode = GEN5_TEXCOORDMODE_CLAMP_BORDER;
  339.                 break;
  340.         case SAMPLER_EXTEND_REPEAT:
  341.                 sampler_state->ss1.r_wrap_mode = GEN5_TEXCOORDMODE_WRAP;
  342.                 sampler_state->ss1.s_wrap_mode = GEN5_TEXCOORDMODE_WRAP;
  343.                 sampler_state->ss1.t_wrap_mode = GEN5_TEXCOORDMODE_WRAP;
  344.                 break;
  345.         case SAMPLER_EXTEND_PAD:
  346.                 sampler_state->ss1.r_wrap_mode = GEN5_TEXCOORDMODE_CLAMP;
  347.                 sampler_state->ss1.s_wrap_mode = GEN5_TEXCOORDMODE_CLAMP;
  348.                 sampler_state->ss1.t_wrap_mode = GEN5_TEXCOORDMODE_CLAMP;
  349.                 break;
  350.         case SAMPLER_EXTEND_REFLECT:
  351.                 sampler_state->ss1.r_wrap_mode = GEN5_TEXCOORDMODE_MIRROR;
  352.                 sampler_state->ss1.s_wrap_mode = GEN5_TEXCOORDMODE_MIRROR;
  353.                 sampler_state->ss1.t_wrap_mode = GEN5_TEXCOORDMODE_MIRROR;
  354.                 break;
  355.         }
  356. }
  357.  
  358. static uint32_t
  359. gen5_tiling_bits(uint32_t tiling)
  360. {
  361.         switch (tiling) {
  362.         default: assert(0);
  363.         case I915_TILING_NONE: return 0;
  364.         case I915_TILING_X: return GEN5_SURFACE_TILED;
  365.         case I915_TILING_Y: return GEN5_SURFACE_TILED | GEN5_SURFACE_TILED_Y;
  366.         }
  367. }
  368.  
  369. /**
  370.  * Sets up the common fields for a surface state buffer for the given
  371.  * picture in the given surface state buffer.
  372.  */
  373. static uint32_t
  374. gen5_bind_bo(struct sna *sna,
  375.              struct kgem_bo *bo,
  376.              uint32_t width,
  377.              uint32_t height,
  378.              uint32_t format,
  379.              bool is_dst)
  380. {
  381.         uint32_t domains;
  382.         uint16_t offset;
  383.         uint32_t *ss;
  384.  
  385.         /* After the first bind, we manage the cache domains within the batch */
  386.         if (!DBG_NO_SURFACE_CACHE) {
  387.                 offset = kgem_bo_get_binding(bo, format);
  388.                 if (offset) {
  389.                         if (is_dst)
  390.                                 kgem_bo_mark_dirty(bo);
  391.                         return offset * sizeof(uint32_t);
  392.                 }
  393.         }
  394.  
  395.         offset = sna->kgem.surface -=
  396.                 sizeof(struct gen5_surface_state_padded) / sizeof(uint32_t);
  397.         ss = sna->kgem.batch + offset;
  398.  
  399.         ss[0] = (GEN5_SURFACE_2D << GEN5_SURFACE_TYPE_SHIFT |
  400.                  GEN5_SURFACE_BLEND_ENABLED |
  401.                  format << GEN5_SURFACE_FORMAT_SHIFT);
  402.  
  403.         if (is_dst)
  404.                 domains = I915_GEM_DOMAIN_RENDER << 16 | I915_GEM_DOMAIN_RENDER;
  405.         else
  406.                 domains = I915_GEM_DOMAIN_SAMPLER << 16;
  407.         ss[1] = kgem_add_reloc(&sna->kgem, offset + 1, bo, domains, 0);
  408.  
  409.         ss[2] = ((width - 1)  << GEN5_SURFACE_WIDTH_SHIFT |
  410.                  (height - 1) << GEN5_SURFACE_HEIGHT_SHIFT);
  411.         ss[3] = (gen5_tiling_bits(bo->tiling) |
  412.                  (bo->pitch - 1) << GEN5_SURFACE_PITCH_SHIFT);
  413.         ss[4] = 0;
  414.         ss[5] = 0;
  415.  
  416.         kgem_bo_set_binding(bo, format, offset);
  417.  
  418.         DBG(("[%x] bind bo(handle=%d, addr=%d), format=%d, width=%d, height=%d, pitch=%d, tiling=%d -> %s\n",
  419.              offset, bo->handle, ss[1],
  420.              format, width, height, bo->pitch, bo->tiling,
  421.              domains & 0xffff ? "render" : "sampler"));
  422.  
  423.         return offset * sizeof(uint32_t);
  424. }
  425.  
  426. static void gen5_emit_vertex_buffer(struct sna *sna,
  427.                                     const struct sna_composite_op *op)
  428. {
  429.         int id = op->u.gen5.ve_id;
  430.  
  431.         assert((sna->render.vb_id & (1 << id)) == 0);
  432.  
  433.         OUT_BATCH(GEN5_3DSTATE_VERTEX_BUFFERS | 3);
  434.         OUT_BATCH(id << VB0_BUFFER_INDEX_SHIFT | VB0_VERTEXDATA |
  435.                   (4*op->floats_per_vertex << VB0_BUFFER_PITCH_SHIFT));
  436.         assert(sna->render.nvertex_reloc < ARRAY_SIZE(sna->render.vertex_reloc));
  437.         sna->render.vertex_reloc[sna->render.nvertex_reloc++] = sna->kgem.nbatch;
  438.         OUT_BATCH(0);
  439.         OUT_BATCH(~0); /* max address: disabled */
  440.         OUT_BATCH(0);
  441.  
  442.         sna->render.vb_id |= 1 << id;
  443. }
  444.  
  445. static void gen5_emit_primitive(struct sna *sna)
  446. {
  447.         if (sna->kgem.nbatch == sna->render_state.gen5.last_primitive) {
  448.                 sna->render.vertex_offset = sna->kgem.nbatch - 5;
  449.                 return;
  450.         }
  451.  
  452.         OUT_BATCH(GEN5_3DPRIMITIVE |
  453.                   GEN5_3DPRIMITIVE_VERTEX_SEQUENTIAL |
  454.                   (_3DPRIM_RECTLIST << GEN5_3DPRIMITIVE_TOPOLOGY_SHIFT) |
  455.                   (0 << 9) |
  456.                   4);
  457.         sna->render.vertex_offset = sna->kgem.nbatch;
  458.         OUT_BATCH(0);   /* vertex count, to be filled in later */
  459.         OUT_BATCH(sna->render.vertex_index);
  460.         OUT_BATCH(1);   /* single instance */
  461.         OUT_BATCH(0);   /* start instance location */
  462.         OUT_BATCH(0);   /* index buffer offset, ignored */
  463.         sna->render.vertex_start = sna->render.vertex_index;
  464.  
  465.         sna->render_state.gen5.last_primitive = sna->kgem.nbatch;
  466. }
  467.  
  468. static bool gen5_rectangle_begin(struct sna *sna,
  469.                                  const struct sna_composite_op *op)
  470. {
  471.         int id = op->u.gen5.ve_id;
  472.         int ndwords;
  473.  
  474.         if (sna_vertex_wait__locked(&sna->render) && sna->render.vertex_offset)
  475.                 return true;
  476.  
  477.         ndwords = op->need_magic_ca_pass ? 20 : 6;
  478.         if ((sna->render.vb_id & (1 << id)) == 0)
  479.                 ndwords += 5;
  480.  
  481.         if (!kgem_check_batch(&sna->kgem, ndwords))
  482.                 return false;
  483.  
  484.         if ((sna->render.vb_id & (1 << id)) == 0)
  485.                 gen5_emit_vertex_buffer(sna, op);
  486.         if (sna->render.vertex_offset == 0)
  487.                 gen5_emit_primitive(sna);
  488.  
  489.         return true;
  490. }
  491.  
  492. static int gen5_get_rectangles__flush(struct sna *sna,
  493.                                       const struct sna_composite_op *op)
  494. {
  495.         /* Preventing discarding new vbo after lock contention */
  496.         if (sna_vertex_wait__locked(&sna->render)) {
  497.                 int rem = vertex_space(sna);
  498.                 if (rem > op->floats_per_rect)
  499.                         return rem;
  500.         }
  501.  
  502.         if (!kgem_check_batch(&sna->kgem, op->need_magic_ca_pass ? 20 : 6))
  503.                 return 0;
  504.         if (!kgem_check_reloc_and_exec(&sna->kgem, 2))
  505.                 return 0;
  506.  
  507.         if (sna->render.vertex_offset) {
  508.                 gen4_vertex_flush(sna);
  509.                 if (gen5_magic_ca_pass(sna, op))
  510.                         gen5_emit_pipelined_pointers(sna, op, op->op,
  511.                                                      op->u.gen5.wm_kernel);
  512.         }
  513.  
  514.         return gen4_vertex_finish(sna);
  515. }
  516.  
  517. inline static int gen5_get_rectangles(struct sna *sna,
  518.                                       const struct sna_composite_op *op,
  519.                                       int want,
  520.                                       void (*emit_state)(struct sna *sna,
  521.                                                          const struct sna_composite_op *op))
  522. {
  523.         int rem;
  524.  
  525.         assert(want);
  526.  
  527. start:
  528.         rem = vertex_space(sna);
  529.         if (unlikely(rem < op->floats_per_rect)) {
  530.                 DBG(("flushing vbo for %s: %d < %d\n",
  531.                      __FUNCTION__, rem, op->floats_per_rect));
  532.                 rem = gen5_get_rectangles__flush(sna, op);
  533.                 if (unlikely (rem == 0))
  534.                         goto flush;
  535.         }
  536.  
  537.         if (unlikely(sna->render.vertex_offset == 0)) {
  538.                 if (!gen5_rectangle_begin(sna, op))
  539.                         goto flush;
  540.                 else
  541.                         goto start;
  542.         }
  543.  
  544.         assert(op->floats_per_rect >= vertex_space(sna));
  545.         assert(rem <= vertex_space(sna));
  546.         if (want > 1 && want * op->floats_per_rect > rem)
  547.                 want = rem / op->floats_per_rect;
  548.  
  549.         sna->render.vertex_index += 3*want;
  550.         return want;
  551.  
  552. flush:
  553.         if (sna->render.vertex_offset) {
  554.                 gen4_vertex_flush(sna);
  555.                 gen5_magic_ca_pass(sna, op);
  556.         }
  557.         sna_vertex_wait__locked(&sna->render);
  558.         _kgem_submit(&sna->kgem);
  559.         emit_state(sna, op);
  560.         goto start;
  561. }
  562.  
  563. static uint32_t *
  564. gen5_composite_get_binding_table(struct sna *sna,
  565.                                  uint16_t *offset)
  566. {
  567.         sna->kgem.surface -=
  568.                 sizeof(struct gen5_surface_state_padded) / sizeof(uint32_t);
  569.  
  570.         DBG(("%s(%x)\n", __FUNCTION__, 4*sna->kgem.surface));
  571.  
  572.         /* Clear all surplus entries to zero in case of prefetch */
  573.         *offset = sna->kgem.surface;
  574.         return memset(sna->kgem.batch + sna->kgem.surface,
  575.                       0, sizeof(struct gen5_surface_state_padded));
  576. }
  577.  
  578. static void
  579. gen5_emit_urb(struct sna *sna)
  580. {
  581.         int urb_vs_start, urb_vs_size;
  582.         int urb_gs_start, urb_gs_size;
  583.         int urb_clip_start, urb_clip_size;
  584.         int urb_sf_start, urb_sf_size;
  585.         int urb_cs_start, urb_cs_size;
  586.  
  587.         urb_vs_start = 0;
  588.         urb_vs_size = URB_VS_ENTRIES * URB_VS_ENTRY_SIZE;
  589.         urb_gs_start = urb_vs_start + urb_vs_size;
  590.         urb_gs_size = URB_GS_ENTRIES * URB_GS_ENTRY_SIZE;
  591.         urb_clip_start = urb_gs_start + urb_gs_size;
  592.         urb_clip_size = URB_CLIP_ENTRIES * URB_CLIP_ENTRY_SIZE;
  593.         urb_sf_start = urb_clip_start + urb_clip_size;
  594.         urb_sf_size = URB_SF_ENTRIES * URB_SF_ENTRY_SIZE;
  595.         urb_cs_start = urb_sf_start + urb_sf_size;
  596.         urb_cs_size = URB_CS_ENTRIES * URB_CS_ENTRY_SIZE;
  597.  
  598.         OUT_BATCH(GEN5_URB_FENCE |
  599.                   UF0_CS_REALLOC |
  600.                   UF0_SF_REALLOC |
  601.                   UF0_CLIP_REALLOC |
  602.                   UF0_GS_REALLOC |
  603.                   UF0_VS_REALLOC |
  604.                   1);
  605.         OUT_BATCH(((urb_clip_start + urb_clip_size) << UF1_CLIP_FENCE_SHIFT) |
  606.                   ((urb_gs_start + urb_gs_size) << UF1_GS_FENCE_SHIFT) |
  607.                   ((urb_vs_start + urb_vs_size) << UF1_VS_FENCE_SHIFT));
  608.         OUT_BATCH(((urb_cs_start + urb_cs_size) << UF2_CS_FENCE_SHIFT) |
  609.                   ((urb_sf_start + urb_sf_size) << UF2_SF_FENCE_SHIFT));
  610.  
  611.         /* Constant buffer state */
  612.         OUT_BATCH(GEN5_CS_URB_STATE | 0);
  613.         OUT_BATCH((URB_CS_ENTRY_SIZE - 1) << 4 | URB_CS_ENTRIES << 0);
  614. }
  615.  
  616. static void
  617. gen5_emit_state_base_address(struct sna *sna)
  618. {
  619.         assert(sna->render_state.gen5.general_bo->proxy == NULL);
  620.         OUT_BATCH(GEN5_STATE_BASE_ADDRESS | 6);
  621.         OUT_BATCH(kgem_add_reloc(&sna->kgem, /* general */
  622.                                  sna->kgem.nbatch,
  623.                                  sna->render_state.gen5.general_bo,
  624.                                  I915_GEM_DOMAIN_INSTRUCTION << 16,
  625.                                  BASE_ADDRESS_MODIFY));
  626.         OUT_BATCH(kgem_add_reloc(&sna->kgem, /* surface */
  627.                                  sna->kgem.nbatch,
  628.                                  NULL,
  629.                                  I915_GEM_DOMAIN_INSTRUCTION << 16,
  630.                                  BASE_ADDRESS_MODIFY));
  631.         OUT_BATCH(0); /* media */
  632.         OUT_BATCH(kgem_add_reloc(&sna->kgem, /* instruction */
  633.                                  sna->kgem.nbatch,
  634.                                  sna->render_state.gen5.general_bo,
  635.                                  I915_GEM_DOMAIN_INSTRUCTION << 16,
  636.                                  BASE_ADDRESS_MODIFY));
  637.  
  638.         /* upper bounds, all disabled */
  639.         OUT_BATCH(BASE_ADDRESS_MODIFY);
  640.         OUT_BATCH(0);
  641.         OUT_BATCH(BASE_ADDRESS_MODIFY);
  642. }
  643.  
  644. static void
  645. gen5_emit_invariant(struct sna *sna)
  646. {
  647.         /* Ironlake errata workaround: Before disabling the clipper,
  648.          * you have to MI_FLUSH to get the pipeline idle.
  649.          *
  650.          * However, the kernel flushes the pipeline between batches,
  651.          * so we should be safe....
  652.          * OUT_BATCH(MI_FLUSH | MI_INHIBIT_RENDER_CACHE_FLUSH);
  653.          */
  654.         OUT_BATCH(GEN5_PIPELINE_SELECT | PIPELINE_SELECT_3D);
  655.  
  656.         gen5_emit_state_base_address(sna);
  657.  
  658.         sna->render_state.gen5.needs_invariant = false;
  659. }
  660.  
  661. static void
  662. gen5_get_batch(struct sna *sna, const struct sna_composite_op *op)
  663. {
  664.         kgem_set_mode(&sna->kgem, KGEM_RENDER, op->dst.bo);
  665.  
  666.         if (!kgem_check_batch_with_surfaces(&sna->kgem, 150, 4)) {
  667.                 DBG(("%s: flushing batch: %d < %d+%d\n",
  668.                      __FUNCTION__, sna->kgem.surface - sna->kgem.nbatch,
  669.                      150, 4*8));
  670.                 kgem_submit(&sna->kgem);
  671.                 _kgem_set_mode(&sna->kgem, KGEM_RENDER);
  672.         }
  673.  
  674.         if (sna->render_state.gen5.needs_invariant)
  675.                 gen5_emit_invariant(sna);
  676. }
  677.  
  678. static void
  679. gen5_align_vertex(struct sna *sna, const struct sna_composite_op *op)
  680. {
  681.         assert(op->floats_per_rect == 3*op->floats_per_vertex);
  682.         if (op->floats_per_vertex != sna->render_state.gen5.floats_per_vertex) {
  683.                 if (sna->render.vertex_size - sna->render.vertex_used < 2*op->floats_per_rect)
  684.                         gen4_vertex_finish(sna);
  685.  
  686.                 DBG(("aligning vertex: was %d, now %d floats per vertex, %d->%d\n",
  687.                      sna->render_state.gen5.floats_per_vertex,
  688.                      op->floats_per_vertex,
  689.                      sna->render.vertex_index,
  690.                      (sna->render.vertex_used + op->floats_per_vertex - 1) / op->floats_per_vertex));
  691.                 sna->render.vertex_index = (sna->render.vertex_used + op->floats_per_vertex - 1) / op->floats_per_vertex;
  692.                 sna->render.vertex_used = sna->render.vertex_index * op->floats_per_vertex;
  693.                 sna->render_state.gen5.floats_per_vertex = op->floats_per_vertex;
  694.         }
  695. }
  696.  
  697. static void
  698. gen5_emit_binding_table(struct sna *sna, uint16_t offset)
  699. {
  700.         if (!DBG_NO_STATE_CACHE &&
  701.             sna->render_state.gen5.surface_table == offset)
  702.                 return;
  703.  
  704.         sna->render_state.gen5.surface_table = offset;
  705.  
  706.         /* Binding table pointers */
  707.         OUT_BATCH(GEN5_3DSTATE_BINDING_TABLE_POINTERS | 4);
  708.         OUT_BATCH(0);           /* vs */
  709.         OUT_BATCH(0);           /* gs */
  710.         OUT_BATCH(0);           /* clip */
  711.         OUT_BATCH(0);           /* sf */
  712.         /* Only the PS uses the binding table */
  713.         OUT_BATCH(offset*4);
  714. }
  715.  
  716. static bool
  717. gen5_emit_pipelined_pointers(struct sna *sna,
  718.                              const struct sna_composite_op *op,
  719.                              int blend, int kernel)
  720. {
  721.         uint16_t sp, bp;
  722.         uint32_t key;
  723.  
  724.         DBG(("%s: has_mask=%d, src=(%d, %d), mask=(%d, %d),kernel=%d, blend=%d, ca=%d, format=%x\n",
  725.              __FUNCTION__, op->u.gen5.ve_id & 2,
  726.              op->src.filter, op->src.repeat,
  727.              op->mask.filter, op->mask.repeat,
  728.              kernel, blend, op->has_component_alpha, (int)op->dst.format));
  729.  
  730.         sp = SAMPLER_OFFSET(op->src.filter, op->src.repeat,
  731.                             op->mask.filter, op->mask.repeat,
  732.                             kernel);
  733.         bp = gen5_get_blend(blend, op->has_component_alpha, op->dst.format);
  734.  
  735.         DBG(("%s: sp=%d, bp=%d\n", __FUNCTION__, sp, bp));
  736.         key = sp | (uint32_t)bp << 16 | (op->mask.bo != NULL) << 31;
  737.         if (key == sna->render_state.gen5.last_pipelined_pointers)
  738.                 return false;
  739.  
  740.  
  741.         OUT_BATCH(GEN5_3DSTATE_PIPELINED_POINTERS | 5);
  742.         OUT_BATCH(sna->render_state.gen5.vs);
  743.         OUT_BATCH(GEN5_GS_DISABLE); /* passthrough */
  744.         OUT_BATCH(GEN5_CLIP_DISABLE); /* passthrough */
  745.         OUT_BATCH(sna->render_state.gen5.sf[op->mask.bo != NULL]);
  746.         OUT_BATCH(sna->render_state.gen5.wm + sp);
  747.         OUT_BATCH(sna->render_state.gen5.cc + bp);
  748.  
  749.         sna->render_state.gen5.last_pipelined_pointers = key;
  750.         return true;
  751. }
  752.  
  753. static void
  754. gen5_emit_drawing_rectangle(struct sna *sna, const struct sna_composite_op *op)
  755. {
  756.         uint32_t limit = (op->dst.height - 1) << 16 | (op->dst.width - 1);
  757.         uint32_t offset = (uint16_t)op->dst.y << 16 | (uint16_t)op->dst.x;
  758.  
  759.         assert(!too_large(op->dst.x, op->dst.y));
  760.         assert(!too_large(op->dst.width, op->dst.height));
  761.  
  762.         if (!DBG_NO_STATE_CACHE &&
  763.             sna->render_state.gen5.drawrect_limit == limit &&
  764.             sna->render_state.gen5.drawrect_offset == offset)
  765.                 return;
  766.  
  767.         sna->render_state.gen5.drawrect_offset = offset;
  768.         sna->render_state.gen5.drawrect_limit = limit;
  769.  
  770.         OUT_BATCH(GEN5_3DSTATE_DRAWING_RECTANGLE | (4 - 2));
  771.         OUT_BATCH(0x00000000);
  772.         OUT_BATCH(limit);
  773.         OUT_BATCH(offset);
  774. }
  775.  
  776. static void
  777. gen5_emit_vertex_elements(struct sna *sna,
  778.                           const struct sna_composite_op *op)
  779. {
  780.         /*
  781.          * vertex data in vertex buffer
  782.          *    position: (x, y)
  783.          *    texture coordinate 0: (u0, v0) if (is_affine is true) else (u0, v0, w0)
  784.          *    texture coordinate 1 if (has_mask is true): same as above
  785.          */
  786.         struct gen5_render_state *render = &sna->render_state.gen5;
  787.         int id = op->u.gen5.ve_id;
  788.         bool has_mask = id >> 2;
  789.         uint32_t format, dw;
  790.  
  791.         if (!DBG_NO_STATE_CACHE && render->ve_id == id)
  792.                 return;
  793.  
  794.         DBG(("%s: changing %d -> %d\n", __FUNCTION__, render->ve_id, id));
  795.         render->ve_id = id;
  796.  
  797.         /* The VUE layout
  798.          *    dword 0-3: pad (0.0, 0.0, 0.0. 0.0)
  799.          *    dword 4-7: position (x, y, 1.0, 1.0),
  800.          *    dword 8-11: texture coordinate 0 (u0, v0, w0, 1.0)
  801.          *    dword 12-15: texture coordinate 1 (u1, v1, w1, 1.0)
  802.          *
  803.          * dword 4-15 are fetched from vertex buffer
  804.          */
  805.         OUT_BATCH(GEN5_3DSTATE_VERTEX_ELEMENTS |
  806.                 ((2 * (has_mask ? 4 : 3)) + 1 - 2));
  807.  
  808.         OUT_BATCH((id << VE0_VERTEX_BUFFER_INDEX_SHIFT) | VE0_VALID |
  809.                   (GEN5_SURFACEFORMAT_R32G32B32A32_FLOAT << VE0_FORMAT_SHIFT) |
  810.                   (0 << VE0_OFFSET_SHIFT));
  811.         OUT_BATCH((VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_0_SHIFT) |
  812.                   (VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_1_SHIFT) |
  813.                   (VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_2_SHIFT) |
  814.                   (VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_3_SHIFT));
  815.  
  816.         /* x,y */
  817.         OUT_BATCH(id << VE0_VERTEX_BUFFER_INDEX_SHIFT | VE0_VALID |
  818.                   GEN5_SURFACEFORMAT_R16G16_SSCALED << VE0_FORMAT_SHIFT |
  819.                   0 << VE0_OFFSET_SHIFT);
  820.         OUT_BATCH(VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT |
  821.                   VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT |
  822.                   VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT |
  823.                   VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT);
  824.  
  825.         /* u0, v0, w0 */
  826.         DBG(("%s: id=%d, first channel %d floats, offset=4b\n", __FUNCTION__,
  827.              id, id & 3));
  828.         dw = VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT;
  829.         switch (id & 3) {
  830.         default:
  831.                 assert(0);
  832.         case 0:
  833.                 format = GEN5_SURFACEFORMAT_R16G16_SSCALED << VE0_FORMAT_SHIFT;
  834.                 dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT;
  835.                 dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT;
  836.                 dw |= VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT;
  837.                 break;
  838.         case 1:
  839.                 format = GEN5_SURFACEFORMAT_R32_FLOAT << VE0_FORMAT_SHIFT;
  840.                 dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT;
  841.                 dw |= VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_1_SHIFT;
  842.                 dw |= VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT;
  843.                 break;
  844.         case 2:
  845.                 format = GEN5_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT;
  846.                 dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT;
  847.                 dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT;
  848.                 dw |= VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT;
  849.                 break;
  850.         case 3:
  851.                 format = GEN5_SURFACEFORMAT_R32G32B32_FLOAT << VE0_FORMAT_SHIFT;
  852.                 dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT;
  853.                 dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT;
  854.                 dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_2_SHIFT;
  855.                 break;
  856.         }
  857.         OUT_BATCH(id << VE0_VERTEX_BUFFER_INDEX_SHIFT | VE0_VALID |
  858.                   format | 4 << VE0_OFFSET_SHIFT);
  859.         OUT_BATCH(dw);
  860.  
  861.         /* u1, v1, w1 */
  862.         if (has_mask) {
  863.                 unsigned offset = 4 + ((id & 3) ?: 1) * sizeof(float);
  864.                 DBG(("%s: id=%x, second channel %d floats, offset=%db\n", __FUNCTION__,
  865.                      id, id >> 2, offset));
  866.                 dw = VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT;
  867.                 switch (id >> 2) {
  868.                 case 1:
  869.                         format = GEN5_SURFACEFORMAT_R32_FLOAT << VE0_FORMAT_SHIFT;
  870.                         dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT;
  871.                         dw |= VFCOMPONENT_STORE_0 << VE1_VFCOMPONENT_1_SHIFT;
  872.                         dw |= VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT;
  873.                         break;
  874.                 default:
  875.                         assert(0);
  876.                 case 2:
  877.                         format = GEN5_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT;
  878.                         dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT;
  879.                         dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT;
  880.                         dw |= VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT;
  881.                         break;
  882.                 case 3:
  883.                         format = GEN5_SURFACEFORMAT_R32G32B32_FLOAT << VE0_FORMAT_SHIFT;
  884.                         dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT;
  885.                         dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT;
  886.                         dw |= VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_2_SHIFT;
  887.                         break;
  888.                 }
  889.                 OUT_BATCH(id << VE0_VERTEX_BUFFER_INDEX_SHIFT | VE0_VALID |
  890.                           format | offset << VE0_OFFSET_SHIFT);
  891.                 OUT_BATCH(dw);
  892.         }
  893. }
  894.  
  895. static void
  896. gen5_emit_state(struct sna *sna,
  897.                 const struct sna_composite_op *op,
  898.                 uint16_t offset)
  899. {
  900.         if (kgem_bo_is_dirty(op->src.bo) || kgem_bo_is_dirty(op->mask.bo)) {
  901.                 DBG(("%s: flushing dirty (%d, %d)\n", __FUNCTION__,
  902.                      kgem_bo_is_dirty(op->src.bo),
  903.                      kgem_bo_is_dirty(op->mask.bo)));
  904.                 OUT_BATCH(MI_FLUSH);
  905.                 kgem_clear_dirty(&sna->kgem);
  906.                 kgem_bo_mark_dirty(op->dst.bo);
  907.         }
  908.  
  909.         /* drawrect must be first for Ironlake BLT workaround */
  910.         gen5_emit_drawing_rectangle(sna, op);
  911.         gen5_emit_binding_table(sna, offset);
  912.         if (gen5_emit_pipelined_pointers(sna, op, op->op, op->u.gen5.wm_kernel))
  913.                 gen5_emit_urb(sna);
  914.         gen5_emit_vertex_elements(sna, op);
  915. }
  916.  
  917. static void gen5_bind_surfaces(struct sna *sna,
  918.                                const struct sna_composite_op *op)
  919. {
  920.         uint32_t *binding_table;
  921.         uint16_t offset;
  922.  
  923.         gen5_get_batch(sna, op);
  924.  
  925.         binding_table = gen5_composite_get_binding_table(sna, &offset);
  926.  
  927.         binding_table[0] =
  928.                 gen5_bind_bo(sna,
  929.                             op->dst.bo, op->dst.width, op->dst.height,
  930.                             gen5_get_dest_format(op->dst.format),
  931.                             true);
  932.         binding_table[1] =
  933.                 gen5_bind_bo(sna,
  934.                              op->src.bo, op->src.width, op->src.height,
  935.                              op->src.card_format,
  936.                              false);
  937.         if (op->mask.bo) {
  938.                 assert(op->u.gen5.ve_id >> 2);
  939.                 binding_table[2] =
  940.                         gen5_bind_bo(sna,
  941.                                      op->mask.bo,
  942.                                      op->mask.width,
  943.                                      op->mask.height,
  944.                                      op->mask.card_format,
  945.                                      false);
  946.         }
  947.  
  948.         if (sna->kgem.surface == offset &&
  949.             *(uint64_t *)(sna->kgem.batch + sna->render_state.gen5.surface_table) == *(uint64_t*)binding_table &&
  950.             (op->mask.bo == NULL ||
  951.              sna->kgem.batch[sna->render_state.gen5.surface_table+2] == binding_table[2])) {
  952.                 sna->kgem.surface += sizeof(struct gen5_surface_state_padded) / sizeof(uint32_t);
  953.                 offset = sna->render_state.gen5.surface_table;
  954.         }
  955.  
  956.         gen5_emit_state(sna, op, offset);
  957. }
  958.  
  959. fastcall static void
  960. gen5_render_composite_blt(struct sna *sna,
  961.                           const struct sna_composite_op *op,
  962.                           const struct sna_composite_rectangles *r)
  963. {
  964.         DBG(("%s: src=(%d, %d)+(%d, %d), mask=(%d, %d)+(%d, %d), dst=(%d, %d)+(%d, %d), size=(%d, %d)\n",
  965.              __FUNCTION__,
  966.              r->src.x, r->src.y, op->src.offset[0], op->src.offset[1],
  967.              r->mask.x, r->mask.y, op->mask.offset[0], op->mask.offset[1],
  968.              r->dst.x, r->dst.y, op->dst.x, op->dst.y,
  969.              r->width, r->height));
  970.  
  971.         gen5_get_rectangles(sna, op, 1, gen5_bind_surfaces);
  972.         op->prim_emit(sna, op, r);
  973. }
  974.  
  975.  
  976. static void
  977. gen5_render_composite_done(struct sna *sna,
  978.                            const struct sna_composite_op *op)
  979. {
  980.         if (sna->render.vertex_offset) {
  981.                 gen4_vertex_flush(sna);
  982.                 gen5_magic_ca_pass(sna,op);
  983.         }
  984.  
  985.         DBG(("%s()\n", __FUNCTION__));
  986.  
  987. }
  988.  
  989.  
  990. static bool
  991. gen5_blit_tex(struct sna *sna,
  992.               uint8_t op, bool scale,
  993.                       PixmapPtr src, struct kgem_bo *src_bo,
  994.                       PixmapPtr mask,struct kgem_bo *mask_bo,
  995.                       PixmapPtr dst, struct kgem_bo *dst_bo,
  996.               int32_t src_x, int32_t src_y,
  997.               int32_t msk_x, int32_t msk_y,
  998.               int32_t dst_x, int32_t dst_y,
  999.               int32_t width, int32_t height,
  1000.               struct sna_composite_op *tmp)
  1001. {
  1002.         DBG(("%s: %dx%d, current mode=%d\n", __FUNCTION__,
  1003.              width, height, sna->kgem.mode));
  1004.  
  1005.     tmp->op = PictOpSrc;
  1006.  
  1007.     tmp->dst.pixmap = dst;
  1008.     tmp->dst.bo     = dst_bo;
  1009.     tmp->dst.width  = dst->drawable.width;
  1010.     tmp->dst.height = dst->drawable.height;
  1011.     tmp->dst.format = PICT_x8r8g8b8;
  1012.  
  1013.  
  1014.         tmp->src.repeat = RepeatNone;
  1015.         tmp->src.filter = PictFilterNearest;
  1016.     tmp->src.is_affine = true;
  1017.  
  1018.     tmp->src.bo = src_bo;
  1019.         tmp->src.pict_format = PICT_x8r8g8b8;
  1020.     tmp->src.card_format = gen5_get_card_format(tmp->src.pict_format);
  1021.     tmp->src.width  = src->drawable.width;
  1022.     tmp->src.height = src->drawable.height;
  1023.  
  1024.  
  1025.     tmp->is_affine = tmp->src.is_affine;
  1026.         tmp->has_component_alpha = false;
  1027.         tmp->need_magic_ca_pass = false;
  1028.        
  1029.     tmp->mask.is_affine = true;
  1030.         tmp->mask.repeat = SAMPLER_EXTEND_NONE;
  1031.         tmp->mask.filter = SAMPLER_FILTER_NEAREST;
  1032.     tmp->mask.bo = mask_bo;
  1033.     tmp->mask.pict_format = PIXMAN_a8;
  1034.     tmp->mask.card_format = gen5_get_card_format(tmp->mask.pict_format);
  1035.     tmp->mask.width  = mask->drawable.width;
  1036.     tmp->mask.height = mask->drawable.height;
  1037.  
  1038.     if( scale )
  1039.     {
  1040.         tmp->src.scale[0] = 1.f/width;
  1041.         tmp->src.scale[1] = 1.f/height;
  1042.     }
  1043.     else
  1044.     {
  1045.         tmp->src.scale[0] = 1.f/src->drawable.width;
  1046.         tmp->src.scale[1] = 1.f/src->drawable.height;
  1047.     }
  1048.  
  1049.     tmp->mask.scale[0] = 1.f/mask->drawable.width;
  1050.     tmp->mask.scale[1] = 1.f/mask->drawable.height;
  1051.        
  1052.        
  1053.         tmp->u.gen5.wm_kernel =
  1054.                 gen5_choose_composite_kernel(tmp->op,
  1055.                                              tmp->mask.bo != NULL,
  1056.                                              tmp->has_component_alpha,
  1057.                                              tmp->is_affine);
  1058.         tmp->u.gen5.ve_id = gen4_choose_composite_emitter(tmp);
  1059.  
  1060.         tmp->blt   = gen5_render_composite_blt;
  1061. //      tmp->box   = gen5_render_composite_box;
  1062.         tmp->done  = gen5_render_composite_done;
  1063.  
  1064.         if (!kgem_check_bo(&sna->kgem,
  1065.                            tmp->dst.bo, tmp->src.bo, tmp->mask.bo, NULL)) {
  1066.                 kgem_submit(&sna->kgem);
  1067.         }
  1068.  
  1069.         gen5_bind_surfaces(sna, tmp);
  1070.         gen5_align_vertex(sna, tmp);
  1071.         return true;
  1072.  
  1073. }
  1074.  
  1075.  
  1076.  
  1077. static void
  1078. gen5_render_flush(struct sna *sna)
  1079. {
  1080.         gen4_vertex_close(sna);
  1081.  
  1082.         assert(sna->render.vb_id == 0);
  1083.         assert(sna->render.vertex_offset == 0);
  1084. }
  1085.  
  1086. static void
  1087. gen5_render_context_switch(struct kgem *kgem,
  1088.                            int new_mode)
  1089. {
  1090.         if (!kgem->nbatch)
  1091.                 return;
  1092.  
  1093.         /* WaNonPipelinedStateCommandFlush
  1094.          *
  1095.          * Ironlake has a limitation that a 3D or Media command can't
  1096.          * be the first command after a BLT, unless it's
  1097.          * non-pipelined.
  1098.          *
  1099.          * We do this by ensuring that the non-pipelined drawrect
  1100.          * is always emitted first following a switch from BLT.
  1101.          */
  1102.         if (kgem->mode == KGEM_BLT) {
  1103.                 struct sna *sna = to_sna_from_kgem(kgem);
  1104.                 DBG(("%s: forcing drawrect on next state emission\n",
  1105.                      __FUNCTION__));
  1106.                 sna->render_state.gen5.drawrect_limit = -1;
  1107.         }
  1108.  
  1109.         if (kgem_ring_is_idle(kgem, kgem->ring)) {
  1110.                 DBG(("%s: GPU idle, flushing\n", __FUNCTION__));
  1111.                 _kgem_submit(kgem);
  1112.         }
  1113. }
  1114.  
  1115. static void
  1116. discard_vbo(struct sna *sna)
  1117. {
  1118.         kgem_bo_destroy(&sna->kgem, sna->render.vbo);
  1119.         sna->render.vbo = NULL;
  1120.         sna->render.vertices = sna->render.vertex_data;
  1121.         sna->render.vertex_size = ARRAY_SIZE(sna->render.vertex_data);
  1122.         sna->render.vertex_used = 0;
  1123.         sna->render.vertex_index = 0;
  1124. }
  1125.  
  1126. static void
  1127. gen5_render_retire(struct kgem *kgem)
  1128. {
  1129.         struct sna *sna;
  1130.  
  1131.         sna = container_of(kgem, struct sna, kgem);
  1132.         if (kgem->nbatch == 0 && sna->render.vbo && !kgem_bo_is_busy(sna->render.vbo)) {
  1133.                 DBG(("%s: resetting idle vbo\n", __FUNCTION__));
  1134.                 sna->render.vertex_used = 0;
  1135.                 sna->render.vertex_index = 0;
  1136.         }
  1137. }
  1138.  
  1139. static void
  1140. gen5_render_expire(struct kgem *kgem)
  1141. {
  1142.         struct sna *sna;
  1143.  
  1144.         sna = container_of(kgem, struct sna, kgem);
  1145.         if (sna->render.vbo && !sna->render.vertex_used) {
  1146.                 DBG(("%s: discarding vbo\n", __FUNCTION__));
  1147.                 discard_vbo(sna);
  1148.         }
  1149. }
  1150.  
  1151. static void gen5_render_reset(struct sna *sna)
  1152. {
  1153.         sna->render_state.gen5.needs_invariant = true;
  1154.         sna->render_state.gen5.ve_id = -1;
  1155.         sna->render_state.gen5.last_primitive = -1;
  1156.         sna->render_state.gen5.last_pipelined_pointers = 0;
  1157.  
  1158.         sna->render_state.gen5.drawrect_offset = -1;
  1159.         sna->render_state.gen5.drawrect_limit = -1;
  1160.         sna->render_state.gen5.surface_table = -1;
  1161.  
  1162.         if (sna->render.vbo &&
  1163.             !kgem_bo_is_mappable(&sna->kgem, sna->render.vbo)) {
  1164.                 DBG(("%s: discarding unmappable vbo\n", __FUNCTION__));
  1165.                 discard_vbo(sna);
  1166.         }
  1167.  
  1168.         sna->render.vertex_offset = 0;
  1169.         sna->render.nvertex_reloc = 0;
  1170.         sna->render.vb_id = 0;
  1171. }
  1172.  
  1173. static void gen5_render_fini(struct sna *sna)
  1174. {
  1175.         kgem_bo_destroy(&sna->kgem, sna->render_state.gen5.general_bo);
  1176. }
  1177.  
  1178. static uint32_t gen5_create_vs_unit_state(struct sna_static_stream *stream)
  1179. {
  1180.         struct gen5_vs_unit_state *vs = sna_static_stream_map(stream, sizeof(*vs), 32);
  1181.  
  1182.         /* Set up the vertex shader to be disabled (passthrough) */
  1183.         vs->thread4.nr_urb_entries = URB_VS_ENTRIES >> 2;
  1184.         vs->thread4.urb_entry_allocation_size = URB_VS_ENTRY_SIZE - 1;
  1185.         vs->vs6.vs_enable = 0;
  1186.         vs->vs6.vert_cache_disable = 1;
  1187.  
  1188.         return sna_static_stream_offsetof(stream, vs);
  1189. }
  1190.  
  1191. static uint32_t gen5_create_sf_state(struct sna_static_stream *stream,
  1192.                                      uint32_t kernel)
  1193. {
  1194.         struct gen5_sf_unit_state *sf_state;
  1195.  
  1196.         sf_state = sna_static_stream_map(stream, sizeof(*sf_state), 32);
  1197.  
  1198.         sf_state->thread0.grf_reg_count = GEN5_GRF_BLOCKS(SF_KERNEL_NUM_GRF);
  1199.         sf_state->thread0.kernel_start_pointer = kernel >> 6;
  1200.  
  1201.         sf_state->thread3.const_urb_entry_read_length = 0;      /* no const URBs */
  1202.         sf_state->thread3.const_urb_entry_read_offset = 0;      /* no const URBs */
  1203.         sf_state->thread3.urb_entry_read_length = 1;    /* 1 URB per vertex */
  1204.         /* don't smash vertex header, read start from dw8 */
  1205.         sf_state->thread3.urb_entry_read_offset = 1;
  1206.         sf_state->thread3.dispatch_grf_start_reg = 3;
  1207.         sf_state->thread4.max_threads = SF_MAX_THREADS - 1;
  1208.         sf_state->thread4.urb_entry_allocation_size = URB_SF_ENTRY_SIZE - 1;
  1209.         sf_state->thread4.nr_urb_entries = URB_SF_ENTRIES;
  1210.         sf_state->sf5.viewport_transform = false;       /* skip viewport */
  1211.         sf_state->sf6.cull_mode = GEN5_CULLMODE_NONE;
  1212.         sf_state->sf6.scissor = 0;
  1213.         sf_state->sf7.trifan_pv = 2;
  1214.         sf_state->sf6.dest_org_vbias = 0x8;
  1215.         sf_state->sf6.dest_org_hbias = 0x8;
  1216.  
  1217.         return sna_static_stream_offsetof(stream, sf_state);
  1218. }
  1219.  
  1220. static uint32_t gen5_create_sampler_state(struct sna_static_stream *stream,
  1221.                                           sampler_filter_t src_filter,
  1222.                                           sampler_extend_t src_extend,
  1223.                                           sampler_filter_t mask_filter,
  1224.                                           sampler_extend_t mask_extend)
  1225. {
  1226.         struct gen5_sampler_state *sampler_state;
  1227.  
  1228.         sampler_state = sna_static_stream_map(stream,
  1229.                                               sizeof(struct gen5_sampler_state) * 2,
  1230.                                               32);
  1231.         sampler_state_init(&sampler_state[0], src_filter, src_extend);
  1232.         sampler_state_init(&sampler_state[1], mask_filter, mask_extend);
  1233.  
  1234.         return sna_static_stream_offsetof(stream, sampler_state);
  1235. }
  1236.  
  1237. static void gen5_init_wm_state(struct gen5_wm_unit_state *state,
  1238.                                bool has_mask,
  1239.                                uint32_t kernel,
  1240.                                uint32_t sampler)
  1241. {
  1242.         state->thread0.grf_reg_count = GEN5_GRF_BLOCKS(PS_KERNEL_NUM_GRF);
  1243.         state->thread0.kernel_start_pointer = kernel >> 6;
  1244.  
  1245.         state->thread1.single_program_flow = 0;
  1246.  
  1247.         /* scratch space is not used in our kernel */
  1248.         state->thread2.scratch_space_base_pointer = 0;
  1249.         state->thread2.per_thread_scratch_space = 0;
  1250.  
  1251.         state->thread3.const_urb_entry_read_length = 0;
  1252.         state->thread3.const_urb_entry_read_offset = 0;
  1253.  
  1254.         state->thread3.urb_entry_read_offset = 0;
  1255.         /* wm kernel use urb from 3, see wm_program in compiler module */
  1256.         state->thread3.dispatch_grf_start_reg = 3;      /* must match kernel */
  1257.  
  1258.         state->wm4.sampler_count = 0;   /* hardware requirement */
  1259.  
  1260.         state->wm4.sampler_state_pointer = sampler >> 5;
  1261.         state->wm5.max_threads = PS_MAX_THREADS - 1;
  1262.         state->wm5.transposed_urb_read = 0;
  1263.         state->wm5.thread_dispatch_enable = 1;
  1264.         /* just use 16-pixel dispatch (4 subspans), don't need to change kernel
  1265.          * start point
  1266.          */
  1267.         state->wm5.enable_16_pix = 1;
  1268.         state->wm5.enable_8_pix = 0;
  1269.         state->wm5.early_depth_test = 1;
  1270.  
  1271.         /* Each pair of attributes (src/mask coords) is two URB entries */
  1272.         if (has_mask) {
  1273.                 state->thread1.binding_table_entry_count = 3;   /* 2 tex and fb */
  1274.                 state->thread3.urb_entry_read_length = 4;
  1275.         } else {
  1276.                 state->thread1.binding_table_entry_count = 2;   /* 1 tex and fb */
  1277.                 state->thread3.urb_entry_read_length = 2;
  1278.         }
  1279.  
  1280.         /* binding table entry count is only used for prefetching,
  1281.          * and it has to be set 0 for Ironlake
  1282.          */
  1283.         state->thread1.binding_table_entry_count = 0;
  1284. }
  1285.  
  1286. static uint32_t gen5_create_cc_unit_state(struct sna_static_stream *stream)
  1287. {
  1288.         uint8_t *ptr, *base;
  1289.         int i, j;
  1290.  
  1291.         base = ptr =
  1292.                 sna_static_stream_map(stream,
  1293.                                       GEN5_BLENDFACTOR_COUNT*GEN5_BLENDFACTOR_COUNT*64,
  1294.                                       64);
  1295.  
  1296.         for (i = 0; i < GEN5_BLENDFACTOR_COUNT; i++) {
  1297.                 for (j = 0; j < GEN5_BLENDFACTOR_COUNT; j++) {
  1298.                         struct gen5_cc_unit_state *state =
  1299.                                 (struct gen5_cc_unit_state *)ptr;
  1300.  
  1301.                         state->cc3.blend_enable =
  1302.                                 !(j == GEN5_BLENDFACTOR_ZERO && i == GEN5_BLENDFACTOR_ONE);
  1303.  
  1304.                         state->cc5.logicop_func = 0xc;  /* COPY */
  1305.                         state->cc5.ia_blend_function = GEN5_BLENDFUNCTION_ADD;
  1306.  
  1307.                         /* Fill in alpha blend factors same as color, for the future. */
  1308.                         state->cc5.ia_src_blend_factor = i;
  1309.                         state->cc5.ia_dest_blend_factor = j;
  1310.  
  1311.                         state->cc6.blend_function = GEN5_BLENDFUNCTION_ADD;
  1312.                         state->cc6.clamp_post_alpha_blend = 1;
  1313.                         state->cc6.clamp_pre_alpha_blend = 1;
  1314.                         state->cc6.src_blend_factor = i;
  1315.                         state->cc6.dest_blend_factor = j;
  1316.  
  1317.                         ptr += 64;
  1318.                 }
  1319.         }
  1320.  
  1321.         return sna_static_stream_offsetof(stream, base);
  1322. }
  1323.  
  1324. static bool gen5_render_setup(struct sna *sna)
  1325. {
  1326.         struct gen5_render_state *state = &sna->render_state.gen5;
  1327.         struct sna_static_stream general;
  1328.         struct gen5_wm_unit_state_padded *wm_state;
  1329.         uint32_t sf[2], wm[KERNEL_COUNT];
  1330.         int i, j, k, l, m;
  1331.  
  1332.         sna_static_stream_init(&general);
  1333.  
  1334.         /* Zero pad the start. If you see an offset of 0x0 in the batchbuffer
  1335.          * dumps, you know it points to zero.
  1336.          */
  1337.         null_create(&general);
  1338.  
  1339.         /* Set up the two SF states (one for blending with a mask, one without) */
  1340.         sf[0] = sna_static_stream_compile_sf(sna, &general, brw_sf_kernel__nomask);
  1341.         sf[1] = sna_static_stream_compile_sf(sna, &general, brw_sf_kernel__mask);
  1342.  
  1343.         for (m = 0; m < KERNEL_COUNT; m++) {
  1344.                 if (wm_kernels[m].size) {
  1345.                         wm[m] = sna_static_stream_add(&general,
  1346.                                                       wm_kernels[m].data,
  1347.                                                       wm_kernels[m].size,
  1348.                                                       64);
  1349.                 } else {
  1350.                         wm[m] = sna_static_stream_compile_wm(sna, &general,
  1351.                                                              wm_kernels[m].data,
  1352.                                                              16);
  1353.                 }
  1354.                 assert(wm[m]);
  1355.         }
  1356.  
  1357.         state->vs = gen5_create_vs_unit_state(&general);
  1358.  
  1359.         state->sf[0] = gen5_create_sf_state(&general, sf[0]);
  1360.         state->sf[1] = gen5_create_sf_state(&general, sf[1]);
  1361.  
  1362.  
  1363.         /* Set up the WM states: each filter/extend type for source and mask, per
  1364.          * kernel.
  1365.          */
  1366.         wm_state = sna_static_stream_map(&general,
  1367.                                           sizeof(*wm_state) * KERNEL_COUNT *
  1368.                                           FILTER_COUNT * EXTEND_COUNT *
  1369.                                           FILTER_COUNT * EXTEND_COUNT,
  1370.                                           64);
  1371.         state->wm = sna_static_stream_offsetof(&general, wm_state);
  1372.         for (i = 0; i < FILTER_COUNT; i++) {
  1373.                 for (j = 0; j < EXTEND_COUNT; j++) {
  1374.                         for (k = 0; k < FILTER_COUNT; k++) {
  1375.                                 for (l = 0; l < EXTEND_COUNT; l++) {
  1376.                                         uint32_t sampler_state;
  1377.  
  1378.                                         sampler_state =
  1379.                                                 gen5_create_sampler_state(&general,
  1380.                                                                           i, j,
  1381.                                                                           k, l);
  1382.  
  1383.                                         for (m = 0; m < KERNEL_COUNT; m++) {
  1384.                                                 gen5_init_wm_state(&wm_state->state,
  1385.                                                                    wm_kernels[m].has_mask,
  1386.                                                                    wm[m], sampler_state);
  1387.                                                 wm_state++;
  1388.                                         }
  1389.                                 }
  1390.         }
  1391.         }
  1392.     }
  1393.  
  1394.     state->cc = gen5_create_cc_unit_state(&general);
  1395.  
  1396.     state->general_bo = sna_static_stream_fini(sna, &general);
  1397.     return state->general_bo != NULL;
  1398. }
  1399.  
  1400. bool gen5_render_init(struct sna *sna)
  1401. {
  1402.         if (!gen5_render_setup(sna))
  1403.                 return false;
  1404.  
  1405.         sna->kgem.context_switch = gen5_render_context_switch;
  1406.         sna->kgem.retire = gen5_render_retire;
  1407.         sna->kgem.expire = gen5_render_expire;
  1408.  
  1409.     sna->render.blit_tex = gen5_blit_tex;
  1410.  
  1411.         sna->render.flush = gen5_render_flush;
  1412.         sna->render.reset = gen5_render_reset;
  1413.         sna->render.fini = gen5_render_fini;
  1414.  
  1415.         sna->render.max_3d_size = MAX_3D_SIZE;
  1416.         sna->render.max_3d_pitch = 1 << 18;
  1417.     sna->render.caps = HW_BIT_BLIT | HW_TEX_BLIT;
  1418.        
  1419.         return true;
  1420. }
  1421.