gen7_render.c revision 42542f5f
103b705cfSriastradh/* 203b705cfSriastradh * Copyright © 2006,2008,2011 Intel Corporation 303b705cfSriastradh * Copyright © 2007 Red Hat, Inc. 403b705cfSriastradh * 503b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a 603b705cfSriastradh * copy of this software and associated documentation files (the "Software"), 703b705cfSriastradh * to deal in the Software without restriction, including without limitation 803b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 903b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the 1003b705cfSriastradh * Software is furnished to do so, subject to the following conditions: 1103b705cfSriastradh * 1203b705cfSriastradh * The above copyright notice and this permission notice (including the next 1303b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the 1403b705cfSriastradh * Software. 1503b705cfSriastradh * 1603b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1703b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1803b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1903b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2003b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2103b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2203b705cfSriastradh * SOFTWARE. 2303b705cfSriastradh * 2403b705cfSriastradh * Authors: 2503b705cfSriastradh * Wang Zhenyu <zhenyu.z.wang@sna.com> 2603b705cfSriastradh * Eric Anholt <eric@anholt.net> 2703b705cfSriastradh * Carl Worth <cworth@redhat.com> 2803b705cfSriastradh * Keith Packard <keithp@keithp.com> 2903b705cfSriastradh * Chris Wilson <chris@chris-wilson.co.uk> 3003b705cfSriastradh * 3103b705cfSriastradh */ 3203b705cfSriastradh 3303b705cfSriastradh#ifdef HAVE_CONFIG_H 3403b705cfSriastradh#include "config.h" 3503b705cfSriastradh#endif 3603b705cfSriastradh 3703b705cfSriastradh#include "sna.h" 3803b705cfSriastradh#include "sna_reg.h" 3903b705cfSriastradh#include "sna_render.h" 4003b705cfSriastradh#include "sna_render_inline.h" 4103b705cfSriastradh#include "sna_video.h" 4203b705cfSriastradh 4303b705cfSriastradh#include "brw/brw.h" 4403b705cfSriastradh#include "gen7_render.h" 4542542f5fSchristos#include "gen4_common.h" 4603b705cfSriastradh#include "gen4_source.h" 4703b705cfSriastradh#include "gen4_vertex.h" 4842542f5fSchristos#include "gen6_common.h" 4942542f5fSchristos 5042542f5fSchristos#define ALWAYS_INVALIDATE 0 5142542f5fSchristos#define ALWAYS_FLUSH 0 5242542f5fSchristos#define ALWAYS_STALL 0 5303b705cfSriastradh 5403b705cfSriastradh#define NO_COMPOSITE 0 5503b705cfSriastradh#define NO_COMPOSITE_SPANS 0 5603b705cfSriastradh#define NO_COPY 0 5703b705cfSriastradh#define NO_COPY_BOXES 0 5803b705cfSriastradh#define NO_FILL 0 5903b705cfSriastradh#define NO_FILL_BOXES 0 6003b705cfSriastradh#define NO_FILL_ONE 0 6103b705cfSriastradh#define NO_FILL_CLEAR 0 6203b705cfSriastradh 6303b705cfSriastradh#define NO_RING_SWITCH 0 6403b705cfSriastradh 6503b705cfSriastradh#define USE_8_PIXEL_DISPATCH 1 6603b705cfSriastradh#define USE_16_PIXEL_DISPATCH 1 6703b705cfSriastradh#define USE_32_PIXEL_DISPATCH 0 6803b705cfSriastradh 6903b705cfSriastradh#if !USE_8_PIXEL_DISPATCH && !USE_16_PIXEL_DISPATCH && !USE_32_PIXEL_DISPATCH 7003b705cfSriastradh#error "Must select at least 8, 16 or 32 pixel dispatch" 7103b705cfSriastradh#endif 7203b705cfSriastradh 7303b705cfSriastradh#define GEN7_MAX_SIZE 16384 7403b705cfSriastradh 7503b705cfSriastradh/* XXX Todo 7603b705cfSriastradh * 7703b705cfSriastradh * STR (software tiled rendering) mode. No, really. 7803b705cfSriastradh * 64x32 pixel blocks align with the rendering cache. Worth considering. 7903b705cfSriastradh */ 8003b705cfSriastradh 8103b705cfSriastradh#define is_aligned(x, y) (((x) & ((y) - 1)) == 0) 8203b705cfSriastradh 8303b705cfSriastradhstruct gt_info { 8403b705cfSriastradh const char *name; 8503b705cfSriastradh uint32_t max_vs_threads; 8603b705cfSriastradh uint32_t max_gs_threads; 8703b705cfSriastradh uint32_t max_wm_threads; 8803b705cfSriastradh struct { 8903b705cfSriastradh int size; 9003b705cfSriastradh int max_vs_entries; 9103b705cfSriastradh int max_gs_entries; 9203b705cfSriastradh int push_ps_size; /* in 1KBs */ 9303b705cfSriastradh } urb; 9442542f5fSchristos int gt; 9542542f5fSchristos uint32_t mocs; 9603b705cfSriastradh}; 9703b705cfSriastradh 9803b705cfSriastradhstatic const struct gt_info ivb_gt_info = { 9903b705cfSriastradh .name = "Ivybridge (gen7)", 10003b705cfSriastradh .max_vs_threads = 16, 10103b705cfSriastradh .max_gs_threads = 16, 10203b705cfSriastradh .max_wm_threads = (16-1) << IVB_PS_MAX_THREADS_SHIFT, 10303b705cfSriastradh .urb = { 128, 64, 64, 8 }, 10442542f5fSchristos .gt = 0, 10503b705cfSriastradh}; 10603b705cfSriastradh 10703b705cfSriastradhstatic const struct gt_info ivb_gt1_info = { 10803b705cfSriastradh .name = "Ivybridge (gen7, gt1)", 10903b705cfSriastradh .max_vs_threads = 36, 11003b705cfSriastradh .max_gs_threads = 36, 11103b705cfSriastradh .max_wm_threads = (48-1) << IVB_PS_MAX_THREADS_SHIFT, 11203b705cfSriastradh .urb = { 128, 512, 192, 8 }, 11342542f5fSchristos .gt = 1, 11442542f5fSchristos .mocs = 3, 11503b705cfSriastradh}; 11603b705cfSriastradh 11703b705cfSriastradhstatic const struct gt_info ivb_gt2_info = { 11803b705cfSriastradh .name = "Ivybridge (gen7, gt2)", 11903b705cfSriastradh .max_vs_threads = 128, 12003b705cfSriastradh .max_gs_threads = 128, 12103b705cfSriastradh .max_wm_threads = (172-1) << IVB_PS_MAX_THREADS_SHIFT, 12203b705cfSriastradh .urb = { 256, 704, 320, 8 }, 12342542f5fSchristos .gt = 2, 12442542f5fSchristos .mocs = 3, 12503b705cfSriastradh}; 12603b705cfSriastradh 12703b705cfSriastradhstatic const struct gt_info byt_gt_info = { 12803b705cfSriastradh .name = "Baytrail (gen7)", 12903b705cfSriastradh .max_vs_threads = 36, 13003b705cfSriastradh .max_gs_threads = 36, 13103b705cfSriastradh .max_wm_threads = (48-1) << IVB_PS_MAX_THREADS_SHIFT, 13203b705cfSriastradh .urb = { 128, 512, 192, 8 }, 13342542f5fSchristos .gt = 1, 13403b705cfSriastradh}; 13503b705cfSriastradh 13603b705cfSriastradhstatic const struct gt_info hsw_gt_info = { 13703b705cfSriastradh .name = "Haswell (gen7.5)", 13803b705cfSriastradh .max_vs_threads = 8, 13903b705cfSriastradh .max_gs_threads = 8, 14003b705cfSriastradh .max_wm_threads = 14103b705cfSriastradh (8 - 1) << HSW_PS_MAX_THREADS_SHIFT | 14203b705cfSriastradh 1 << HSW_PS_SAMPLE_MASK_SHIFT, 14303b705cfSriastradh .urb = { 128, 64, 64, 8 }, 14442542f5fSchristos .gt = 0, 14503b705cfSriastradh}; 14603b705cfSriastradh 14703b705cfSriastradhstatic const struct gt_info hsw_gt1_info = { 14803b705cfSriastradh .name = "Haswell (gen7.5, gt1)", 14903b705cfSriastradh .max_vs_threads = 70, 15003b705cfSriastradh .max_gs_threads = 70, 15103b705cfSriastradh .max_wm_threads = 15203b705cfSriastradh (102 - 1) << HSW_PS_MAX_THREADS_SHIFT | 15303b705cfSriastradh 1 << HSW_PS_SAMPLE_MASK_SHIFT, 15403b705cfSriastradh .urb = { 128, 640, 256, 8 }, 15542542f5fSchristos .gt = 1, 15642542f5fSchristos .mocs = 5, 15703b705cfSriastradh}; 15803b705cfSriastradh 15903b705cfSriastradhstatic const struct gt_info hsw_gt2_info = { 16003b705cfSriastradh .name = "Haswell (gen7.5, gt2)", 16103b705cfSriastradh .max_vs_threads = 140, 16203b705cfSriastradh .max_gs_threads = 140, 16303b705cfSriastradh .max_wm_threads = 16403b705cfSriastradh (140 - 1) << HSW_PS_MAX_THREADS_SHIFT | 16503b705cfSriastradh 1 << HSW_PS_SAMPLE_MASK_SHIFT, 16603b705cfSriastradh .urb = { 256, 1664, 640, 8 }, 16742542f5fSchristos .gt = 2, 16842542f5fSchristos .mocs = 5, 16903b705cfSriastradh}; 17003b705cfSriastradh 17103b705cfSriastradhstatic const struct gt_info hsw_gt3_info = { 17203b705cfSriastradh .name = "Haswell (gen7.5, gt3)", 17303b705cfSriastradh .max_vs_threads = 280, 17403b705cfSriastradh .max_gs_threads = 280, 17503b705cfSriastradh .max_wm_threads = 17603b705cfSriastradh (280 - 1) << HSW_PS_MAX_THREADS_SHIFT | 17703b705cfSriastradh 1 << HSW_PS_SAMPLE_MASK_SHIFT, 17803b705cfSriastradh .urb = { 512, 3328, 1280, 16 }, 17942542f5fSchristos .gt = 3, 18042542f5fSchristos .mocs = 5, 18103b705cfSriastradh}; 18203b705cfSriastradh 18303b705cfSriastradhinline static bool is_ivb(struct sna *sna) 18403b705cfSriastradh{ 18503b705cfSriastradh return sna->kgem.gen == 070; 18603b705cfSriastradh} 18703b705cfSriastradh 18803b705cfSriastradhinline static bool is_byt(struct sna *sna) 18903b705cfSriastradh{ 19003b705cfSriastradh return sna->kgem.gen == 071; 19103b705cfSriastradh} 19203b705cfSriastradh 19303b705cfSriastradhinline static bool is_hsw(struct sna *sna) 19403b705cfSriastradh{ 19503b705cfSriastradh return sna->kgem.gen == 075; 19603b705cfSriastradh} 19703b705cfSriastradh 19803b705cfSriastradhstatic const uint32_t ps_kernel_packed[][4] = { 19903b705cfSriastradh#include "exa_wm_src_affine.g7b" 20003b705cfSriastradh#include "exa_wm_src_sample_argb.g7b" 20103b705cfSriastradh#include "exa_wm_yuv_rgb.g7b" 20203b705cfSriastradh#include "exa_wm_write.g7b" 20303b705cfSriastradh}; 20403b705cfSriastradh 20503b705cfSriastradhstatic const uint32_t ps_kernel_planar[][4] = { 20603b705cfSriastradh#include "exa_wm_src_affine.g7b" 20703b705cfSriastradh#include "exa_wm_src_sample_planar.g7b" 20803b705cfSriastradh#include "exa_wm_yuv_rgb.g7b" 20903b705cfSriastradh#include "exa_wm_write.g7b" 21003b705cfSriastradh}; 21103b705cfSriastradh 21203b705cfSriastradh#define KERNEL(kernel_enum, kernel, num_surfaces) \ 21303b705cfSriastradh [GEN7_WM_KERNEL_##kernel_enum] = {#kernel_enum, kernel, sizeof(kernel), num_surfaces} 21403b705cfSriastradh#define NOKERNEL(kernel_enum, func, num_surfaces) \ 21503b705cfSriastradh [GEN7_WM_KERNEL_##kernel_enum] = {#kernel_enum, (void *)func, 0, num_surfaces} 21603b705cfSriastradhstatic const struct wm_kernel_info { 21703b705cfSriastradh const char *name; 21803b705cfSriastradh const void *data; 21903b705cfSriastradh unsigned int size; 22003b705cfSriastradh int num_surfaces; 22103b705cfSriastradh} wm_kernels[] = { 22203b705cfSriastradh NOKERNEL(NOMASK, brw_wm_kernel__affine, 2), 22303b705cfSriastradh NOKERNEL(NOMASK_P, brw_wm_kernel__projective, 2), 22403b705cfSriastradh 22503b705cfSriastradh NOKERNEL(MASK, brw_wm_kernel__affine_mask, 3), 22603b705cfSriastradh NOKERNEL(MASK_P, brw_wm_kernel__projective_mask, 3), 22703b705cfSriastradh 22803b705cfSriastradh NOKERNEL(MASKCA, brw_wm_kernel__affine_mask_ca, 3), 22903b705cfSriastradh NOKERNEL(MASKCA_P, brw_wm_kernel__projective_mask_ca, 3), 23003b705cfSriastradh 23103b705cfSriastradh NOKERNEL(MASKSA, brw_wm_kernel__affine_mask_sa, 3), 23203b705cfSriastradh NOKERNEL(MASKSA_P, brw_wm_kernel__projective_mask_sa, 3), 23303b705cfSriastradh 23403b705cfSriastradh NOKERNEL(OPACITY, brw_wm_kernel__affine_opacity, 2), 23503b705cfSriastradh NOKERNEL(OPACITY_P, brw_wm_kernel__projective_opacity, 2), 23603b705cfSriastradh 23703b705cfSriastradh KERNEL(VIDEO_PLANAR, ps_kernel_planar, 7), 23803b705cfSriastradh KERNEL(VIDEO_PACKED, ps_kernel_packed, 2), 23903b705cfSriastradh}; 24003b705cfSriastradh#undef KERNEL 24103b705cfSriastradh 24203b705cfSriastradhstatic const struct blendinfo { 24303b705cfSriastradh bool src_alpha; 24403b705cfSriastradh uint32_t src_blend; 24503b705cfSriastradh uint32_t dst_blend; 24603b705cfSriastradh} gen7_blend_op[] = { 24703b705cfSriastradh /* Clear */ {0, GEN7_BLENDFACTOR_ZERO, GEN7_BLENDFACTOR_ZERO}, 24803b705cfSriastradh /* Src */ {0, GEN7_BLENDFACTOR_ONE, GEN7_BLENDFACTOR_ZERO}, 24903b705cfSriastradh /* Dst */ {0, GEN7_BLENDFACTOR_ZERO, GEN7_BLENDFACTOR_ONE}, 25003b705cfSriastradh /* Over */ {1, GEN7_BLENDFACTOR_ONE, GEN7_BLENDFACTOR_INV_SRC_ALPHA}, 25103b705cfSriastradh /* OverReverse */ {0, GEN7_BLENDFACTOR_INV_DST_ALPHA, GEN7_BLENDFACTOR_ONE}, 25203b705cfSriastradh /* In */ {0, GEN7_BLENDFACTOR_DST_ALPHA, GEN7_BLENDFACTOR_ZERO}, 25303b705cfSriastradh /* InReverse */ {1, GEN7_BLENDFACTOR_ZERO, GEN7_BLENDFACTOR_SRC_ALPHA}, 25403b705cfSriastradh /* Out */ {0, GEN7_BLENDFACTOR_INV_DST_ALPHA, GEN7_BLENDFACTOR_ZERO}, 25503b705cfSriastradh /* OutReverse */ {1, GEN7_BLENDFACTOR_ZERO, GEN7_BLENDFACTOR_INV_SRC_ALPHA}, 25603b705cfSriastradh /* Atop */ {1, GEN7_BLENDFACTOR_DST_ALPHA, GEN7_BLENDFACTOR_INV_SRC_ALPHA}, 25703b705cfSriastradh /* AtopReverse */ {1, GEN7_BLENDFACTOR_INV_DST_ALPHA, GEN7_BLENDFACTOR_SRC_ALPHA}, 25803b705cfSriastradh /* Xor */ {1, GEN7_BLENDFACTOR_INV_DST_ALPHA, GEN7_BLENDFACTOR_INV_SRC_ALPHA}, 25903b705cfSriastradh /* Add */ {0, GEN7_BLENDFACTOR_ONE, GEN7_BLENDFACTOR_ONE}, 26003b705cfSriastradh}; 26103b705cfSriastradh 26203b705cfSriastradh/** 26303b705cfSriastradh * Highest-valued BLENDFACTOR used in gen7_blend_op. 26403b705cfSriastradh * 26503b705cfSriastradh * This leaves out GEN7_BLENDFACTOR_INV_DST_COLOR, 26603b705cfSriastradh * GEN7_BLENDFACTOR_INV_CONST_{COLOR,ALPHA}, 26703b705cfSriastradh * GEN7_BLENDFACTOR_INV_SRC1_{COLOR,ALPHA} 26803b705cfSriastradh */ 26903b705cfSriastradh#define GEN7_BLENDFACTOR_COUNT (GEN7_BLENDFACTOR_INV_DST_ALPHA + 1) 27003b705cfSriastradh 27103b705cfSriastradh#define GEN7_BLEND_STATE_PADDED_SIZE ALIGN(sizeof(struct gen7_blend_state), 64) 27203b705cfSriastradh 27303b705cfSriastradh#define BLEND_OFFSET(s, d) \ 27403b705cfSriastradh ((d != GEN7_BLENDFACTOR_ZERO) << 15 | \ 27503b705cfSriastradh (((s) * GEN7_BLENDFACTOR_COUNT + (d)) * GEN7_BLEND_STATE_PADDED_SIZE)) 27603b705cfSriastradh 27703b705cfSriastradh#define NO_BLEND BLEND_OFFSET(GEN7_BLENDFACTOR_ONE, GEN7_BLENDFACTOR_ZERO) 27803b705cfSriastradh#define CLEAR BLEND_OFFSET(GEN7_BLENDFACTOR_ZERO, GEN7_BLENDFACTOR_ZERO) 27903b705cfSriastradh 28003b705cfSriastradh#define SAMPLER_OFFSET(sf, se, mf, me) \ 28103b705cfSriastradh ((((((sf) * EXTEND_COUNT + (se)) * FILTER_COUNT + (mf)) * EXTEND_COUNT + (me)) + 2) * 2 * sizeof(struct gen7_sampler_state)) 28203b705cfSriastradh 28303b705cfSriastradh#define VERTEX_2s2s 0 28403b705cfSriastradh 28503b705cfSriastradh#define COPY_SAMPLER 0 28603b705cfSriastradh#define COPY_VERTEX VERTEX_2s2s 28703b705cfSriastradh#define COPY_FLAGS(a) GEN7_SET_FLAGS(COPY_SAMPLER, (a) == GXcopy ? NO_BLEND : CLEAR, GEN7_WM_KERNEL_NOMASK, COPY_VERTEX) 28803b705cfSriastradh 28903b705cfSriastradh#define FILL_SAMPLER (2 * sizeof(struct gen7_sampler_state)) 29003b705cfSriastradh#define FILL_VERTEX VERTEX_2s2s 29103b705cfSriastradh#define FILL_FLAGS(op, format) GEN7_SET_FLAGS(FILL_SAMPLER, gen7_get_blend((op), false, (format)), GEN7_WM_KERNEL_NOMASK, FILL_VERTEX) 29203b705cfSriastradh#define FILL_FLAGS_NOBLEND GEN7_SET_FLAGS(FILL_SAMPLER, NO_BLEND, GEN7_WM_KERNEL_NOMASK, FILL_VERTEX) 29303b705cfSriastradh 29403b705cfSriastradh#define GEN7_SAMPLER(f) (((f) >> 16) & 0xfff0) 29503b705cfSriastradh#define GEN7_BLEND(f) (((f) >> 0) & 0x7ff0) 29603b705cfSriastradh#define GEN7_READS_DST(f) (((f) >> 15) & 1) 29703b705cfSriastradh#define GEN7_KERNEL(f) (((f) >> 16) & 0xf) 29803b705cfSriastradh#define GEN7_VERTEX(f) (((f) >> 0) & 0xf) 29903b705cfSriastradh#define GEN7_SET_FLAGS(S, B, K, V) (((S) | (K)) << 16 | ((B) | (V))) 30003b705cfSriastradh 30103b705cfSriastradh#define OUT_BATCH(v) batch_emit(sna, v) 30203b705cfSriastradh#define OUT_VERTEX(x,y) vertex_emit_2s(sna, x,y) 30303b705cfSriastradh#define OUT_VERTEX_F(v) vertex_emit(sna, v) 30403b705cfSriastradh 30503b705cfSriastradhstatic inline bool too_large(int width, int height) 30603b705cfSriastradh{ 30703b705cfSriastradh return width > GEN7_MAX_SIZE || height > GEN7_MAX_SIZE; 30803b705cfSriastradh} 30903b705cfSriastradh 31003b705cfSriastradhstatic uint32_t gen7_get_blend(int op, 31103b705cfSriastradh bool has_component_alpha, 31203b705cfSriastradh uint32_t dst_format) 31303b705cfSriastradh{ 31403b705cfSriastradh uint32_t src, dst; 31503b705cfSriastradh 31603b705cfSriastradh src = gen7_blend_op[op].src_blend; 31703b705cfSriastradh dst = gen7_blend_op[op].dst_blend; 31803b705cfSriastradh 31903b705cfSriastradh /* If there's no dst alpha channel, adjust the blend op so that 32003b705cfSriastradh * we'll treat it always as 1. 32103b705cfSriastradh */ 32203b705cfSriastradh if (PICT_FORMAT_A(dst_format) == 0) { 32303b705cfSriastradh if (src == GEN7_BLENDFACTOR_DST_ALPHA) 32403b705cfSriastradh src = GEN7_BLENDFACTOR_ONE; 32503b705cfSriastradh else if (src == GEN7_BLENDFACTOR_INV_DST_ALPHA) 32603b705cfSriastradh src = GEN7_BLENDFACTOR_ZERO; 32703b705cfSriastradh } 32803b705cfSriastradh 32903b705cfSriastradh /* If the source alpha is being used, then we should only be in a 33003b705cfSriastradh * case where the source blend factor is 0, and the source blend 33103b705cfSriastradh * value is the mask channels multiplied by the source picture's alpha. 33203b705cfSriastradh */ 33303b705cfSriastradh if (has_component_alpha && gen7_blend_op[op].src_alpha) { 33403b705cfSriastradh if (dst == GEN7_BLENDFACTOR_SRC_ALPHA) 33503b705cfSriastradh dst = GEN7_BLENDFACTOR_SRC_COLOR; 33603b705cfSriastradh else if (dst == GEN7_BLENDFACTOR_INV_SRC_ALPHA) 33703b705cfSriastradh dst = GEN7_BLENDFACTOR_INV_SRC_COLOR; 33803b705cfSriastradh } 33903b705cfSriastradh 34003b705cfSriastradh DBG(("blend op=%d, dst=%x [A=%d] => src=%d, dst=%d => offset=%x\n", 34103b705cfSriastradh op, dst_format, PICT_FORMAT_A(dst_format), 34203b705cfSriastradh src, dst, (int)BLEND_OFFSET(src, dst))); 34303b705cfSriastradh return BLEND_OFFSET(src, dst); 34403b705cfSriastradh} 34503b705cfSriastradh 34603b705cfSriastradhstatic uint32_t gen7_get_card_format(PictFormat format) 34703b705cfSriastradh{ 34803b705cfSriastradh switch (format) { 34903b705cfSriastradh default: 35003b705cfSriastradh return -1; 35103b705cfSriastradh case PICT_a8r8g8b8: 35203b705cfSriastradh return GEN7_SURFACEFORMAT_B8G8R8A8_UNORM; 35303b705cfSriastradh case PICT_x8r8g8b8: 35403b705cfSriastradh return GEN7_SURFACEFORMAT_B8G8R8X8_UNORM; 35503b705cfSriastradh case PICT_a8b8g8r8: 35603b705cfSriastradh return GEN7_SURFACEFORMAT_R8G8B8A8_UNORM; 35703b705cfSriastradh case PICT_x8b8g8r8: 35803b705cfSriastradh return GEN7_SURFACEFORMAT_R8G8B8X8_UNORM; 35942542f5fSchristos#ifdef PICT_a2r10g10b10 36003b705cfSriastradh case PICT_a2r10g10b10: 36103b705cfSriastradh return GEN7_SURFACEFORMAT_B10G10R10A2_UNORM; 36203b705cfSriastradh case PICT_x2r10g10b10: 36303b705cfSriastradh return GEN7_SURFACEFORMAT_B10G10R10X2_UNORM; 36442542f5fSchristos#endif 36503b705cfSriastradh case PICT_r8g8b8: 36603b705cfSriastradh return GEN7_SURFACEFORMAT_R8G8B8_UNORM; 36703b705cfSriastradh case PICT_r5g6b5: 36803b705cfSriastradh return GEN7_SURFACEFORMAT_B5G6R5_UNORM; 36903b705cfSriastradh case PICT_a1r5g5b5: 37003b705cfSriastradh return GEN7_SURFACEFORMAT_B5G5R5A1_UNORM; 37103b705cfSriastradh case PICT_a8: 37203b705cfSriastradh return GEN7_SURFACEFORMAT_A8_UNORM; 37303b705cfSriastradh case PICT_a4r4g4b4: 37403b705cfSriastradh return GEN7_SURFACEFORMAT_B4G4R4A4_UNORM; 37503b705cfSriastradh } 37603b705cfSriastradh} 37703b705cfSriastradh 37803b705cfSriastradhstatic uint32_t gen7_get_dest_format(PictFormat format) 37903b705cfSriastradh{ 38003b705cfSriastradh switch (format) { 38103b705cfSriastradh default: 38203b705cfSriastradh return -1; 38303b705cfSriastradh case PICT_a8r8g8b8: 38403b705cfSriastradh case PICT_x8r8g8b8: 38503b705cfSriastradh return GEN7_SURFACEFORMAT_B8G8R8A8_UNORM; 38603b705cfSriastradh case PICT_a8b8g8r8: 38703b705cfSriastradh case PICT_x8b8g8r8: 38803b705cfSriastradh return GEN7_SURFACEFORMAT_R8G8B8A8_UNORM; 38942542f5fSchristos#ifdef PICT_a2r10g10b10 39003b705cfSriastradh case PICT_a2r10g10b10: 39103b705cfSriastradh case PICT_x2r10g10b10: 39203b705cfSriastradh return GEN7_SURFACEFORMAT_B10G10R10A2_UNORM; 39342542f5fSchristos#endif 39403b705cfSriastradh case PICT_r5g6b5: 39503b705cfSriastradh return GEN7_SURFACEFORMAT_B5G6R5_UNORM; 39603b705cfSriastradh case PICT_x1r5g5b5: 39703b705cfSriastradh case PICT_a1r5g5b5: 39803b705cfSriastradh return GEN7_SURFACEFORMAT_B5G5R5A1_UNORM; 39903b705cfSriastradh case PICT_a8: 40003b705cfSriastradh return GEN7_SURFACEFORMAT_A8_UNORM; 40103b705cfSriastradh case PICT_a4r4g4b4: 40203b705cfSriastradh case PICT_x4r4g4b4: 40303b705cfSriastradh return GEN7_SURFACEFORMAT_B4G4R4A4_UNORM; 40403b705cfSriastradh } 40503b705cfSriastradh} 40603b705cfSriastradh 40703b705cfSriastradhstatic bool gen7_check_dst_format(PictFormat format) 40803b705cfSriastradh{ 40903b705cfSriastradh if (gen7_get_dest_format(format) != -1) 41003b705cfSriastradh return true; 41103b705cfSriastradh 41203b705cfSriastradh DBG(("%s: unhandled format: %x\n", __FUNCTION__, (int)format)); 41303b705cfSriastradh return false; 41403b705cfSriastradh} 41503b705cfSriastradh 41603b705cfSriastradhstatic bool gen7_check_format(uint32_t format) 41703b705cfSriastradh{ 41803b705cfSriastradh if (gen7_get_card_format(format) != -1) 41903b705cfSriastradh return true; 42003b705cfSriastradh 42103b705cfSriastradh DBG(("%s: unhandled format: %x\n", __FUNCTION__, (int)format)); 42203b705cfSriastradh return false; 42303b705cfSriastradh} 42403b705cfSriastradh 42503b705cfSriastradhstatic uint32_t gen7_filter(uint32_t filter) 42603b705cfSriastradh{ 42703b705cfSriastradh switch (filter) { 42803b705cfSriastradh default: 42903b705cfSriastradh assert(0); 43003b705cfSriastradh case PictFilterNearest: 43103b705cfSriastradh return SAMPLER_FILTER_NEAREST; 43203b705cfSriastradh case PictFilterBilinear: 43303b705cfSriastradh return SAMPLER_FILTER_BILINEAR; 43403b705cfSriastradh } 43503b705cfSriastradh} 43603b705cfSriastradh 43703b705cfSriastradhstatic uint32_t gen7_check_filter(PicturePtr picture) 43803b705cfSriastradh{ 43903b705cfSriastradh switch (picture->filter) { 44003b705cfSriastradh case PictFilterNearest: 44103b705cfSriastradh case PictFilterBilinear: 44203b705cfSriastradh return true; 44303b705cfSriastradh default: 44403b705cfSriastradh return false; 44503b705cfSriastradh } 44603b705cfSriastradh} 44703b705cfSriastradh 44803b705cfSriastradhstatic uint32_t gen7_repeat(uint32_t repeat) 44903b705cfSriastradh{ 45003b705cfSriastradh switch (repeat) { 45103b705cfSriastradh default: 45203b705cfSriastradh assert(0); 45303b705cfSriastradh case RepeatNone: 45403b705cfSriastradh return SAMPLER_EXTEND_NONE; 45503b705cfSriastradh case RepeatNormal: 45603b705cfSriastradh return SAMPLER_EXTEND_REPEAT; 45703b705cfSriastradh case RepeatPad: 45803b705cfSriastradh return SAMPLER_EXTEND_PAD; 45903b705cfSriastradh case RepeatReflect: 46003b705cfSriastradh return SAMPLER_EXTEND_REFLECT; 46103b705cfSriastradh } 46203b705cfSriastradh} 46303b705cfSriastradh 46403b705cfSriastradhstatic bool gen7_check_repeat(PicturePtr picture) 46503b705cfSriastradh{ 46603b705cfSriastradh if (!picture->repeat) 46703b705cfSriastradh return true; 46803b705cfSriastradh 46903b705cfSriastradh switch (picture->repeatType) { 47003b705cfSriastradh case RepeatNone: 47103b705cfSriastradh case RepeatNormal: 47203b705cfSriastradh case RepeatPad: 47303b705cfSriastradh case RepeatReflect: 47403b705cfSriastradh return true; 47503b705cfSriastradh default: 47603b705cfSriastradh return false; 47703b705cfSriastradh } 47803b705cfSriastradh} 47903b705cfSriastradh 48003b705cfSriastradhstatic int 48103b705cfSriastradhgen7_choose_composite_kernel(int op, bool has_mask, bool is_ca, bool is_affine) 48203b705cfSriastradh{ 48303b705cfSriastradh int base; 48403b705cfSriastradh 48503b705cfSriastradh if (has_mask) { 48603b705cfSriastradh if (is_ca) { 48703b705cfSriastradh if (gen7_blend_op[op].src_alpha) 48803b705cfSriastradh base = GEN7_WM_KERNEL_MASKSA; 48903b705cfSriastradh else 49003b705cfSriastradh base = GEN7_WM_KERNEL_MASKCA; 49103b705cfSriastradh } else 49203b705cfSriastradh base = GEN7_WM_KERNEL_MASK; 49303b705cfSriastradh } else 49403b705cfSriastradh base = GEN7_WM_KERNEL_NOMASK; 49503b705cfSriastradh 49603b705cfSriastradh return base + !is_affine; 49703b705cfSriastradh} 49803b705cfSriastradh 49903b705cfSriastradhstatic void 50003b705cfSriastradhgen7_emit_urb(struct sna *sna) 50103b705cfSriastradh{ 50203b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_PS | (2 - 2)); 50303b705cfSriastradh OUT_BATCH(sna->render_state.gen7.info->urb.push_ps_size); 50403b705cfSriastradh 50503b705cfSriastradh /* num of VS entries must be divisible by 8 if size < 9 */ 50603b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_URB_VS | (2 - 2)); 50703b705cfSriastradh OUT_BATCH((sna->render_state.gen7.info->urb.max_vs_entries << GEN7_URB_ENTRY_NUMBER_SHIFT) | 50803b705cfSriastradh (2 - 1) << GEN7_URB_ENTRY_SIZE_SHIFT | 50903b705cfSriastradh (1 << GEN7_URB_STARTING_ADDRESS_SHIFT)); 51003b705cfSriastradh 51103b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_URB_HS | (2 - 2)); 51203b705cfSriastradh OUT_BATCH((0 << GEN7_URB_ENTRY_SIZE_SHIFT) | 51303b705cfSriastradh (2 << GEN7_URB_STARTING_ADDRESS_SHIFT)); 51403b705cfSriastradh 51503b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_URB_DS | (2 - 2)); 51603b705cfSriastradh OUT_BATCH((0 << GEN7_URB_ENTRY_SIZE_SHIFT) | 51703b705cfSriastradh (2 << GEN7_URB_STARTING_ADDRESS_SHIFT)); 51803b705cfSriastradh 51903b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_URB_GS | (2 - 2)); 52003b705cfSriastradh OUT_BATCH((0 << GEN7_URB_ENTRY_SIZE_SHIFT) | 52103b705cfSriastradh (1 << GEN7_URB_STARTING_ADDRESS_SHIFT)); 52203b705cfSriastradh} 52303b705cfSriastradh 52403b705cfSriastradhstatic void 52503b705cfSriastradhgen7_emit_state_base_address(struct sna *sna) 52603b705cfSriastradh{ 52742542f5fSchristos uint32_t mocs = sna->render_state.gen7.info->mocs << 8; 52803b705cfSriastradh 52903b705cfSriastradh OUT_BATCH(GEN7_STATE_BASE_ADDRESS | (10 - 2)); 53003b705cfSriastradh OUT_BATCH(0); /* general */ 53103b705cfSriastradh OUT_BATCH(kgem_add_reloc(&sna->kgem, /* surface */ 53203b705cfSriastradh sna->kgem.nbatch, 53303b705cfSriastradh NULL, 53403b705cfSriastradh I915_GEM_DOMAIN_INSTRUCTION << 16, 53503b705cfSriastradh BASE_ADDRESS_MODIFY)); 53603b705cfSriastradh OUT_BATCH(kgem_add_reloc(&sna->kgem, /* dynamic */ 53703b705cfSriastradh sna->kgem.nbatch, 53803b705cfSriastradh sna->render_state.gen7.general_bo, 53903b705cfSriastradh I915_GEM_DOMAIN_INSTRUCTION << 16, 54003b705cfSriastradh mocs | BASE_ADDRESS_MODIFY)); 54103b705cfSriastradh OUT_BATCH(0); /* indirect */ 54203b705cfSriastradh OUT_BATCH(kgem_add_reloc(&sna->kgem, /* instruction */ 54303b705cfSriastradh sna->kgem.nbatch, 54403b705cfSriastradh sna->render_state.gen7.general_bo, 54503b705cfSriastradh I915_GEM_DOMAIN_INSTRUCTION << 16, 54603b705cfSriastradh mocs | BASE_ADDRESS_MODIFY)); 54703b705cfSriastradh 54803b705cfSriastradh /* upper bounds, disable */ 54903b705cfSriastradh OUT_BATCH(0); 55003b705cfSriastradh OUT_BATCH(BASE_ADDRESS_MODIFY); 55103b705cfSriastradh OUT_BATCH(0); 55203b705cfSriastradh OUT_BATCH(BASE_ADDRESS_MODIFY); 55303b705cfSriastradh} 55403b705cfSriastradh 55503b705cfSriastradhstatic void 55603b705cfSriastradhgen7_disable_vs(struct sna *sna) 55703b705cfSriastradh{ 55803b705cfSriastradh /* For future reference: 55903b705cfSriastradh * A PIPE_CONTROL with post-sync op set to 1 and a depth stall needs 56003b705cfSriastradh * to be emitted just prior to change VS state, i.e. 3DSTATE_VS, 56103b705cfSriastradh * 3DSTATE_URB_VS, 3DSTATE_CONSTANT_VS, 56203b705cfSriastradh * 3DSTATE_BINDING_TABLE_POINTER_VS, 3DSTATE_SAMPLER_STATE_POINTER_VS. 56303b705cfSriastradh * 56403b705cfSriastradh * Here we saved by the full-flush incurred when emitting 56503b705cfSriastradh * the batchbuffer. 56603b705cfSriastradh */ 56703b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_VS | (6 - 2)); 56803b705cfSriastradh OUT_BATCH(0); /* no VS kernel */ 56903b705cfSriastradh OUT_BATCH(0); 57003b705cfSriastradh OUT_BATCH(0); 57103b705cfSriastradh OUT_BATCH(0); 57203b705cfSriastradh OUT_BATCH(0); /* pass-through */ 57303b705cfSriastradh 57403b705cfSriastradh#if 0 57503b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_CONSTANT_VS | (7 - 2)); 57603b705cfSriastradh OUT_BATCH(0); 57703b705cfSriastradh OUT_BATCH(0); 57803b705cfSriastradh OUT_BATCH(0); 57903b705cfSriastradh OUT_BATCH(0); 58003b705cfSriastradh OUT_BATCH(0); 58103b705cfSriastradh OUT_BATCH(0); 58203b705cfSriastradh 58303b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_BINDING_TABLE_POINTERS_VS | (2 - 2)); 58403b705cfSriastradh OUT_BATCH(0); 58503b705cfSriastradh 58603b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_SAMPLER_STATE_POINTERS_VS | (2 - 2)); 58703b705cfSriastradh OUT_BATCH(0); 58803b705cfSriastradh#endif 58903b705cfSriastradh} 59003b705cfSriastradh 59103b705cfSriastradhstatic void 59203b705cfSriastradhgen7_disable_hs(struct sna *sna) 59303b705cfSriastradh{ 59403b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_HS | (7 - 2)); 59503b705cfSriastradh OUT_BATCH(0); /* no HS kernel */ 59603b705cfSriastradh OUT_BATCH(0); 59703b705cfSriastradh OUT_BATCH(0); 59803b705cfSriastradh OUT_BATCH(0); 59903b705cfSriastradh OUT_BATCH(0); 60003b705cfSriastradh OUT_BATCH(0); /* pass-through */ 60103b705cfSriastradh 60203b705cfSriastradh#if 0 60303b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_CONSTANT_HS | (7 - 2)); 60403b705cfSriastradh OUT_BATCH(0); 60503b705cfSriastradh OUT_BATCH(0); 60603b705cfSriastradh OUT_BATCH(0); 60703b705cfSriastradh OUT_BATCH(0); 60803b705cfSriastradh OUT_BATCH(0); 60903b705cfSriastradh OUT_BATCH(0); 61003b705cfSriastradh 61103b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_BINDING_TABLE_POINTERS_HS | (2 - 2)); 61203b705cfSriastradh OUT_BATCH(0); 61303b705cfSriastradh 61403b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_SAMPLER_STATE_POINTERS_HS | (2 - 2)); 61503b705cfSriastradh OUT_BATCH(0); 61603b705cfSriastradh#endif 61703b705cfSriastradh} 61803b705cfSriastradh 61903b705cfSriastradhstatic void 62003b705cfSriastradhgen7_disable_te(struct sna *sna) 62103b705cfSriastradh{ 62203b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_TE | (4 - 2)); 62303b705cfSriastradh OUT_BATCH(0); 62403b705cfSriastradh OUT_BATCH(0); 62503b705cfSriastradh OUT_BATCH(0); 62603b705cfSriastradh} 62703b705cfSriastradh 62803b705cfSriastradhstatic void 62903b705cfSriastradhgen7_disable_ds(struct sna *sna) 63003b705cfSriastradh{ 63103b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_DS | (6 - 2)); 63203b705cfSriastradh OUT_BATCH(0); 63303b705cfSriastradh OUT_BATCH(0); 63403b705cfSriastradh OUT_BATCH(0); 63503b705cfSriastradh OUT_BATCH(0); 63603b705cfSriastradh OUT_BATCH(0); 63703b705cfSriastradh 63803b705cfSriastradh#if 0 63903b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_CONSTANT_DS | (7 - 2)); 64003b705cfSriastradh OUT_BATCH(0); 64103b705cfSriastradh OUT_BATCH(0); 64203b705cfSriastradh OUT_BATCH(0); 64303b705cfSriastradh OUT_BATCH(0); 64403b705cfSriastradh OUT_BATCH(0); 64503b705cfSriastradh OUT_BATCH(0); 64603b705cfSriastradh 64703b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_BINDING_TABLE_POINTERS_DS | (2 - 2)); 64803b705cfSriastradh OUT_BATCH(0); 64903b705cfSriastradh 65003b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_SAMPLER_STATE_POINTERS_DS | (2 - 2)); 65103b705cfSriastradh OUT_BATCH(0); 65203b705cfSriastradh#endif 65303b705cfSriastradh} 65403b705cfSriastradh 65503b705cfSriastradhstatic void 65603b705cfSriastradhgen7_disable_gs(struct sna *sna) 65703b705cfSriastradh{ 65803b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_GS | (7 - 2)); 65903b705cfSriastradh OUT_BATCH(0); /* no GS kernel */ 66003b705cfSriastradh OUT_BATCH(0); 66103b705cfSriastradh OUT_BATCH(0); 66203b705cfSriastradh OUT_BATCH(0); 66303b705cfSriastradh OUT_BATCH(0); 66403b705cfSriastradh OUT_BATCH(0); /* pass-through */ 66503b705cfSriastradh 66603b705cfSriastradh#if 0 66703b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_CONSTANT_GS | (7 - 2)); 66803b705cfSriastradh OUT_BATCH(0); 66903b705cfSriastradh OUT_BATCH(0); 67003b705cfSriastradh OUT_BATCH(0); 67103b705cfSriastradh OUT_BATCH(0); 67203b705cfSriastradh OUT_BATCH(0); 67303b705cfSriastradh OUT_BATCH(0); 67403b705cfSriastradh 67503b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_BINDING_TABLE_POINTERS_GS | (2 - 2)); 67603b705cfSriastradh OUT_BATCH(0); 67703b705cfSriastradh 67803b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_SAMPLER_STATE_POINTERS_GS | (2 - 2)); 67903b705cfSriastradh OUT_BATCH(0); 68003b705cfSriastradh#endif 68103b705cfSriastradh} 68203b705cfSriastradh 68303b705cfSriastradhstatic void 68403b705cfSriastradhgen7_disable_streamout(struct sna *sna) 68503b705cfSriastradh{ 68603b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_STREAMOUT | (3 - 2)); 68703b705cfSriastradh OUT_BATCH(0); 68803b705cfSriastradh OUT_BATCH(0); 68903b705cfSriastradh} 69003b705cfSriastradh 69103b705cfSriastradhstatic void 69203b705cfSriastradhgen7_emit_sf_invariant(struct sna *sna) 69303b705cfSriastradh{ 69403b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_SF | (7 - 2)); 69503b705cfSriastradh OUT_BATCH(0); 69603b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_SF_CULL_NONE); 69703b705cfSriastradh OUT_BATCH(2 << GEN7_3DSTATE_SF_TRIFAN_PROVOKE_SHIFT); 69803b705cfSriastradh OUT_BATCH(0); 69903b705cfSriastradh OUT_BATCH(0); 70003b705cfSriastradh OUT_BATCH(0); 70103b705cfSriastradh} 70203b705cfSriastradh 70303b705cfSriastradhstatic void 70403b705cfSriastradhgen7_emit_cc_invariant(struct sna *sna) 70503b705cfSriastradh{ 70603b705cfSriastradh#if 0 /* unused, no change */ 70703b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_CC_STATE_POINTERS | (2 - 2)); 70803b705cfSriastradh OUT_BATCH(0); 70903b705cfSriastradh 71003b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_DEPTH_STENCIL_STATE_POINTERS | (2 - 2)); 71103b705cfSriastradh OUT_BATCH(0); 71203b705cfSriastradh#endif 71303b705cfSriastradh 71403b705cfSriastradh /* XXX clear to be safe */ 71503b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_VIEWPORT_STATE_POINTERS_CC | (2 - 2)); 71603b705cfSriastradh OUT_BATCH(0); 71703b705cfSriastradh} 71803b705cfSriastradh 71903b705cfSriastradhstatic void 72003b705cfSriastradhgen7_disable_clip(struct sna *sna) 72103b705cfSriastradh{ 72203b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_CLIP | (4 - 2)); 72303b705cfSriastradh OUT_BATCH(0); 72403b705cfSriastradh OUT_BATCH(0); /* pass-through */ 72503b705cfSriastradh OUT_BATCH(0); 72603b705cfSriastradh 72703b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CL | (2 - 2)); 72803b705cfSriastradh OUT_BATCH(0); 72903b705cfSriastradh} 73003b705cfSriastradh 73103b705cfSriastradhstatic void 73203b705cfSriastradhgen7_emit_wm_invariant(struct sna *sna) 73303b705cfSriastradh{ 73403b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_WM | (3 - 2)); 73503b705cfSriastradh OUT_BATCH(GEN7_WM_DISPATCH_ENABLE | 73603b705cfSriastradh GEN7_WM_PERSPECTIVE_PIXEL_BARYCENTRIC); 73703b705cfSriastradh OUT_BATCH(0); 73803b705cfSriastradh 73903b705cfSriastradh#if 0 74003b705cfSriastradh /* XXX length bias of 7 in old spec? */ 74103b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_CONSTANT_PS | (7 - 2)); 74203b705cfSriastradh OUT_BATCH(0); 74303b705cfSriastradh OUT_BATCH(0); 74403b705cfSriastradh OUT_BATCH(0); 74503b705cfSriastradh OUT_BATCH(0); 74603b705cfSriastradh OUT_BATCH(0); 74703b705cfSriastradh OUT_BATCH(0); 74803b705cfSriastradh#endif 74903b705cfSriastradh} 75003b705cfSriastradh 75103b705cfSriastradhstatic void 75203b705cfSriastradhgen7_emit_null_depth_buffer(struct sna *sna) 75303b705cfSriastradh{ 75403b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_DEPTH_BUFFER | (7 - 2)); 75503b705cfSriastradh OUT_BATCH(GEN7_SURFACE_NULL << GEN7_3DSTATE_DEPTH_BUFFER_TYPE_SHIFT | 75603b705cfSriastradh GEN7_DEPTHFORMAT_D32_FLOAT << GEN7_3DSTATE_DEPTH_BUFFER_FORMAT_SHIFT); 75703b705cfSriastradh OUT_BATCH(0); /* disable depth, stencil and hiz */ 75803b705cfSriastradh OUT_BATCH(0); 75903b705cfSriastradh OUT_BATCH(0); 76003b705cfSriastradh OUT_BATCH(0); 76103b705cfSriastradh OUT_BATCH(0); 76203b705cfSriastradh 76303b705cfSriastradh#if 0 76403b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_CLEAR_PARAMS | (3 - 2)); 76503b705cfSriastradh OUT_BATCH(0); 76603b705cfSriastradh OUT_BATCH(0); 76703b705cfSriastradh#endif 76803b705cfSriastradh} 76903b705cfSriastradh 77003b705cfSriastradhstatic void 77103b705cfSriastradhgen7_emit_invariant(struct sna *sna) 77203b705cfSriastradh{ 77303b705cfSriastradh OUT_BATCH(GEN7_PIPELINE_SELECT | PIPELINE_SELECT_3D); 77403b705cfSriastradh 77503b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_MULTISAMPLE | (4 - 2)); 77603b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_MULTISAMPLE_PIXEL_LOCATION_CENTER | 77703b705cfSriastradh GEN7_3DSTATE_MULTISAMPLE_NUMSAMPLES_1); /* 1 sample/pixel */ 77803b705cfSriastradh OUT_BATCH(0); 77903b705cfSriastradh OUT_BATCH(0); 78003b705cfSriastradh 78103b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_SAMPLE_MASK | (2 - 2)); 78203b705cfSriastradh OUT_BATCH(1); 78303b705cfSriastradh 78403b705cfSriastradh gen7_emit_urb(sna); 78503b705cfSriastradh 78603b705cfSriastradh gen7_emit_state_base_address(sna); 78703b705cfSriastradh 78803b705cfSriastradh gen7_disable_vs(sna); 78903b705cfSriastradh gen7_disable_hs(sna); 79003b705cfSriastradh gen7_disable_te(sna); 79103b705cfSriastradh gen7_disable_ds(sna); 79203b705cfSriastradh gen7_disable_gs(sna); 79303b705cfSriastradh gen7_disable_clip(sna); 79403b705cfSriastradh gen7_emit_sf_invariant(sna); 79503b705cfSriastradh gen7_emit_wm_invariant(sna); 79603b705cfSriastradh gen7_emit_cc_invariant(sna); 79703b705cfSriastradh gen7_disable_streamout(sna); 79803b705cfSriastradh gen7_emit_null_depth_buffer(sna); 79903b705cfSriastradh 80003b705cfSriastradh sna->render_state.gen7.needs_invariant = false; 80103b705cfSriastradh} 80203b705cfSriastradh 80303b705cfSriastradhstatic void 80403b705cfSriastradhgen7_emit_cc(struct sna *sna, uint32_t blend_offset) 80503b705cfSriastradh{ 80603b705cfSriastradh struct gen7_render_state *render = &sna->render_state.gen7; 80703b705cfSriastradh 80803b705cfSriastradh if (render->blend == blend_offset) 80903b705cfSriastradh return; 81003b705cfSriastradh 81103b705cfSriastradh DBG(("%s: blend = %x\n", __FUNCTION__, blend_offset)); 81203b705cfSriastradh 81303b705cfSriastradh /* XXX can have upto 8 blend states preload, selectable via 81403b705cfSriastradh * Render Target Index. What other side-effects of Render Target Index? 81503b705cfSriastradh */ 81603b705cfSriastradh 81703b705cfSriastradh assert (is_aligned(render->cc_blend + blend_offset, 64)); 81803b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_BLEND_STATE_POINTERS | (2 - 2)); 81903b705cfSriastradh OUT_BATCH((render->cc_blend + blend_offset) | 1); 82003b705cfSriastradh 82103b705cfSriastradh render->blend = blend_offset; 82203b705cfSriastradh} 82303b705cfSriastradh 82403b705cfSriastradhstatic void 82503b705cfSriastradhgen7_emit_sampler(struct sna *sna, uint32_t state) 82603b705cfSriastradh{ 82703b705cfSriastradh if (sna->render_state.gen7.samplers == state) 82803b705cfSriastradh return; 82903b705cfSriastradh 83003b705cfSriastradh sna->render_state.gen7.samplers = state; 83103b705cfSriastradh 83203b705cfSriastradh DBG(("%s: sampler = %x\n", __FUNCTION__, state)); 83303b705cfSriastradh 83403b705cfSriastradh assert (is_aligned(sna->render_state.gen7.wm_state + state, 32)); 83503b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_SAMPLER_STATE_POINTERS_PS | (2 - 2)); 83603b705cfSriastradh OUT_BATCH(sna->render_state.gen7.wm_state + state); 83703b705cfSriastradh} 83803b705cfSriastradh 83903b705cfSriastradhstatic void 84003b705cfSriastradhgen7_emit_sf(struct sna *sna, bool has_mask) 84103b705cfSriastradh{ 84203b705cfSriastradh int num_sf_outputs = has_mask ? 2 : 1; 84303b705cfSriastradh 84403b705cfSriastradh if (sna->render_state.gen7.num_sf_outputs == num_sf_outputs) 84503b705cfSriastradh return; 84603b705cfSriastradh 84703b705cfSriastradh DBG(("%s: num_sf_outputs=%d, read_length=%d, read_offset=%d\n", 84803b705cfSriastradh __FUNCTION__, num_sf_outputs, 1, 0)); 84903b705cfSriastradh 85003b705cfSriastradh sna->render_state.gen7.num_sf_outputs = num_sf_outputs; 85103b705cfSriastradh 85203b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_SBE | (14 - 2)); 85303b705cfSriastradh OUT_BATCH(num_sf_outputs << GEN7_SBE_NUM_OUTPUTS_SHIFT | 85403b705cfSriastradh 1 << GEN7_SBE_URB_ENTRY_READ_LENGTH_SHIFT | 85503b705cfSriastradh 1 << GEN7_SBE_URB_ENTRY_READ_OFFSET_SHIFT); 85603b705cfSriastradh OUT_BATCH(0); 85703b705cfSriastradh OUT_BATCH(0); /* dw4 */ 85803b705cfSriastradh OUT_BATCH(0); 85903b705cfSriastradh OUT_BATCH(0); 86003b705cfSriastradh OUT_BATCH(0); 86103b705cfSriastradh OUT_BATCH(0); /* dw8 */ 86203b705cfSriastradh OUT_BATCH(0); 86303b705cfSriastradh OUT_BATCH(0); 86403b705cfSriastradh OUT_BATCH(0); 86503b705cfSriastradh OUT_BATCH(0); /* dw12 */ 86603b705cfSriastradh OUT_BATCH(0); 86703b705cfSriastradh OUT_BATCH(0); 86803b705cfSriastradh} 86903b705cfSriastradh 87003b705cfSriastradhstatic void 87103b705cfSriastradhgen7_emit_wm(struct sna *sna, int kernel) 87203b705cfSriastradh{ 87303b705cfSriastradh const uint32_t *kernels; 87403b705cfSriastradh 87503b705cfSriastradh if (sna->render_state.gen7.kernel == kernel) 87603b705cfSriastradh return; 87703b705cfSriastradh 87803b705cfSriastradh sna->render_state.gen7.kernel = kernel; 87903b705cfSriastradh kernels = sna->render_state.gen7.wm_kernel[kernel]; 88003b705cfSriastradh 88103b705cfSriastradh DBG(("%s: switching to %s, num_surfaces=%d (8-wide? %d, 16-wide? %d, 32-wide? %d)\n", 88203b705cfSriastradh __FUNCTION__, 88303b705cfSriastradh wm_kernels[kernel].name, 88403b705cfSriastradh wm_kernels[kernel].num_surfaces, 88503b705cfSriastradh kernels[0], kernels[1], kernels[2])); 88603b705cfSriastradh 88703b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_PS | (8 - 2)); 88803b705cfSriastradh OUT_BATCH(kernels[0] ?: kernels[1] ?: kernels[2]); 88903b705cfSriastradh OUT_BATCH(1 << GEN7_PS_SAMPLER_COUNT_SHIFT | 89003b705cfSriastradh wm_kernels[kernel].num_surfaces << GEN7_PS_BINDING_TABLE_ENTRY_COUNT_SHIFT); 89103b705cfSriastradh OUT_BATCH(0); /* scratch address */ 89203b705cfSriastradh OUT_BATCH(sna->render_state.gen7.info->max_wm_threads | 89303b705cfSriastradh (kernels[0] ? GEN7_PS_8_DISPATCH_ENABLE : 0) | 89403b705cfSriastradh (kernels[1] ? GEN7_PS_16_DISPATCH_ENABLE : 0) | 89503b705cfSriastradh (kernels[2] ? GEN7_PS_32_DISPATCH_ENABLE : 0) | 89603b705cfSriastradh GEN7_PS_ATTRIBUTE_ENABLE); 89703b705cfSriastradh OUT_BATCH((kernels[0] ? 4 : kernels[1] ? 6 : 8) << GEN7_PS_DISPATCH_START_GRF_SHIFT_0 | 89803b705cfSriastradh 8 << GEN7_PS_DISPATCH_START_GRF_SHIFT_1 | 89903b705cfSriastradh 6 << GEN7_PS_DISPATCH_START_GRF_SHIFT_2); 90003b705cfSriastradh OUT_BATCH(kernels[2]); 90103b705cfSriastradh OUT_BATCH(kernels[1]); 90203b705cfSriastradh} 90303b705cfSriastradh 90403b705cfSriastradhstatic bool 90503b705cfSriastradhgen7_emit_binding_table(struct sna *sna, uint16_t offset) 90603b705cfSriastradh{ 90703b705cfSriastradh if (sna->render_state.gen7.surface_table == offset) 90803b705cfSriastradh return false; 90903b705cfSriastradh 91003b705cfSriastradh /* Binding table pointers */ 91103b705cfSriastradh assert(is_aligned(4*offset, 32)); 91203b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_BINDING_TABLE_POINTERS_PS | (2 - 2)); 91303b705cfSriastradh OUT_BATCH(offset*4); 91403b705cfSriastradh 91503b705cfSriastradh sna->render_state.gen7.surface_table = offset; 91603b705cfSriastradh return true; 91703b705cfSriastradh} 91803b705cfSriastradh 91903b705cfSriastradhstatic bool 92003b705cfSriastradhgen7_emit_drawing_rectangle(struct sna *sna, 92103b705cfSriastradh const struct sna_composite_op *op) 92203b705cfSriastradh{ 92303b705cfSriastradh uint32_t limit = (op->dst.height - 1) << 16 | (op->dst.width - 1); 92403b705cfSriastradh uint32_t offset = (uint16_t)op->dst.y << 16 | (uint16_t)op->dst.x; 92503b705cfSriastradh 92603b705cfSriastradh assert(!too_large(op->dst.x, op->dst.y)); 92703b705cfSriastradh assert(!too_large(op->dst.width, op->dst.height)); 92803b705cfSriastradh 92903b705cfSriastradh if (sna->render_state.gen7.drawrect_limit == limit && 93003b705cfSriastradh sna->render_state.gen7.drawrect_offset == offset) 93103b705cfSriastradh return true; 93203b705cfSriastradh 93303b705cfSriastradh sna->render_state.gen7.drawrect_offset = offset; 93403b705cfSriastradh sna->render_state.gen7.drawrect_limit = limit; 93503b705cfSriastradh 93603b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_DRAWING_RECTANGLE | (4 - 2)); 93703b705cfSriastradh OUT_BATCH(0); 93803b705cfSriastradh OUT_BATCH(limit); 93903b705cfSriastradh OUT_BATCH(offset); 94003b705cfSriastradh return false; 94103b705cfSriastradh} 94203b705cfSriastradh 94303b705cfSriastradhstatic void 94403b705cfSriastradhgen7_emit_vertex_elements(struct sna *sna, 94503b705cfSriastradh const struct sna_composite_op *op) 94603b705cfSriastradh{ 94703b705cfSriastradh /* 94803b705cfSriastradh * vertex data in vertex buffer 94903b705cfSriastradh * position: (x, y) 95003b705cfSriastradh * texture coordinate 0: (u0, v0) if (is_affine is true) else (u0, v0, w0) 95103b705cfSriastradh * texture coordinate 1 if (has_mask is true): same as above 95203b705cfSriastradh */ 95303b705cfSriastradh struct gen7_render_state *render = &sna->render_state.gen7; 95403b705cfSriastradh uint32_t src_format, dw; 95503b705cfSriastradh int id = GEN7_VERTEX(op->u.gen7.flags); 95603b705cfSriastradh bool has_mask; 95703b705cfSriastradh 95803b705cfSriastradh DBG(("%s: setup id=%d\n", __FUNCTION__, id)); 95903b705cfSriastradh 96003b705cfSriastradh if (render->ve_id == id) 96103b705cfSriastradh return; 96203b705cfSriastradh render->ve_id = id; 96303b705cfSriastradh 96403b705cfSriastradh /* The VUE layout 96503b705cfSriastradh * dword 0-3: pad (0.0, 0.0, 0.0. 0.0) 96603b705cfSriastradh * dword 4-7: position (x, y, 1.0, 1.0), 96703b705cfSriastradh * dword 8-11: texture coordinate 0 (u0, v0, w0, 1.0) 96803b705cfSriastradh * dword 12-15: texture coordinate 1 (u1, v1, w1, 1.0) 96903b705cfSriastradh * 97003b705cfSriastradh * dword 4-15 are fetched from vertex buffer 97103b705cfSriastradh */ 97203b705cfSriastradh has_mask = (id >> 2) != 0; 97303b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_VERTEX_ELEMENTS | 97403b705cfSriastradh ((2 * (3 + has_mask)) + 1 - 2)); 97503b705cfSriastradh 97603b705cfSriastradh OUT_BATCH(id << GEN7_VE0_VERTEX_BUFFER_INDEX_SHIFT | GEN7_VE0_VALID | 97703b705cfSriastradh GEN7_SURFACEFORMAT_R32G32B32A32_FLOAT << GEN7_VE0_FORMAT_SHIFT | 97803b705cfSriastradh 0 << GEN7_VE0_OFFSET_SHIFT); 97903b705cfSriastradh OUT_BATCH(GEN7_VFCOMPONENT_STORE_0 << GEN7_VE1_VFCOMPONENT_0_SHIFT | 98003b705cfSriastradh GEN7_VFCOMPONENT_STORE_0 << GEN7_VE1_VFCOMPONENT_1_SHIFT | 98103b705cfSriastradh GEN7_VFCOMPONENT_STORE_0 << GEN7_VE1_VFCOMPONENT_2_SHIFT | 98203b705cfSriastradh GEN7_VFCOMPONENT_STORE_0 << GEN7_VE1_VFCOMPONENT_3_SHIFT); 98303b705cfSriastradh 98403b705cfSriastradh /* x,y */ 98503b705cfSriastradh OUT_BATCH(id << GEN7_VE0_VERTEX_BUFFER_INDEX_SHIFT | GEN7_VE0_VALID | 98603b705cfSriastradh GEN7_SURFACEFORMAT_R16G16_SSCALED << GEN7_VE0_FORMAT_SHIFT | 98703b705cfSriastradh 0 << GEN7_VE0_OFFSET_SHIFT); 98803b705cfSriastradh OUT_BATCH(GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_0_SHIFT | 98903b705cfSriastradh GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_1_SHIFT | 99003b705cfSriastradh GEN7_VFCOMPONENT_STORE_0 << GEN7_VE1_VFCOMPONENT_2_SHIFT | 99103b705cfSriastradh GEN7_VFCOMPONENT_STORE_1_FLT << GEN7_VE1_VFCOMPONENT_3_SHIFT); 99203b705cfSriastradh 99303b705cfSriastradh /* u0, v0, w0 */ 99403b705cfSriastradh DBG(("%s: first channel %d floats, offset=4b\n", __FUNCTION__, id & 3)); 99503b705cfSriastradh dw = GEN7_VFCOMPONENT_STORE_1_FLT << GEN7_VE1_VFCOMPONENT_3_SHIFT; 99603b705cfSriastradh switch (id & 3) { 99703b705cfSriastradh default: 99803b705cfSriastradh assert(0); 99903b705cfSriastradh case 0: 100003b705cfSriastradh src_format = GEN7_SURFACEFORMAT_R16G16_SSCALED; 100103b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_0_SHIFT; 100203b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_1_SHIFT; 100303b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_0 << GEN7_VE1_VFCOMPONENT_2_SHIFT; 100403b705cfSriastradh break; 100503b705cfSriastradh case 1: 100603b705cfSriastradh src_format = GEN7_SURFACEFORMAT_R32_FLOAT; 100703b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_0_SHIFT; 100803b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_0 << GEN7_VE1_VFCOMPONENT_1_SHIFT; 100903b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_0 << GEN7_VE1_VFCOMPONENT_2_SHIFT; 101003b705cfSriastradh break; 101103b705cfSriastradh case 2: 101203b705cfSriastradh src_format = GEN7_SURFACEFORMAT_R32G32_FLOAT; 101303b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_0_SHIFT; 101403b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_1_SHIFT; 101503b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_0 << GEN7_VE1_VFCOMPONENT_2_SHIFT; 101603b705cfSriastradh break; 101703b705cfSriastradh case 3: 101803b705cfSriastradh src_format = GEN7_SURFACEFORMAT_R32G32B32_FLOAT; 101903b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_0_SHIFT; 102003b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_1_SHIFT; 102103b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_2_SHIFT; 102203b705cfSriastradh break; 102303b705cfSriastradh } 102403b705cfSriastradh OUT_BATCH(id << GEN7_VE0_VERTEX_BUFFER_INDEX_SHIFT | GEN7_VE0_VALID | 102503b705cfSriastradh src_format << GEN7_VE0_FORMAT_SHIFT | 102603b705cfSriastradh 4 << GEN7_VE0_OFFSET_SHIFT); 102703b705cfSriastradh OUT_BATCH(dw); 102803b705cfSriastradh 102903b705cfSriastradh /* u1, v1, w1 */ 103003b705cfSriastradh if (has_mask) { 103103b705cfSriastradh unsigned offset = 4 + ((id & 3) ?: 1) * sizeof(float); 103203b705cfSriastradh DBG(("%s: second channel %d floats, offset=%db\n", __FUNCTION__, id >> 2, offset)); 103303b705cfSriastradh dw = GEN7_VFCOMPONENT_STORE_1_FLT << GEN7_VE1_VFCOMPONENT_3_SHIFT; 103403b705cfSriastradh switch (id >> 2) { 103503b705cfSriastradh case 1: 103603b705cfSriastradh src_format = GEN7_SURFACEFORMAT_R32_FLOAT; 103703b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_0_SHIFT; 103803b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_0 << GEN7_VE1_VFCOMPONENT_1_SHIFT; 103903b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_0 << GEN7_VE1_VFCOMPONENT_2_SHIFT; 104003b705cfSriastradh break; 104103b705cfSriastradh default: 104203b705cfSriastradh assert(0); 104303b705cfSriastradh case 2: 104403b705cfSriastradh src_format = GEN7_SURFACEFORMAT_R32G32_FLOAT; 104503b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_0_SHIFT; 104603b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_1_SHIFT; 104703b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_0 << GEN7_VE1_VFCOMPONENT_2_SHIFT; 104803b705cfSriastradh break; 104903b705cfSriastradh case 3: 105003b705cfSriastradh src_format = GEN7_SURFACEFORMAT_R32G32B32_FLOAT; 105103b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_0_SHIFT; 105203b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_1_SHIFT; 105303b705cfSriastradh dw |= GEN7_VFCOMPONENT_STORE_SRC << GEN7_VE1_VFCOMPONENT_2_SHIFT; 105403b705cfSriastradh break; 105503b705cfSriastradh } 105603b705cfSriastradh OUT_BATCH(id << GEN7_VE0_VERTEX_BUFFER_INDEX_SHIFT | GEN7_VE0_VALID | 105703b705cfSriastradh src_format << GEN7_VE0_FORMAT_SHIFT | 105803b705cfSriastradh offset << GEN7_VE0_OFFSET_SHIFT); 105903b705cfSriastradh OUT_BATCH(dw); 106003b705cfSriastradh } 106103b705cfSriastradh} 106203b705cfSriastradh 106303b705cfSriastradhinline static void 106403b705cfSriastradhgen7_emit_pipe_invalidate(struct sna *sna) 106503b705cfSriastradh{ 106603b705cfSriastradh OUT_BATCH(GEN7_PIPE_CONTROL | (4 - 2)); 106703b705cfSriastradh OUT_BATCH(GEN7_PIPE_CONTROL_WC_FLUSH | 106803b705cfSriastradh GEN7_PIPE_CONTROL_TC_FLUSH | 106903b705cfSriastradh GEN7_PIPE_CONTROL_CS_STALL); 107003b705cfSriastradh OUT_BATCH(0); 107103b705cfSriastradh OUT_BATCH(0); 107203b705cfSriastradh} 107303b705cfSriastradh 107403b705cfSriastradhinline static void 107542542f5fSchristosgen7_emit_pipe_flush(struct sna *sna, bool need_stall) 107603b705cfSriastradh{ 107742542f5fSchristos unsigned stall; 107842542f5fSchristos 107942542f5fSchristos stall = 0; 108042542f5fSchristos if (need_stall) 108142542f5fSchristos stall = (GEN7_PIPE_CONTROL_CS_STALL | 108242542f5fSchristos GEN7_PIPE_CONTROL_STALL_AT_SCOREBOARD); 108342542f5fSchristos 108403b705cfSriastradh OUT_BATCH(GEN7_PIPE_CONTROL | (4 - 2)); 108542542f5fSchristos OUT_BATCH(GEN7_PIPE_CONTROL_WC_FLUSH | stall); 108603b705cfSriastradh OUT_BATCH(0); 108703b705cfSriastradh OUT_BATCH(0); 108803b705cfSriastradh} 108903b705cfSriastradh 109003b705cfSriastradhinline static void 109103b705cfSriastradhgen7_emit_pipe_stall(struct sna *sna) 109203b705cfSriastradh{ 109303b705cfSriastradh OUT_BATCH(GEN7_PIPE_CONTROL | (4 - 2)); 109403b705cfSriastradh OUT_BATCH(GEN7_PIPE_CONTROL_CS_STALL | 109503b705cfSriastradh GEN7_PIPE_CONTROL_STALL_AT_SCOREBOARD); 109603b705cfSriastradh OUT_BATCH(0); 109703b705cfSriastradh OUT_BATCH(0); 109803b705cfSriastradh} 109903b705cfSriastradh 110003b705cfSriastradhstatic void 110103b705cfSriastradhgen7_emit_state(struct sna *sna, 110203b705cfSriastradh const struct sna_composite_op *op, 110303b705cfSriastradh uint16_t wm_binding_table) 110403b705cfSriastradh{ 110542542f5fSchristos bool need_invalidate; 110642542f5fSchristos bool need_flush; 110703b705cfSriastradh bool need_stall; 110803b705cfSriastradh 110903b705cfSriastradh assert(op->dst.bo->exec); 111003b705cfSriastradh 111142542f5fSchristos need_flush = wm_binding_table & 1 || 111242542f5fSchristos (sna->render_state.gen7.emit_flush && GEN7_READS_DST(op->u.gen7.flags)); 111342542f5fSchristos if (ALWAYS_FLUSH) 111442542f5fSchristos need_flush = true; 111503b705cfSriastradh 111642542f5fSchristos wm_binding_table &= ~1; 111742542f5fSchristos 111842542f5fSchristos need_stall = sna->render_state.gen7.surface_table != wm_binding_table; 111942542f5fSchristos 112042542f5fSchristos need_invalidate = kgem_bo_is_dirty(op->src.bo) || kgem_bo_is_dirty(op->mask.bo); 112142542f5fSchristos if (ALWAYS_INVALIDATE) 112242542f5fSchristos need_invalidate = true; 112303b705cfSriastradh 112403b705cfSriastradh need_stall &= gen7_emit_drawing_rectangle(sna, op); 112542542f5fSchristos if (ALWAYS_STALL) 112642542f5fSchristos need_stall = true; 112703b705cfSriastradh 112842542f5fSchristos if (need_invalidate) { 112903b705cfSriastradh gen7_emit_pipe_invalidate(sna); 113003b705cfSriastradh kgem_clear_dirty(&sna->kgem); 113103b705cfSriastradh assert(op->dst.bo->exec); 113203b705cfSriastradh kgem_bo_mark_dirty(op->dst.bo); 113342542f5fSchristos 113442542f5fSchristos need_flush = false; 113542542f5fSchristos need_stall = false; 113642542f5fSchristos } 113742542f5fSchristos if (need_flush) { 113842542f5fSchristos gen7_emit_pipe_flush(sna, need_stall); 113903b705cfSriastradh need_stall = false; 114003b705cfSriastradh } 114103b705cfSriastradh if (need_stall) 114203b705cfSriastradh gen7_emit_pipe_stall(sna); 114303b705cfSriastradh 114442542f5fSchristos gen7_emit_cc(sna, GEN7_BLEND(op->u.gen7.flags)); 114542542f5fSchristos gen7_emit_sampler(sna, GEN7_SAMPLER(op->u.gen7.flags)); 114642542f5fSchristos gen7_emit_sf(sna, GEN7_VERTEX(op->u.gen7.flags) >> 2); 114742542f5fSchristos gen7_emit_wm(sna, GEN7_KERNEL(op->u.gen7.flags)); 114842542f5fSchristos gen7_emit_vertex_elements(sna, op); 114942542f5fSchristos gen7_emit_binding_table(sna, wm_binding_table); 115042542f5fSchristos 115103b705cfSriastradh sna->render_state.gen7.emit_flush = GEN7_READS_DST(op->u.gen7.flags); 115203b705cfSriastradh} 115303b705cfSriastradh 115403b705cfSriastradhstatic bool gen7_magic_ca_pass(struct sna *sna, 115503b705cfSriastradh const struct sna_composite_op *op) 115603b705cfSriastradh{ 115703b705cfSriastradh struct gen7_render_state *state = &sna->render_state.gen7; 115803b705cfSriastradh 115903b705cfSriastradh if (!op->need_magic_ca_pass) 116003b705cfSriastradh return false; 116103b705cfSriastradh 116203b705cfSriastradh DBG(("%s: CA fixup (%d -> %d)\n", __FUNCTION__, 116303b705cfSriastradh sna->render.vertex_start, sna->render.vertex_index)); 116403b705cfSriastradh 116503b705cfSriastradh gen7_emit_pipe_stall(sna); 116603b705cfSriastradh 116703b705cfSriastradh gen7_emit_cc(sna, 116803b705cfSriastradh GEN7_BLEND(gen7_get_blend(PictOpAdd, true, 116903b705cfSriastradh op->dst.format))); 117003b705cfSriastradh gen7_emit_wm(sna, 117103b705cfSriastradh gen7_choose_composite_kernel(PictOpAdd, 117203b705cfSriastradh true, true, 117303b705cfSriastradh op->is_affine)); 117403b705cfSriastradh 117503b705cfSriastradh OUT_BATCH(GEN7_3DPRIMITIVE | (7- 2)); 117603b705cfSriastradh OUT_BATCH(GEN7_3DPRIMITIVE_VERTEX_SEQUENTIAL | _3DPRIM_RECTLIST); 117703b705cfSriastradh OUT_BATCH(sna->render.vertex_index - sna->render.vertex_start); 117803b705cfSriastradh OUT_BATCH(sna->render.vertex_start); 117903b705cfSriastradh OUT_BATCH(1); /* single instance */ 118003b705cfSriastradh OUT_BATCH(0); /* start instance location */ 118103b705cfSriastradh OUT_BATCH(0); /* index buffer offset, ignored */ 118203b705cfSriastradh 118303b705cfSriastradh state->last_primitive = sna->kgem.nbatch; 118403b705cfSriastradh return true; 118503b705cfSriastradh} 118603b705cfSriastradh 118703b705cfSriastradhstatic void null_create(struct sna_static_stream *stream) 118803b705cfSriastradh{ 118903b705cfSriastradh /* A bunch of zeros useful for legacy border color and depth-stencil */ 119003b705cfSriastradh sna_static_stream_map(stream, 64, 64); 119103b705cfSriastradh} 119203b705cfSriastradh 119303b705cfSriastradhstatic void 119403b705cfSriastradhsampler_state_init(struct gen7_sampler_state *sampler_state, 119503b705cfSriastradh sampler_filter_t filter, 119603b705cfSriastradh sampler_extend_t extend) 119703b705cfSriastradh{ 119803b705cfSriastradh sampler_state->ss0.lod_preclamp = 1; /* GL mode */ 119903b705cfSriastradh 120003b705cfSriastradh /* We use the legacy mode to get the semantics specified by 120103b705cfSriastradh * the Render extension. */ 120203b705cfSriastradh sampler_state->ss0.default_color_mode = GEN7_BORDER_COLOR_MODE_LEGACY; 120303b705cfSriastradh 120403b705cfSriastradh switch (filter) { 120503b705cfSriastradh default: 120603b705cfSriastradh case SAMPLER_FILTER_NEAREST: 120703b705cfSriastradh sampler_state->ss0.min_filter = GEN7_MAPFILTER_NEAREST; 120803b705cfSriastradh sampler_state->ss0.mag_filter = GEN7_MAPFILTER_NEAREST; 120903b705cfSriastradh break; 121003b705cfSriastradh case SAMPLER_FILTER_BILINEAR: 121103b705cfSriastradh sampler_state->ss0.min_filter = GEN7_MAPFILTER_LINEAR; 121203b705cfSriastradh sampler_state->ss0.mag_filter = GEN7_MAPFILTER_LINEAR; 121303b705cfSriastradh break; 121403b705cfSriastradh } 121503b705cfSriastradh 121603b705cfSriastradh switch (extend) { 121703b705cfSriastradh default: 121803b705cfSriastradh case SAMPLER_EXTEND_NONE: 121903b705cfSriastradh sampler_state->ss3.r_wrap_mode = GEN7_TEXCOORDMODE_CLAMP_BORDER; 122003b705cfSriastradh sampler_state->ss3.s_wrap_mode = GEN7_TEXCOORDMODE_CLAMP_BORDER; 122103b705cfSriastradh sampler_state->ss3.t_wrap_mode = GEN7_TEXCOORDMODE_CLAMP_BORDER; 122203b705cfSriastradh break; 122303b705cfSriastradh case SAMPLER_EXTEND_REPEAT: 122403b705cfSriastradh sampler_state->ss3.r_wrap_mode = GEN7_TEXCOORDMODE_WRAP; 122503b705cfSriastradh sampler_state->ss3.s_wrap_mode = GEN7_TEXCOORDMODE_WRAP; 122603b705cfSriastradh sampler_state->ss3.t_wrap_mode = GEN7_TEXCOORDMODE_WRAP; 122703b705cfSriastradh break; 122803b705cfSriastradh case SAMPLER_EXTEND_PAD: 122903b705cfSriastradh sampler_state->ss3.r_wrap_mode = GEN7_TEXCOORDMODE_CLAMP; 123003b705cfSriastradh sampler_state->ss3.s_wrap_mode = GEN7_TEXCOORDMODE_CLAMP; 123103b705cfSriastradh sampler_state->ss3.t_wrap_mode = GEN7_TEXCOORDMODE_CLAMP; 123203b705cfSriastradh break; 123303b705cfSriastradh case SAMPLER_EXTEND_REFLECT: 123403b705cfSriastradh sampler_state->ss3.r_wrap_mode = GEN7_TEXCOORDMODE_MIRROR; 123503b705cfSriastradh sampler_state->ss3.s_wrap_mode = GEN7_TEXCOORDMODE_MIRROR; 123603b705cfSriastradh sampler_state->ss3.t_wrap_mode = GEN7_TEXCOORDMODE_MIRROR; 123703b705cfSriastradh break; 123803b705cfSriastradh } 123903b705cfSriastradh} 124003b705cfSriastradh 124103b705cfSriastradhstatic void 124203b705cfSriastradhsampler_copy_init(struct gen7_sampler_state *ss) 124303b705cfSriastradh{ 124403b705cfSriastradh sampler_state_init(ss, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE); 124503b705cfSriastradh ss->ss3.non_normalized_coord = 1; 124603b705cfSriastradh 124703b705cfSriastradh sampler_state_init(ss+1, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE); 124803b705cfSriastradh} 124903b705cfSriastradh 125003b705cfSriastradhstatic void 125103b705cfSriastradhsampler_fill_init(struct gen7_sampler_state *ss) 125203b705cfSriastradh{ 125303b705cfSriastradh sampler_state_init(ss, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_REPEAT); 125403b705cfSriastradh ss->ss3.non_normalized_coord = 1; 125503b705cfSriastradh 125603b705cfSriastradh sampler_state_init(ss+1, SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE); 125703b705cfSriastradh} 125803b705cfSriastradh 125903b705cfSriastradhstatic uint32_t 126003b705cfSriastradhgen7_tiling_bits(uint32_t tiling) 126103b705cfSriastradh{ 126203b705cfSriastradh switch (tiling) { 126303b705cfSriastradh default: assert(0); 126403b705cfSriastradh case I915_TILING_NONE: return 0; 126503b705cfSriastradh case I915_TILING_X: return GEN7_SURFACE_TILED; 126603b705cfSriastradh case I915_TILING_Y: return GEN7_SURFACE_TILED | GEN7_SURFACE_TILED_Y; 126703b705cfSriastradh } 126803b705cfSriastradh} 126903b705cfSriastradh 127003b705cfSriastradh/** 127103b705cfSriastradh * Sets up the common fields for a surface state buffer for the given 127203b705cfSriastradh * picture in the given surface state buffer. 127303b705cfSriastradh */ 127403b705cfSriastradhstatic uint32_t 127503b705cfSriastradhgen7_bind_bo(struct sna *sna, 127603b705cfSriastradh struct kgem_bo *bo, 127703b705cfSriastradh uint32_t width, 127803b705cfSriastradh uint32_t height, 127903b705cfSriastradh uint32_t format, 128003b705cfSriastradh bool is_dst) 128103b705cfSriastradh{ 128203b705cfSriastradh uint32_t *ss; 128303b705cfSriastradh uint32_t domains; 128403b705cfSriastradh int offset; 128503b705cfSriastradh uint32_t is_scanout = is_dst && bo->scanout; 128603b705cfSriastradh 128703b705cfSriastradh COMPILE_TIME_ASSERT(sizeof(struct gen7_surface_state) == 32); 128803b705cfSriastradh 128903b705cfSriastradh /* After the first bind, we manage the cache domains within the batch */ 129003b705cfSriastradh offset = kgem_bo_get_binding(bo, format | is_dst << 30 | is_scanout << 31); 129103b705cfSriastradh if (offset) { 129242542f5fSchristos assert(offset >= sna->kgem.surface); 129303b705cfSriastradh if (is_dst) 129403b705cfSriastradh kgem_bo_mark_dirty(bo); 129503b705cfSriastradh return offset * sizeof(uint32_t); 129603b705cfSriastradh } 129703b705cfSriastradh 129803b705cfSriastradh offset = sna->kgem.surface -= 129903b705cfSriastradh sizeof(struct gen7_surface_state) / sizeof(uint32_t); 130003b705cfSriastradh ss = sna->kgem.batch + offset; 130103b705cfSriastradh ss[0] = (GEN7_SURFACE_2D << GEN7_SURFACE_TYPE_SHIFT | 130203b705cfSriastradh gen7_tiling_bits(bo->tiling) | 130303b705cfSriastradh format << GEN7_SURFACE_FORMAT_SHIFT); 130403b705cfSriastradh if (bo->tiling == I915_TILING_Y) 130503b705cfSriastradh ss[0] |= GEN7_SURFACE_VALIGN_4; 130603b705cfSriastradh if (is_dst) { 130703b705cfSriastradh ss[0] |= GEN7_SURFACE_RC_READ_WRITE; 130803b705cfSriastradh domains = I915_GEM_DOMAIN_RENDER << 16 |I915_GEM_DOMAIN_RENDER; 130903b705cfSriastradh } else 131003b705cfSriastradh domains = I915_GEM_DOMAIN_SAMPLER << 16; 131103b705cfSriastradh ss[1] = kgem_add_reloc(&sna->kgem, offset + 1, bo, domains, 0); 131203b705cfSriastradh ss[2] = ((width - 1) << GEN7_SURFACE_WIDTH_SHIFT | 131303b705cfSriastradh (height - 1) << GEN7_SURFACE_HEIGHT_SHIFT); 131403b705cfSriastradh ss[3] = (bo->pitch - 1) << GEN7_SURFACE_PITCH_SHIFT; 131503b705cfSriastradh ss[4] = 0; 131642542f5fSchristos ss[5] = (is_scanout || bo->io) ? 0 : sna->render_state.gen7.info->mocs << 16; 131703b705cfSriastradh ss[6] = 0; 131803b705cfSriastradh ss[7] = 0; 131903b705cfSriastradh if (is_hsw(sna)) 132003b705cfSriastradh ss[7] |= HSW_SURFACE_SWIZZLE(RED, GREEN, BLUE, ALPHA); 132103b705cfSriastradh 132203b705cfSriastradh kgem_bo_set_binding(bo, format | is_dst << 30 | is_scanout << 31, offset); 132303b705cfSriastradh 132403b705cfSriastradh DBG(("[%x] bind bo(handle=%d, addr=%d), format=%d, width=%d, height=%d, pitch=%d, tiling=%d -> %s\n", 132503b705cfSriastradh offset, bo->handle, ss[1], 132603b705cfSriastradh format, width, height, bo->pitch, bo->tiling, 132703b705cfSriastradh domains & 0xffff ? "render" : "sampler")); 132803b705cfSriastradh 132903b705cfSriastradh return offset * sizeof(uint32_t); 133003b705cfSriastradh} 133103b705cfSriastradh 133203b705cfSriastradhstatic void gen7_emit_vertex_buffer(struct sna *sna, 133303b705cfSriastradh const struct sna_composite_op *op) 133403b705cfSriastradh{ 133503b705cfSriastradh int id = GEN7_VERTEX(op->u.gen7.flags); 133603b705cfSriastradh 133703b705cfSriastradh OUT_BATCH(GEN7_3DSTATE_VERTEX_BUFFERS | (5 - 2)); 133803b705cfSriastradh OUT_BATCH(id << GEN7_VB0_BUFFER_INDEX_SHIFT | 133903b705cfSriastradh GEN7_VB0_VERTEXDATA | 134003b705cfSriastradh GEN7_VB0_ADDRESS_MODIFY_ENABLE | 134103b705cfSriastradh 4*op->floats_per_vertex << GEN7_VB0_BUFFER_PITCH_SHIFT); 134203b705cfSriastradh sna->render.vertex_reloc[sna->render.nvertex_reloc++] = sna->kgem.nbatch; 134303b705cfSriastradh OUT_BATCH(0); 134403b705cfSriastradh OUT_BATCH(~0); /* max address: disabled */ 134503b705cfSriastradh OUT_BATCH(0); 134603b705cfSriastradh 134703b705cfSriastradh sna->render.vb_id |= 1 << id; 134803b705cfSriastradh} 134903b705cfSriastradh 135003b705cfSriastradhstatic void gen7_emit_primitive(struct sna *sna) 135103b705cfSriastradh{ 135203b705cfSriastradh if (sna->kgem.nbatch == sna->render_state.gen7.last_primitive) { 135303b705cfSriastradh sna->render.vertex_offset = sna->kgem.nbatch - 5; 135403b705cfSriastradh return; 135503b705cfSriastradh } 135603b705cfSriastradh 135703b705cfSriastradh OUT_BATCH(GEN7_3DPRIMITIVE | (7- 2)); 135803b705cfSriastradh OUT_BATCH(GEN7_3DPRIMITIVE_VERTEX_SEQUENTIAL | _3DPRIM_RECTLIST); 135903b705cfSriastradh sna->render.vertex_offset = sna->kgem.nbatch; 136003b705cfSriastradh OUT_BATCH(0); /* vertex count, to be filled in later */ 136103b705cfSriastradh OUT_BATCH(sna->render.vertex_index); 136203b705cfSriastradh OUT_BATCH(1); /* single instance */ 136303b705cfSriastradh OUT_BATCH(0); /* start instance location */ 136403b705cfSriastradh OUT_BATCH(0); /* index buffer offset, ignored */ 136503b705cfSriastradh sna->render.vertex_start = sna->render.vertex_index; 136603b705cfSriastradh 136703b705cfSriastradh sna->render_state.gen7.last_primitive = sna->kgem.nbatch; 136803b705cfSriastradh} 136903b705cfSriastradh 137003b705cfSriastradhstatic bool gen7_rectangle_begin(struct sna *sna, 137103b705cfSriastradh const struct sna_composite_op *op) 137203b705cfSriastradh{ 137303b705cfSriastradh int id = 1 << GEN7_VERTEX(op->u.gen7.flags); 137403b705cfSriastradh int ndwords; 137503b705cfSriastradh 137603b705cfSriastradh if (sna_vertex_wait__locked(&sna->render) && sna->render.vertex_offset) 137703b705cfSriastradh return true; 137803b705cfSriastradh 137903b705cfSriastradh ndwords = op->need_magic_ca_pass ? 60 : 6; 138003b705cfSriastradh if ((sna->render.vb_id & id) == 0) 138103b705cfSriastradh ndwords += 5; 138203b705cfSriastradh if (!kgem_check_batch(&sna->kgem, ndwords)) 138303b705cfSriastradh return false; 138403b705cfSriastradh 138503b705cfSriastradh if ((sna->render.vb_id & id) == 0) 138603b705cfSriastradh gen7_emit_vertex_buffer(sna, op); 138703b705cfSriastradh 138803b705cfSriastradh gen7_emit_primitive(sna); 138903b705cfSriastradh return true; 139003b705cfSriastradh} 139103b705cfSriastradh 139203b705cfSriastradhstatic int gen7_get_rectangles__flush(struct sna *sna, 139303b705cfSriastradh const struct sna_composite_op *op) 139403b705cfSriastradh{ 139503b705cfSriastradh /* Preventing discarding new vbo after lock contention */ 139603b705cfSriastradh if (sna_vertex_wait__locked(&sna->render)) { 139703b705cfSriastradh int rem = vertex_space(sna); 139803b705cfSriastradh if (rem > op->floats_per_rect) 139903b705cfSriastradh return rem; 140003b705cfSriastradh } 140103b705cfSriastradh 140203b705cfSriastradh if (!kgem_check_batch(&sna->kgem, op->need_magic_ca_pass ? 65 : 6)) 140303b705cfSriastradh return 0; 140403b705cfSriastradh if (!kgem_check_reloc_and_exec(&sna->kgem, 2)) 140503b705cfSriastradh return 0; 140603b705cfSriastradh 140703b705cfSriastradh if (sna->render.vertex_offset) { 140803b705cfSriastradh gen4_vertex_flush(sna); 140903b705cfSriastradh if (gen7_magic_ca_pass(sna, op)) { 141003b705cfSriastradh gen7_emit_pipe_stall(sna); 141103b705cfSriastradh gen7_emit_cc(sna, GEN7_BLEND(op->u.gen7.flags)); 141203b705cfSriastradh gen7_emit_wm(sna, GEN7_KERNEL(op->u.gen7.flags)); 141303b705cfSriastradh } 141403b705cfSriastradh } 141503b705cfSriastradh 141603b705cfSriastradh return gen4_vertex_finish(sna); 141703b705cfSriastradh} 141803b705cfSriastradh 141903b705cfSriastradhinline static int gen7_get_rectangles(struct sna *sna, 142003b705cfSriastradh const struct sna_composite_op *op, 142103b705cfSriastradh int want, 142203b705cfSriastradh void (*emit_state)(struct sna *sna, const struct sna_composite_op *op)) 142303b705cfSriastradh{ 142403b705cfSriastradh int rem; 142503b705cfSriastradh 142603b705cfSriastradh assert(want); 142703b705cfSriastradh 142803b705cfSriastradhstart: 142903b705cfSriastradh rem = vertex_space(sna); 143003b705cfSriastradh if (unlikely(rem < op->floats_per_rect)) { 143103b705cfSriastradh DBG(("flushing vbo for %s: %d < %d\n", 143203b705cfSriastradh __FUNCTION__, rem, op->floats_per_rect)); 143303b705cfSriastradh rem = gen7_get_rectangles__flush(sna, op); 143403b705cfSriastradh if (unlikely(rem == 0)) 143503b705cfSriastradh goto flush; 143603b705cfSriastradh } 143703b705cfSriastradh 143803b705cfSriastradh if (unlikely(sna->render.vertex_offset == 0)) { 143903b705cfSriastradh if (!gen7_rectangle_begin(sna, op)) 144003b705cfSriastradh goto flush; 144103b705cfSriastradh else 144203b705cfSriastradh goto start; 144303b705cfSriastradh } 144403b705cfSriastradh 144503b705cfSriastradh assert(rem <= vertex_space(sna)); 144603b705cfSriastradh assert(op->floats_per_rect <= rem); 144703b705cfSriastradh if (want > 1 && want * op->floats_per_rect > rem) 144803b705cfSriastradh want = rem / op->floats_per_rect; 144903b705cfSriastradh 145003b705cfSriastradh assert(want > 0); 145103b705cfSriastradh sna->render.vertex_index += 3*want; 145203b705cfSriastradh return want; 145303b705cfSriastradh 145403b705cfSriastradhflush: 145503b705cfSriastradh if (sna->render.vertex_offset) { 145603b705cfSriastradh gen4_vertex_flush(sna); 145703b705cfSriastradh gen7_magic_ca_pass(sna, op); 145803b705cfSriastradh } 145903b705cfSriastradh sna_vertex_wait__locked(&sna->render); 146003b705cfSriastradh _kgem_submit(&sna->kgem); 146103b705cfSriastradh emit_state(sna, op); 146203b705cfSriastradh goto start; 146303b705cfSriastradh} 146403b705cfSriastradh 146503b705cfSriastradhinline static uint32_t *gen7_composite_get_binding_table(struct sna *sna, 146603b705cfSriastradh uint16_t *offset) 146703b705cfSriastradh{ 146803b705cfSriastradh uint32_t *table; 146903b705cfSriastradh 147003b705cfSriastradh sna->kgem.surface -= 147103b705cfSriastradh sizeof(struct gen7_surface_state) / sizeof(uint32_t); 147203b705cfSriastradh /* Clear all surplus entries to zero in case of prefetch */ 147303b705cfSriastradh table = memset(sna->kgem.batch + sna->kgem.surface, 147403b705cfSriastradh 0, sizeof(struct gen7_surface_state)); 147503b705cfSriastradh 147603b705cfSriastradh DBG(("%s(%x)\n", __FUNCTION__, 4*sna->kgem.surface)); 147703b705cfSriastradh 147803b705cfSriastradh *offset = sna->kgem.surface; 147903b705cfSriastradh return table; 148003b705cfSriastradh} 148103b705cfSriastradh 148203b705cfSriastradhstatic void 148303b705cfSriastradhgen7_get_batch(struct sna *sna, const struct sna_composite_op *op) 148403b705cfSriastradh{ 148503b705cfSriastradh kgem_set_mode(&sna->kgem, KGEM_RENDER, op->dst.bo); 148603b705cfSriastradh 148703b705cfSriastradh if (!kgem_check_batch_with_surfaces(&sna->kgem, 150, 4)) { 148803b705cfSriastradh DBG(("%s: flushing batch: %d < %d+%d\n", 148903b705cfSriastradh __FUNCTION__, sna->kgem.surface - sna->kgem.nbatch, 149003b705cfSriastradh 150, 4*8)); 149103b705cfSriastradh _kgem_submit(&sna->kgem); 149203b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 149303b705cfSriastradh } 149403b705cfSriastradh 149503b705cfSriastradh assert(sna->kgem.mode == KGEM_RENDER); 149603b705cfSriastradh assert(sna->kgem.ring == KGEM_RENDER); 149703b705cfSriastradh 149803b705cfSriastradh if (sna->render_state.gen7.needs_invariant) 149903b705cfSriastradh gen7_emit_invariant(sna); 150003b705cfSriastradh} 150103b705cfSriastradh 150203b705cfSriastradhstatic void gen7_emit_composite_state(struct sna *sna, 150303b705cfSriastradh const struct sna_composite_op *op) 150403b705cfSriastradh{ 150503b705cfSriastradh uint32_t *binding_table; 150642542f5fSchristos uint16_t offset, dirty; 150703b705cfSriastradh 150803b705cfSriastradh gen7_get_batch(sna, op); 150903b705cfSriastradh 151003b705cfSriastradh binding_table = gen7_composite_get_binding_table(sna, &offset); 151103b705cfSriastradh 151242542f5fSchristos dirty = kgem_bo_is_dirty(op->dst.bo); 151342542f5fSchristos 151403b705cfSriastradh binding_table[0] = 151503b705cfSriastradh gen7_bind_bo(sna, 151603b705cfSriastradh op->dst.bo, op->dst.width, op->dst.height, 151703b705cfSriastradh gen7_get_dest_format(op->dst.format), 151803b705cfSriastradh true); 151903b705cfSriastradh binding_table[1] = 152003b705cfSriastradh gen7_bind_bo(sna, 152103b705cfSriastradh op->src.bo, op->src.width, op->src.height, 152203b705cfSriastradh op->src.card_format, 152303b705cfSriastradh false); 152403b705cfSriastradh if (op->mask.bo) { 152503b705cfSriastradh binding_table[2] = 152603b705cfSriastradh gen7_bind_bo(sna, 152703b705cfSriastradh op->mask.bo, 152803b705cfSriastradh op->mask.width, 152903b705cfSriastradh op->mask.height, 153003b705cfSriastradh op->mask.card_format, 153103b705cfSriastradh false); 153203b705cfSriastradh } 153303b705cfSriastradh 153403b705cfSriastradh if (sna->kgem.surface == offset && 153503b705cfSriastradh *(uint64_t *)(sna->kgem.batch + sna->render_state.gen7.surface_table) == *(uint64_t*)binding_table && 153603b705cfSriastradh (op->mask.bo == NULL || 153703b705cfSriastradh sna->kgem.batch[sna->render_state.gen7.surface_table+2] == binding_table[2])) { 153803b705cfSriastradh sna->kgem.surface += sizeof(struct gen7_surface_state) / sizeof(uint32_t); 153903b705cfSriastradh offset = sna->render_state.gen7.surface_table; 154003b705cfSriastradh } 154103b705cfSriastradh 154242542f5fSchristos if (sna->kgem.batch[sna->render_state.gen7.surface_table] == binding_table[0]) 154342542f5fSchristos dirty = 0; 154442542f5fSchristos 154542542f5fSchristos gen7_emit_state(sna, op, offset | dirty); 154603b705cfSriastradh} 154703b705cfSriastradh 154803b705cfSriastradhstatic void 154903b705cfSriastradhgen7_align_vertex(struct sna *sna, const struct sna_composite_op *op) 155003b705cfSriastradh{ 155103b705cfSriastradh if (op->floats_per_vertex != sna->render_state.gen7.floats_per_vertex) { 155242542f5fSchristos DBG(("aligning vertex: was %d, now %d floats per vertex\n", 155342542f5fSchristos sna->render_state.gen7.floats_per_vertex, op->floats_per_vertex)); 155442542f5fSchristos gen4_vertex_align(sna, op); 155503b705cfSriastradh sna->render_state.gen7.floats_per_vertex = op->floats_per_vertex; 155603b705cfSriastradh } 155703b705cfSriastradh} 155803b705cfSriastradh 155903b705cfSriastradhfastcall static void 156003b705cfSriastradhgen7_render_composite_blt(struct sna *sna, 156103b705cfSriastradh const struct sna_composite_op *op, 156203b705cfSriastradh const struct sna_composite_rectangles *r) 156303b705cfSriastradh{ 156403b705cfSriastradh gen7_get_rectangles(sna, op, 1, gen7_emit_composite_state); 156503b705cfSriastradh op->prim_emit(sna, op, r); 156603b705cfSriastradh} 156703b705cfSriastradh 156803b705cfSriastradhfastcall static void 156903b705cfSriastradhgen7_render_composite_box(struct sna *sna, 157003b705cfSriastradh const struct sna_composite_op *op, 157103b705cfSriastradh const BoxRec *box) 157203b705cfSriastradh{ 157303b705cfSriastradh struct sna_composite_rectangles r; 157403b705cfSriastradh 157503b705cfSriastradh gen7_get_rectangles(sna, op, 1, gen7_emit_composite_state); 157603b705cfSriastradh 157703b705cfSriastradh DBG((" %s: (%d, %d), (%d, %d)\n", 157803b705cfSriastradh __FUNCTION__, 157903b705cfSriastradh box->x1, box->y1, box->x2, box->y2)); 158003b705cfSriastradh 158103b705cfSriastradh r.dst.x = box->x1; 158203b705cfSriastradh r.dst.y = box->y1; 158303b705cfSriastradh r.width = box->x2 - box->x1; 158403b705cfSriastradh r.height = box->y2 - box->y1; 158503b705cfSriastradh r.src = r.mask = r.dst; 158603b705cfSriastradh 158703b705cfSriastradh op->prim_emit(sna, op, &r); 158803b705cfSriastradh} 158903b705cfSriastradh 159003b705cfSriastradhstatic void 159103b705cfSriastradhgen7_render_composite_boxes__blt(struct sna *sna, 159203b705cfSriastradh const struct sna_composite_op *op, 159303b705cfSriastradh const BoxRec *box, int nbox) 159403b705cfSriastradh{ 159503b705cfSriastradh DBG(("composite_boxes(%d)\n", nbox)); 159603b705cfSriastradh 159703b705cfSriastradh do { 159803b705cfSriastradh int nbox_this_time; 159903b705cfSriastradh 160003b705cfSriastradh nbox_this_time = gen7_get_rectangles(sna, op, nbox, 160103b705cfSriastradh gen7_emit_composite_state); 160203b705cfSriastradh nbox -= nbox_this_time; 160303b705cfSriastradh 160403b705cfSriastradh do { 160503b705cfSriastradh struct sna_composite_rectangles r; 160603b705cfSriastradh 160703b705cfSriastradh DBG((" %s: (%d, %d), (%d, %d)\n", 160803b705cfSriastradh __FUNCTION__, 160903b705cfSriastradh box->x1, box->y1, box->x2, box->y2)); 161003b705cfSriastradh 161103b705cfSriastradh r.dst.x = box->x1; 161203b705cfSriastradh r.dst.y = box->y1; 161303b705cfSriastradh r.width = box->x2 - box->x1; 161403b705cfSriastradh r.height = box->y2 - box->y1; 161503b705cfSriastradh r.src = r.mask = r.dst; 161603b705cfSriastradh 161703b705cfSriastradh op->prim_emit(sna, op, &r); 161803b705cfSriastradh box++; 161903b705cfSriastradh } while (--nbox_this_time); 162003b705cfSriastradh } while (nbox); 162103b705cfSriastradh} 162203b705cfSriastradh 162303b705cfSriastradhstatic void 162403b705cfSriastradhgen7_render_composite_boxes(struct sna *sna, 162503b705cfSriastradh const struct sna_composite_op *op, 162603b705cfSriastradh const BoxRec *box, int nbox) 162703b705cfSriastradh{ 162803b705cfSriastradh DBG(("%s: nbox=%d\n", __FUNCTION__, nbox)); 162903b705cfSriastradh 163003b705cfSriastradh do { 163103b705cfSriastradh int nbox_this_time; 163203b705cfSriastradh float *v; 163303b705cfSriastradh 163403b705cfSriastradh nbox_this_time = gen7_get_rectangles(sna, op, nbox, 163503b705cfSriastradh gen7_emit_composite_state); 163603b705cfSriastradh assert(nbox_this_time); 163703b705cfSriastradh nbox -= nbox_this_time; 163803b705cfSriastradh 163903b705cfSriastradh v = sna->render.vertices + sna->render.vertex_used; 164003b705cfSriastradh sna->render.vertex_used += nbox_this_time * op->floats_per_rect; 164103b705cfSriastradh 164203b705cfSriastradh op->emit_boxes(op, box, nbox_this_time, v); 164303b705cfSriastradh box += nbox_this_time; 164403b705cfSriastradh } while (nbox); 164503b705cfSriastradh} 164603b705cfSriastradh 164703b705cfSriastradhstatic void 164803b705cfSriastradhgen7_render_composite_boxes__thread(struct sna *sna, 164903b705cfSriastradh const struct sna_composite_op *op, 165003b705cfSriastradh const BoxRec *box, int nbox) 165103b705cfSriastradh{ 165203b705cfSriastradh DBG(("%s: nbox=%d\n", __FUNCTION__, nbox)); 165303b705cfSriastradh 165403b705cfSriastradh sna_vertex_lock(&sna->render); 165503b705cfSriastradh do { 165603b705cfSriastradh int nbox_this_time; 165703b705cfSriastradh float *v; 165803b705cfSriastradh 165903b705cfSriastradh nbox_this_time = gen7_get_rectangles(sna, op, nbox, 166003b705cfSriastradh gen7_emit_composite_state); 166103b705cfSriastradh assert(nbox_this_time); 166203b705cfSriastradh nbox -= nbox_this_time; 166303b705cfSriastradh 166403b705cfSriastradh v = sna->render.vertices + sna->render.vertex_used; 166503b705cfSriastradh sna->render.vertex_used += nbox_this_time * op->floats_per_rect; 166603b705cfSriastradh 166703b705cfSriastradh sna_vertex_acquire__locked(&sna->render); 166803b705cfSriastradh sna_vertex_unlock(&sna->render); 166903b705cfSriastradh 167003b705cfSriastradh op->emit_boxes(op, box, nbox_this_time, v); 167103b705cfSriastradh box += nbox_this_time; 167203b705cfSriastradh 167303b705cfSriastradh sna_vertex_lock(&sna->render); 167403b705cfSriastradh sna_vertex_release__locked(&sna->render); 167503b705cfSriastradh } while (nbox); 167603b705cfSriastradh sna_vertex_unlock(&sna->render); 167703b705cfSriastradh} 167803b705cfSriastradh 167903b705cfSriastradh#ifndef MAX 168003b705cfSriastradh#define MAX(a,b) ((a) > (b) ? (a) : (b)) 168103b705cfSriastradh#endif 168203b705cfSriastradh 168303b705cfSriastradhstatic uint32_t 168403b705cfSriastradhgen7_composite_create_blend_state(struct sna_static_stream *stream) 168503b705cfSriastradh{ 168603b705cfSriastradh char *base, *ptr; 168703b705cfSriastradh int src, dst; 168803b705cfSriastradh 168903b705cfSriastradh base = sna_static_stream_map(stream, 169003b705cfSriastradh GEN7_BLENDFACTOR_COUNT * GEN7_BLENDFACTOR_COUNT * GEN7_BLEND_STATE_PADDED_SIZE, 169103b705cfSriastradh 64); 169203b705cfSriastradh 169303b705cfSriastradh ptr = base; 169403b705cfSriastradh for (src = 0; src < GEN7_BLENDFACTOR_COUNT; src++) { 169503b705cfSriastradh for (dst= 0; dst < GEN7_BLENDFACTOR_COUNT; dst++) { 169603b705cfSriastradh struct gen7_blend_state *blend = 169703b705cfSriastradh (struct gen7_blend_state *)ptr; 169803b705cfSriastradh 169903b705cfSriastradh blend->blend0.dest_blend_factor = dst; 170003b705cfSriastradh blend->blend0.source_blend_factor = src; 170103b705cfSriastradh blend->blend0.blend_func = GEN7_BLENDFUNCTION_ADD; 170203b705cfSriastradh blend->blend0.blend_enable = 170303b705cfSriastradh !(dst == GEN7_BLENDFACTOR_ZERO && src == GEN7_BLENDFACTOR_ONE); 170403b705cfSriastradh 170503b705cfSriastradh blend->blend1.post_blend_clamp_enable = 1; 170603b705cfSriastradh blend->blend1.pre_blend_clamp_enable = 1; 170703b705cfSriastradh 170803b705cfSriastradh ptr += GEN7_BLEND_STATE_PADDED_SIZE; 170903b705cfSriastradh } 171003b705cfSriastradh } 171103b705cfSriastradh 171203b705cfSriastradh return sna_static_stream_offsetof(stream, base); 171303b705cfSriastradh} 171403b705cfSriastradh 171503b705cfSriastradhstatic uint32_t gen7_bind_video_source(struct sna *sna, 171603b705cfSriastradh struct kgem_bo *bo, 171703b705cfSriastradh uint32_t offset, 171803b705cfSriastradh int width, 171903b705cfSriastradh int height, 172003b705cfSriastradh int pitch, 172103b705cfSriastradh uint32_t format) 172203b705cfSriastradh{ 172303b705cfSriastradh uint32_t *ss, bind; 172403b705cfSriastradh 172503b705cfSriastradh bind = sna->kgem.surface -= 172603b705cfSriastradh sizeof(struct gen7_surface_state) / sizeof(uint32_t); 172703b705cfSriastradh 172803b705cfSriastradh assert(bo->tiling == I915_TILING_NONE); 172903b705cfSriastradh 173003b705cfSriastradh ss = sna->kgem.batch + bind; 173103b705cfSriastradh ss[0] = (GEN7_SURFACE_2D << GEN7_SURFACE_TYPE_SHIFT | 173203b705cfSriastradh format << GEN7_SURFACE_FORMAT_SHIFT); 173303b705cfSriastradh ss[1] = kgem_add_reloc(&sna->kgem, bind + 1, bo, 173403b705cfSriastradh I915_GEM_DOMAIN_SAMPLER << 16, 173503b705cfSriastradh offset); 173603b705cfSriastradh ss[2] = ((width - 1) << GEN7_SURFACE_WIDTH_SHIFT | 173703b705cfSriastradh (height - 1) << GEN7_SURFACE_HEIGHT_SHIFT); 173803b705cfSriastradh ss[3] = (pitch - 1) << GEN7_SURFACE_PITCH_SHIFT; 173903b705cfSriastradh ss[4] = 0; 174003b705cfSriastradh ss[5] = 0; 174103b705cfSriastradh ss[6] = 0; 174203b705cfSriastradh ss[7] = 0; 174303b705cfSriastradh if (is_hsw(sna)) 174403b705cfSriastradh ss[7] |= HSW_SURFACE_SWIZZLE(RED, GREEN, BLUE, ALPHA); 174503b705cfSriastradh 174603b705cfSriastradh DBG(("[%x] bind bo(handle=%d, addr=%d), format=%d, width=%d, height=%d, pitch=%d, offset=%d\n", 174703b705cfSriastradh bind, bo->handle, ss[1], 174803b705cfSriastradh format, width, height, pitch, offset)); 174903b705cfSriastradh 175003b705cfSriastradh return bind * sizeof(uint32_t); 175103b705cfSriastradh} 175203b705cfSriastradh 175303b705cfSriastradhstatic void gen7_emit_video_state(struct sna *sna, 175403b705cfSriastradh const struct sna_composite_op *op) 175503b705cfSriastradh{ 175603b705cfSriastradh struct sna_video_frame *frame = op->priv; 175703b705cfSriastradh uint32_t src_surf_format; 175803b705cfSriastradh uint32_t src_surf_base[6]; 175903b705cfSriastradh int src_width[6]; 176003b705cfSriastradh int src_height[6]; 176103b705cfSriastradh int src_pitch[6]; 176203b705cfSriastradh uint32_t *binding_table; 176342542f5fSchristos uint16_t offset, dirty; 176403b705cfSriastradh int n_src, n; 176503b705cfSriastradh 176603b705cfSriastradh gen7_get_batch(sna, op); 176703b705cfSriastradh 176803b705cfSriastradh src_surf_base[0] = 0; 176903b705cfSriastradh src_surf_base[1] = 0; 177003b705cfSriastradh src_surf_base[2] = frame->VBufOffset; 177103b705cfSriastradh src_surf_base[3] = frame->VBufOffset; 177203b705cfSriastradh src_surf_base[4] = frame->UBufOffset; 177303b705cfSriastradh src_surf_base[5] = frame->UBufOffset; 177403b705cfSriastradh 177503b705cfSriastradh if (is_planar_fourcc(frame->id)) { 177603b705cfSriastradh src_surf_format = GEN7_SURFACEFORMAT_R8_UNORM; 177703b705cfSriastradh src_width[1] = src_width[0] = frame->width; 177803b705cfSriastradh src_height[1] = src_height[0] = frame->height; 177903b705cfSriastradh src_pitch[1] = src_pitch[0] = frame->pitch[1]; 178003b705cfSriastradh src_width[4] = src_width[5] = src_width[2] = src_width[3] = 178103b705cfSriastradh frame->width / 2; 178203b705cfSriastradh src_height[4] = src_height[5] = src_height[2] = src_height[3] = 178303b705cfSriastradh frame->height / 2; 178403b705cfSriastradh src_pitch[4] = src_pitch[5] = src_pitch[2] = src_pitch[3] = 178503b705cfSriastradh frame->pitch[0]; 178603b705cfSriastradh n_src = 6; 178703b705cfSriastradh } else { 178803b705cfSriastradh if (frame->id == FOURCC_UYVY) 178903b705cfSriastradh src_surf_format = GEN7_SURFACEFORMAT_YCRCB_SWAPY; 179003b705cfSriastradh else 179103b705cfSriastradh src_surf_format = GEN7_SURFACEFORMAT_YCRCB_NORMAL; 179203b705cfSriastradh 179303b705cfSriastradh src_width[0] = frame->width; 179403b705cfSriastradh src_height[0] = frame->height; 179503b705cfSriastradh src_pitch[0] = frame->pitch[0]; 179603b705cfSriastradh n_src = 1; 179703b705cfSriastradh } 179803b705cfSriastradh 179903b705cfSriastradh binding_table = gen7_composite_get_binding_table(sna, &offset); 180003b705cfSriastradh 180142542f5fSchristos dirty = kgem_bo_is_dirty(op->dst.bo); 180242542f5fSchristos 180303b705cfSriastradh binding_table[0] = 180403b705cfSriastradh gen7_bind_bo(sna, 180503b705cfSriastradh op->dst.bo, op->dst.width, op->dst.height, 180603b705cfSriastradh gen7_get_dest_format(op->dst.format), 180703b705cfSriastradh true); 180803b705cfSriastradh for (n = 0; n < n_src; n++) { 180903b705cfSriastradh binding_table[1+n] = 181003b705cfSriastradh gen7_bind_video_source(sna, 181103b705cfSriastradh frame->bo, 181203b705cfSriastradh src_surf_base[n], 181303b705cfSriastradh src_width[n], 181403b705cfSriastradh src_height[n], 181503b705cfSriastradh src_pitch[n], 181603b705cfSriastradh src_surf_format); 181703b705cfSriastradh } 181803b705cfSriastradh 181942542f5fSchristos gen7_emit_state(sna, op, offset | dirty); 182003b705cfSriastradh} 182103b705cfSriastradh 182203b705cfSriastradhstatic bool 182303b705cfSriastradhgen7_render_video(struct sna *sna, 182403b705cfSriastradh struct sna_video *video, 182503b705cfSriastradh struct sna_video_frame *frame, 182603b705cfSriastradh RegionPtr dstRegion, 182703b705cfSriastradh PixmapPtr pixmap) 182803b705cfSriastradh{ 182903b705cfSriastradh struct sna_composite_op tmp; 183042542f5fSchristos struct sna_pixmap *priv = sna_pixmap(pixmap); 183103b705cfSriastradh int dst_width = dstRegion->extents.x2 - dstRegion->extents.x1; 183203b705cfSriastradh int dst_height = dstRegion->extents.y2 - dstRegion->extents.y1; 183303b705cfSriastradh int src_width = frame->src.x2 - frame->src.x1; 183403b705cfSriastradh int src_height = frame->src.y2 - frame->src.y1; 183503b705cfSriastradh float src_offset_x, src_offset_y; 183603b705cfSriastradh float src_scale_x, src_scale_y; 183703b705cfSriastradh int nbox, pix_xoff, pix_yoff; 183803b705cfSriastradh unsigned filter; 183942542f5fSchristos const BoxRec *box; 184003b705cfSriastradh 184142542f5fSchristos DBG(("%s: src=(%d, %d), dst=(%d, %d), %dx[(%d, %d), (%d, %d)...]\n", 184203b705cfSriastradh __FUNCTION__, 184303b705cfSriastradh src_width, src_height, dst_width, dst_height, 184442542f5fSchristos region_num_rects(dstRegion), 184503b705cfSriastradh REGION_EXTENTS(NULL, dstRegion)->x1, 184603b705cfSriastradh REGION_EXTENTS(NULL, dstRegion)->y1, 184703b705cfSriastradh REGION_EXTENTS(NULL, dstRegion)->x2, 184803b705cfSriastradh REGION_EXTENTS(NULL, dstRegion)->y2)); 184903b705cfSriastradh 185042542f5fSchristos assert(priv->gpu_bo); 185103b705cfSriastradh memset(&tmp, 0, sizeof(tmp)); 185203b705cfSriastradh 185303b705cfSriastradh tmp.dst.pixmap = pixmap; 185403b705cfSriastradh tmp.dst.width = pixmap->drawable.width; 185503b705cfSriastradh tmp.dst.height = pixmap->drawable.height; 185603b705cfSriastradh tmp.dst.format = sna_render_format_for_depth(pixmap->drawable.depth); 185703b705cfSriastradh tmp.dst.bo = priv->gpu_bo; 185803b705cfSriastradh 185903b705cfSriastradh tmp.src.bo = frame->bo; 186003b705cfSriastradh tmp.mask.bo = NULL; 186103b705cfSriastradh 186203b705cfSriastradh tmp.floats_per_vertex = 3; 186303b705cfSriastradh tmp.floats_per_rect = 9; 186403b705cfSriastradh 186503b705cfSriastradh if (src_width == dst_width && src_height == dst_height) 186603b705cfSriastradh filter = SAMPLER_FILTER_NEAREST; 186703b705cfSriastradh else 186803b705cfSriastradh filter = SAMPLER_FILTER_BILINEAR; 186903b705cfSriastradh 187003b705cfSriastradh tmp.u.gen7.flags = 187103b705cfSriastradh GEN7_SET_FLAGS(SAMPLER_OFFSET(filter, SAMPLER_EXTEND_PAD, 187203b705cfSriastradh SAMPLER_FILTER_NEAREST, SAMPLER_EXTEND_NONE), 187303b705cfSriastradh NO_BLEND, 187403b705cfSriastradh is_planar_fourcc(frame->id) ? 187503b705cfSriastradh GEN7_WM_KERNEL_VIDEO_PLANAR : 187603b705cfSriastradh GEN7_WM_KERNEL_VIDEO_PACKED, 187703b705cfSriastradh 2); 187803b705cfSriastradh tmp.priv = frame; 187903b705cfSriastradh 188003b705cfSriastradh kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp.dst.bo); 188103b705cfSriastradh if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, frame->bo, NULL)) { 188203b705cfSriastradh kgem_submit(&sna->kgem); 188342542f5fSchristos if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, frame->bo, NULL)) 188442542f5fSchristos return false; 188542542f5fSchristos 188603b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 188703b705cfSriastradh } 188803b705cfSriastradh 188903b705cfSriastradh gen7_align_vertex(sna, &tmp); 189042542f5fSchristos gen7_emit_video_state(sna, &tmp); 189103b705cfSriastradh 189203b705cfSriastradh /* Set up the offset for translating from the given region (in screen 189303b705cfSriastradh * coordinates) to the backing pixmap. 189403b705cfSriastradh */ 189503b705cfSriastradh#ifdef COMPOSITE 189603b705cfSriastradh pix_xoff = -pixmap->screen_x + pixmap->drawable.x; 189703b705cfSriastradh pix_yoff = -pixmap->screen_y + pixmap->drawable.y; 189803b705cfSriastradh#else 189903b705cfSriastradh pix_xoff = 0; 190003b705cfSriastradh pix_yoff = 0; 190103b705cfSriastradh#endif 190203b705cfSriastradh 190303b705cfSriastradh DBG(("%s: src=(%d, %d)x(%d, %d); frame=(%dx%d), dst=(%dx%d)\n", 190403b705cfSriastradh __FUNCTION__, 190503b705cfSriastradh frame->src.x1, frame->src.y1, 190603b705cfSriastradh src_width, src_height, 190703b705cfSriastradh dst_width, dst_height, 190803b705cfSriastradh frame->width, frame->height)); 190903b705cfSriastradh 191003b705cfSriastradh src_scale_x = (float)src_width / dst_width / frame->width; 191103b705cfSriastradh src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x; 191203b705cfSriastradh 191303b705cfSriastradh src_scale_y = (float)src_height / dst_height / frame->height; 191403b705cfSriastradh src_offset_y = (float)frame->src.y1 / frame->height - dstRegion->extents.y1 * src_scale_y; 191503b705cfSriastradh 191603b705cfSriastradh DBG(("%s: scale=(%f, %f), offset=(%f, %f)\n", 191703b705cfSriastradh __FUNCTION__, 191803b705cfSriastradh src_scale_x, src_scale_y, 191903b705cfSriastradh src_offset_x, src_offset_y)); 192003b705cfSriastradh 192142542f5fSchristos box = region_rects(dstRegion); 192242542f5fSchristos nbox = region_num_rects(dstRegion); 192303b705cfSriastradh while (nbox--) { 192403b705cfSriastradh BoxRec r; 192503b705cfSriastradh 192603b705cfSriastradh DBG(("%s: dst=(%d, %d), (%d, %d) + (%d, %d); src=(%f, %f), (%f, %f)\n", 192703b705cfSriastradh __FUNCTION__, 192803b705cfSriastradh box->x1, box->y1, 192903b705cfSriastradh box->x2, box->y2, 193003b705cfSriastradh pix_xoff, pix_yoff, 193103b705cfSriastradh box->x1 * src_scale_x + src_offset_x, 193203b705cfSriastradh box->y1 * src_scale_y + src_offset_y, 193303b705cfSriastradh box->x2 * src_scale_x + src_offset_x, 193403b705cfSriastradh box->y2 * src_scale_y + src_offset_y)); 193503b705cfSriastradh 193603b705cfSriastradh r.x1 = box->x1 + pix_xoff; 193703b705cfSriastradh r.x2 = box->x2 + pix_xoff; 193803b705cfSriastradh r.y1 = box->y1 + pix_yoff; 193903b705cfSriastradh r.y2 = box->y2 + pix_yoff; 194003b705cfSriastradh 194103b705cfSriastradh gen7_get_rectangles(sna, &tmp, 1, gen7_emit_video_state); 194203b705cfSriastradh 194303b705cfSriastradh OUT_VERTEX(r.x2, r.y2); 194403b705cfSriastradh OUT_VERTEX_F(box->x2 * src_scale_x + src_offset_x); 194503b705cfSriastradh OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y); 194603b705cfSriastradh 194703b705cfSriastradh OUT_VERTEX(r.x1, r.y2); 194803b705cfSriastradh OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x); 194903b705cfSriastradh OUT_VERTEX_F(box->y2 * src_scale_y + src_offset_y); 195003b705cfSriastradh 195103b705cfSriastradh OUT_VERTEX(r.x1, r.y1); 195203b705cfSriastradh OUT_VERTEX_F(box->x1 * src_scale_x + src_offset_x); 195303b705cfSriastradh OUT_VERTEX_F(box->y1 * src_scale_y + src_offset_y); 195403b705cfSriastradh 195503b705cfSriastradh if (!DAMAGE_IS_ALL(priv->gpu_damage)) { 195603b705cfSriastradh sna_damage_add_box(&priv->gpu_damage, &r); 195703b705cfSriastradh sna_damage_subtract_box(&priv->cpu_damage, &r); 195803b705cfSriastradh } 195903b705cfSriastradh box++; 196003b705cfSriastradh } 196103b705cfSriastradh 196203b705cfSriastradh gen4_vertex_flush(sna); 196303b705cfSriastradh return true; 196403b705cfSriastradh} 196503b705cfSriastradh 196603b705cfSriastradhstatic int 196703b705cfSriastradhgen7_composite_picture(struct sna *sna, 196803b705cfSriastradh PicturePtr picture, 196903b705cfSriastradh struct sna_composite_channel *channel, 197003b705cfSriastradh int x, int y, 197103b705cfSriastradh int w, int h, 197203b705cfSriastradh int dst_x, int dst_y, 197303b705cfSriastradh bool precise) 197403b705cfSriastradh{ 197503b705cfSriastradh PixmapPtr pixmap; 197603b705cfSriastradh uint32_t color; 197703b705cfSriastradh int16_t dx, dy; 197803b705cfSriastradh 197903b705cfSriastradh DBG(("%s: (%d, %d)x(%d, %d), dst=(%d, %d)\n", 198003b705cfSriastradh __FUNCTION__, x, y, w, h, dst_x, dst_y)); 198103b705cfSriastradh 198203b705cfSriastradh channel->is_solid = false; 198303b705cfSriastradh channel->card_format = -1; 198403b705cfSriastradh 198503b705cfSriastradh if (sna_picture_is_solid(picture, &color)) 198603b705cfSriastradh return gen4_channel_init_solid(sna, channel, color); 198703b705cfSriastradh 198803b705cfSriastradh if (picture->pDrawable == NULL) { 198903b705cfSriastradh int ret; 199003b705cfSriastradh 199103b705cfSriastradh if (picture->pSourcePict->type == SourcePictTypeLinear) 199203b705cfSriastradh return gen4_channel_init_linear(sna, picture, channel, 199303b705cfSriastradh x, y, 199403b705cfSriastradh w, h, 199503b705cfSriastradh dst_x, dst_y); 199603b705cfSriastradh 199703b705cfSriastradh DBG(("%s -- fixup, gradient\n", __FUNCTION__)); 199803b705cfSriastradh ret = -1; 199903b705cfSriastradh if (!precise) 200003b705cfSriastradh ret = sna_render_picture_approximate_gradient(sna, picture, channel, 200103b705cfSriastradh x, y, w, h, dst_x, dst_y); 200203b705cfSriastradh if (ret == -1) 200303b705cfSriastradh ret = sna_render_picture_fixup(sna, picture, channel, 200403b705cfSriastradh x, y, w, h, dst_x, dst_y); 200503b705cfSriastradh return ret; 200603b705cfSriastradh } 200703b705cfSriastradh 200803b705cfSriastradh if (picture->alphaMap) { 200903b705cfSriastradh DBG(("%s -- fallback, alphamap\n", __FUNCTION__)); 201003b705cfSriastradh return sna_render_picture_fixup(sna, picture, channel, 201103b705cfSriastradh x, y, w, h, dst_x, dst_y); 201203b705cfSriastradh } 201303b705cfSriastradh 201403b705cfSriastradh if (!gen7_check_repeat(picture)) 201503b705cfSriastradh return sna_render_picture_fixup(sna, picture, channel, 201603b705cfSriastradh x, y, w, h, dst_x, dst_y); 201703b705cfSriastradh 201803b705cfSriastradh if (!gen7_check_filter(picture)) 201903b705cfSriastradh return sna_render_picture_fixup(sna, picture, channel, 202003b705cfSriastradh x, y, w, h, dst_x, dst_y); 202103b705cfSriastradh 202203b705cfSriastradh channel->repeat = picture->repeat ? picture->repeatType : RepeatNone; 202303b705cfSriastradh channel->filter = picture->filter; 202403b705cfSriastradh 202542542f5fSchristos assert(picture->pDrawable); 202603b705cfSriastradh pixmap = get_drawable_pixmap(picture->pDrawable); 202703b705cfSriastradh get_drawable_deltas(picture->pDrawable, pixmap, &dx, &dy); 202803b705cfSriastradh 202903b705cfSriastradh x += dx + picture->pDrawable->x; 203003b705cfSriastradh y += dy + picture->pDrawable->y; 203103b705cfSriastradh 203203b705cfSriastradh channel->is_affine = sna_transform_is_affine(picture->transform); 203342542f5fSchristos if (sna_transform_is_imprecise_integer_translation(picture->transform, picture->filter, precise, &dx, &dy)) { 203403b705cfSriastradh DBG(("%s: integer translation (%d, %d), removing\n", 203503b705cfSriastradh __FUNCTION__, dx, dy)); 203603b705cfSriastradh x += dx; 203703b705cfSriastradh y += dy; 203803b705cfSriastradh channel->transform = NULL; 203903b705cfSriastradh channel->filter = PictFilterNearest; 204042542f5fSchristos 204142542f5fSchristos if (channel->repeat || 204242542f5fSchristos (x >= 0 && 204342542f5fSchristos y >= 0 && 204442542f5fSchristos x + w < pixmap->drawable.width && 204542542f5fSchristos y + h < pixmap->drawable.height)) { 204642542f5fSchristos struct sna_pixmap *priv = sna_pixmap(pixmap); 204742542f5fSchristos if (priv && priv->clear) { 204842542f5fSchristos DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color)); 204942542f5fSchristos return gen4_channel_init_solid(sna, channel, priv->clear_color); 205042542f5fSchristos } 205142542f5fSchristos } 205203b705cfSriastradh } else 205303b705cfSriastradh channel->transform = picture->transform; 205403b705cfSriastradh 205503b705cfSriastradh channel->pict_format = picture->format; 205603b705cfSriastradh channel->card_format = gen7_get_card_format(picture->format); 205703b705cfSriastradh if (channel->card_format == (unsigned)-1) 205803b705cfSriastradh return sna_render_picture_convert(sna, picture, channel, pixmap, 205903b705cfSriastradh x, y, w, h, dst_x, dst_y, 206003b705cfSriastradh false); 206103b705cfSriastradh 206203b705cfSriastradh if (too_large(pixmap->drawable.width, pixmap->drawable.height)) { 206303b705cfSriastradh DBG(("%s: extracting from pixmap %dx%d\n", __FUNCTION__, 206403b705cfSriastradh pixmap->drawable.width, pixmap->drawable.height)); 206503b705cfSriastradh return sna_render_picture_extract(sna, picture, channel, 206603b705cfSriastradh x, y, w, h, dst_x, dst_y); 206703b705cfSriastradh } 206803b705cfSriastradh 206903b705cfSriastradh DBG(("%s: pixmap, repeat=%d, filter=%d, transform?=%d [affine? %d], format=%08x\n", 207003b705cfSriastradh __FUNCTION__, 207103b705cfSriastradh channel->repeat, channel->filter, 207203b705cfSriastradh channel->transform != NULL, channel->is_affine, 207303b705cfSriastradh channel->pict_format)); 207403b705cfSriastradh if (channel->transform) { 207503b705cfSriastradh DBG(("%s: transform=[%f %f %f, %f %f %f, %f %f %f]\n", 207603b705cfSriastradh __FUNCTION__, 207703b705cfSriastradh channel->transform->matrix[0][0] / 65536., 207803b705cfSriastradh channel->transform->matrix[0][1] / 65536., 207903b705cfSriastradh channel->transform->matrix[0][2] / 65536., 208003b705cfSriastradh channel->transform->matrix[1][0] / 65536., 208103b705cfSriastradh channel->transform->matrix[1][1] / 65536., 208203b705cfSriastradh channel->transform->matrix[1][2] / 65536., 208303b705cfSriastradh channel->transform->matrix[2][0] / 65536., 208403b705cfSriastradh channel->transform->matrix[2][1] / 65536., 208503b705cfSriastradh channel->transform->matrix[2][2] / 65536.)); 208603b705cfSriastradh } 208703b705cfSriastradh 208803b705cfSriastradh return sna_render_pixmap_bo(sna, channel, pixmap, 208903b705cfSriastradh x, y, w, h, dst_x, dst_y); 209003b705cfSriastradh} 209103b705cfSriastradh 209242542f5fSchristosinline static void gen7_composite_channel_convert(struct sna_composite_channel *channel) 209303b705cfSriastradh{ 209403b705cfSriastradh channel->repeat = gen7_repeat(channel->repeat); 209503b705cfSriastradh channel->filter = gen7_filter(channel->filter); 209603b705cfSriastradh if (channel->card_format == (unsigned)-1) 209703b705cfSriastradh channel->card_format = gen7_get_card_format(channel->pict_format); 209803b705cfSriastradh assert(channel->card_format != (unsigned)-1); 209903b705cfSriastradh} 210003b705cfSriastradh 210103b705cfSriastradhstatic void gen7_render_composite_done(struct sna *sna, 210203b705cfSriastradh const struct sna_composite_op *op) 210303b705cfSriastradh{ 210403b705cfSriastradh if (sna->render.vertex_offset) { 210503b705cfSriastradh gen4_vertex_flush(sna); 210603b705cfSriastradh gen7_magic_ca_pass(sna, op); 210703b705cfSriastradh } 210803b705cfSriastradh 210903b705cfSriastradh if (op->mask.bo) 211003b705cfSriastradh kgem_bo_destroy(&sna->kgem, op->mask.bo); 211103b705cfSriastradh if (op->src.bo) 211203b705cfSriastradh kgem_bo_destroy(&sna->kgem, op->src.bo); 211303b705cfSriastradh 211403b705cfSriastradh sna_render_composite_redirect_done(sna, op); 211503b705cfSriastradh} 211603b705cfSriastradh 211742542f5fSchristosinline static bool 211803b705cfSriastradhgen7_composite_set_target(struct sna *sna, 211903b705cfSriastradh struct sna_composite_op *op, 212003b705cfSriastradh PicturePtr dst, 212103b705cfSriastradh int x, int y, int w, int h, 212203b705cfSriastradh bool partial) 212303b705cfSriastradh{ 212403b705cfSriastradh BoxRec box; 212542542f5fSchristos unsigned int hint; 212642542f5fSchristos 212742542f5fSchristos DBG(("%s: (%d, %d)x(%d, %d), partial?=%d\n", __FUNCTION__, x, y, w, h, partial)); 212803b705cfSriastradh 212903b705cfSriastradh op->dst.pixmap = get_drawable_pixmap(dst->pDrawable); 213003b705cfSriastradh op->dst.format = dst->format; 213103b705cfSriastradh op->dst.width = op->dst.pixmap->drawable.width; 213203b705cfSriastradh op->dst.height = op->dst.pixmap->drawable.height; 213303b705cfSriastradh 213403b705cfSriastradh if (w | h) { 213503b705cfSriastradh assert(w && h); 213603b705cfSriastradh box.x1 = x; 213703b705cfSriastradh box.y1 = y; 213803b705cfSriastradh box.x2 = x + w; 213903b705cfSriastradh box.y2 = y + h; 214003b705cfSriastradh } else 214103b705cfSriastradh sna_render_picture_extents(dst, &box); 214203b705cfSriastradh 214342542f5fSchristos hint = PREFER_GPU | FORCE_GPU | RENDER_GPU; 214442542f5fSchristos if (!partial) { 214542542f5fSchristos hint |= IGNORE_DAMAGE; 214642542f5fSchristos if (w == op->dst.width && h == op->dst.height) 214742542f5fSchristos hint |= REPLACES; 214842542f5fSchristos } 214942542f5fSchristos 215042542f5fSchristos op->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint, &box, &op->damage); 215103b705cfSriastradh if (op->dst.bo == NULL) 215203b705cfSriastradh return false; 215303b705cfSriastradh 215442542f5fSchristos if (hint & REPLACES) { 215542542f5fSchristos struct sna_pixmap *priv = sna_pixmap(op->dst.pixmap); 215642542f5fSchristos kgem_bo_pair_undo(&sna->kgem, priv->gpu_bo, priv->cpu_bo); 215742542f5fSchristos } 215842542f5fSchristos 215903b705cfSriastradh get_drawable_deltas(dst->pDrawable, op->dst.pixmap, 216003b705cfSriastradh &op->dst.x, &op->dst.y); 216103b705cfSriastradh 216242542f5fSchristos DBG(("%s: pixmap=%ld, format=%08x, size=%dx%d, pitch=%d, delta=(%d,%d),damage=%p\n", 216303b705cfSriastradh __FUNCTION__, 216442542f5fSchristos op->dst.pixmap->drawable.serialNumber, (int)op->dst.format, 216503b705cfSriastradh op->dst.width, op->dst.height, 216603b705cfSriastradh op->dst.bo->pitch, 216703b705cfSriastradh op->dst.x, op->dst.y, 216803b705cfSriastradh op->damage ? *op->damage : (void *)-1)); 216903b705cfSriastradh 217003b705cfSriastradh assert(op->dst.bo->proxy == NULL); 217103b705cfSriastradh 217203b705cfSriastradh if (too_large(op->dst.width, op->dst.height) && 217303b705cfSriastradh !sna_render_composite_redirect(sna, op, x, y, w, h, partial)) 217403b705cfSriastradh return false; 217503b705cfSriastradh 217603b705cfSriastradh return true; 217703b705cfSriastradh} 217803b705cfSriastradh 217903b705cfSriastradhstatic bool 218003b705cfSriastradhtry_blt(struct sna *sna, 218103b705cfSriastradh PicturePtr dst, PicturePtr src, 218203b705cfSriastradh int width, int height) 218303b705cfSriastradh{ 218403b705cfSriastradh struct kgem_bo *bo; 218503b705cfSriastradh 218642542f5fSchristos if (sna->kgem.mode == KGEM_BLT) { 218703b705cfSriastradh DBG(("%s: already performing BLT\n", __FUNCTION__)); 218803b705cfSriastradh return true; 218903b705cfSriastradh } 219003b705cfSriastradh 219103b705cfSriastradh if (too_large(width, height)) { 219203b705cfSriastradh DBG(("%s: operation too large for 3D pipe (%d, %d)\n", 219303b705cfSriastradh __FUNCTION__, width, height)); 219403b705cfSriastradh return true; 219503b705cfSriastradh } 219603b705cfSriastradh 219742542f5fSchristos bo = __sna_drawable_peek_bo(dst->pDrawable); 219842542f5fSchristos if (bo == NULL) 219942542f5fSchristos return true; 220042542f5fSchristos if (bo->rq) 220142542f5fSchristos return RQ_IS_BLT(bo->rq); 220242542f5fSchristos 220342542f5fSchristos if (sna_picture_is_solid(src, NULL) && can_switch_to_blt(sna, bo, 0)) 220403b705cfSriastradh return true; 220503b705cfSriastradh 220642542f5fSchristos if (src->pDrawable) { 220742542f5fSchristos bo = __sna_drawable_peek_bo(src->pDrawable); 220842542f5fSchristos if (bo == NULL) 220942542f5fSchristos return true; 221042542f5fSchristos 221142542f5fSchristos if (prefer_blt_bo(sna, bo)) 221242542f5fSchristos return true; 221342542f5fSchristos } 221442542f5fSchristos 221542542f5fSchristos if (sna->kgem.ring == KGEM_BLT) { 221642542f5fSchristos DBG(("%s: already performing BLT\n", __FUNCTION__)); 221742542f5fSchristos return true; 221842542f5fSchristos } 221942542f5fSchristos 222003b705cfSriastradh return false; 222103b705cfSriastradh} 222203b705cfSriastradh 222303b705cfSriastradhstatic bool 222403b705cfSriastradhcheck_gradient(PicturePtr picture, bool precise) 222503b705cfSriastradh{ 222603b705cfSriastradh if (picture->pDrawable) 222703b705cfSriastradh return false; 222803b705cfSriastradh 222903b705cfSriastradh switch (picture->pSourcePict->type) { 223003b705cfSriastradh case SourcePictTypeSolidFill: 223103b705cfSriastradh case SourcePictTypeLinear: 223203b705cfSriastradh return false; 223303b705cfSriastradh default: 223403b705cfSriastradh return precise; 223503b705cfSriastradh } 223603b705cfSriastradh} 223703b705cfSriastradh 223803b705cfSriastradhstatic bool 223903b705cfSriastradhhas_alphamap(PicturePtr p) 224003b705cfSriastradh{ 224103b705cfSriastradh return p->alphaMap != NULL; 224203b705cfSriastradh} 224303b705cfSriastradh 224403b705cfSriastradhstatic bool 224503b705cfSriastradhneed_upload(PicturePtr p) 224603b705cfSriastradh{ 224703b705cfSriastradh return p->pDrawable && unattached(p->pDrawable) && untransformed(p); 224803b705cfSriastradh} 224903b705cfSriastradh 225003b705cfSriastradhstatic bool 225103b705cfSriastradhsource_is_busy(PixmapPtr pixmap) 225203b705cfSriastradh{ 225303b705cfSriastradh struct sna_pixmap *priv = sna_pixmap(pixmap); 225403b705cfSriastradh if (priv == NULL || priv->clear) 225503b705cfSriastradh return false; 225603b705cfSriastradh 225703b705cfSriastradh if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo)) 225803b705cfSriastradh return true; 225903b705cfSriastradh 226003b705cfSriastradh if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) 226103b705cfSriastradh return true; 226203b705cfSriastradh 226303b705cfSriastradh return priv->gpu_damage && !priv->cpu_damage; 226403b705cfSriastradh} 226503b705cfSriastradh 226603b705cfSriastradhstatic bool 226703b705cfSriastradhsource_fallback(PicturePtr p, PixmapPtr pixmap, bool precise) 226803b705cfSriastradh{ 226903b705cfSriastradh if (sna_picture_is_solid(p, NULL)) 227003b705cfSriastradh return false; 227103b705cfSriastradh 227203b705cfSriastradh if (p->pSourcePict) 227303b705cfSriastradh return check_gradient(p, precise); 227403b705cfSriastradh 227503b705cfSriastradh if (!gen7_check_repeat(p) || !gen7_check_format(p->format)) 227603b705cfSriastradh return true; 227703b705cfSriastradh 227803b705cfSriastradh if (pixmap && source_is_busy(pixmap)) 227903b705cfSriastradh return false; 228003b705cfSriastradh 228103b705cfSriastradh return has_alphamap(p) || !gen7_check_filter(p) || need_upload(p); 228203b705cfSriastradh} 228303b705cfSriastradh 228403b705cfSriastradhstatic bool 228503b705cfSriastradhgen7_composite_fallback(struct sna *sna, 228603b705cfSriastradh PicturePtr src, 228703b705cfSriastradh PicturePtr mask, 228803b705cfSriastradh PicturePtr dst) 228903b705cfSriastradh{ 229003b705cfSriastradh PixmapPtr src_pixmap; 229103b705cfSriastradh PixmapPtr mask_pixmap; 229203b705cfSriastradh PixmapPtr dst_pixmap; 229303b705cfSriastradh bool src_fallback, mask_fallback; 229403b705cfSriastradh 229503b705cfSriastradh if (!gen7_check_dst_format(dst->format)) { 229603b705cfSriastradh DBG(("%s: unknown destination format: %d\n", 229703b705cfSriastradh __FUNCTION__, dst->format)); 229803b705cfSriastradh return true; 229903b705cfSriastradh } 230003b705cfSriastradh 230103b705cfSriastradh dst_pixmap = get_drawable_pixmap(dst->pDrawable); 230203b705cfSriastradh 230303b705cfSriastradh src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL; 230403b705cfSriastradh src_fallback = source_fallback(src, src_pixmap, 230503b705cfSriastradh dst->polyMode == PolyModePrecise); 230603b705cfSriastradh 230703b705cfSriastradh if (mask) { 230803b705cfSriastradh mask_pixmap = mask->pDrawable ? get_drawable_pixmap(mask->pDrawable) : NULL; 230903b705cfSriastradh mask_fallback = source_fallback(mask, mask_pixmap, 231003b705cfSriastradh dst->polyMode == PolyModePrecise); 231103b705cfSriastradh } else { 231203b705cfSriastradh mask_pixmap = NULL; 231303b705cfSriastradh mask_fallback = false; 231403b705cfSriastradh } 231503b705cfSriastradh 231603b705cfSriastradh /* If we are using the destination as a source and need to 231703b705cfSriastradh * readback in order to upload the source, do it all 231803b705cfSriastradh * on the cpu. 231903b705cfSriastradh */ 232003b705cfSriastradh if (src_pixmap == dst_pixmap && src_fallback) { 232103b705cfSriastradh DBG(("%s: src is dst and will fallback\n",__FUNCTION__)); 232203b705cfSriastradh return true; 232303b705cfSriastradh } 232403b705cfSriastradh if (mask_pixmap == dst_pixmap && mask_fallback) { 232503b705cfSriastradh DBG(("%s: mask is dst and will fallback\n",__FUNCTION__)); 232603b705cfSriastradh return true; 232703b705cfSriastradh } 232803b705cfSriastradh 232903b705cfSriastradh /* If anything is on the GPU, push everything out to the GPU */ 233003b705cfSriastradh if (dst_use_gpu(dst_pixmap)) { 233103b705cfSriastradh DBG(("%s: dst is already on the GPU, try to use GPU\n", 233203b705cfSriastradh __FUNCTION__)); 233303b705cfSriastradh return false; 233403b705cfSriastradh } 233503b705cfSriastradh 233603b705cfSriastradh if (src_pixmap && !src_fallback) { 233703b705cfSriastradh DBG(("%s: src is already on the GPU, try to use GPU\n", 233803b705cfSriastradh __FUNCTION__)); 233903b705cfSriastradh return false; 234003b705cfSriastradh } 234103b705cfSriastradh if (mask_pixmap && !mask_fallback) { 234203b705cfSriastradh DBG(("%s: mask is already on the GPU, try to use GPU\n", 234303b705cfSriastradh __FUNCTION__)); 234403b705cfSriastradh return false; 234503b705cfSriastradh } 234603b705cfSriastradh 234703b705cfSriastradh /* However if the dst is not on the GPU and we need to 234803b705cfSriastradh * render one of the sources using the CPU, we may 234903b705cfSriastradh * as well do the entire operation in place onthe CPU. 235003b705cfSriastradh */ 235103b705cfSriastradh if (src_fallback) { 235203b705cfSriastradh DBG(("%s: dst is on the CPU and src will fallback\n", 235303b705cfSriastradh __FUNCTION__)); 235403b705cfSriastradh return true; 235503b705cfSriastradh } 235603b705cfSriastradh 235703b705cfSriastradh if (mask && mask_fallback) { 235803b705cfSriastradh DBG(("%s: dst is on the CPU and mask will fallback\n", 235903b705cfSriastradh __FUNCTION__)); 236003b705cfSriastradh return true; 236103b705cfSriastradh } 236203b705cfSriastradh 236303b705cfSriastradh if (too_large(dst_pixmap->drawable.width, 236403b705cfSriastradh dst_pixmap->drawable.height) && 236503b705cfSriastradh dst_is_cpu(dst_pixmap)) { 236603b705cfSriastradh DBG(("%s: dst is on the CPU and too large\n", __FUNCTION__)); 236703b705cfSriastradh return true; 236803b705cfSriastradh } 236903b705cfSriastradh 237003b705cfSriastradh DBG(("%s: dst is not on the GPU and the operation should not fallback\n", 237103b705cfSriastradh __FUNCTION__)); 237203b705cfSriastradh return dst_use_cpu(dst_pixmap); 237303b705cfSriastradh} 237403b705cfSriastradh 237503b705cfSriastradhstatic int 237603b705cfSriastradhreuse_source(struct sna *sna, 237703b705cfSriastradh PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y, 237803b705cfSriastradh PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y) 237903b705cfSriastradh{ 238003b705cfSriastradh uint32_t color; 238103b705cfSriastradh 238203b705cfSriastradh if (src_x != msk_x || src_y != msk_y) 238303b705cfSriastradh return false; 238403b705cfSriastradh 238503b705cfSriastradh if (src == mask) { 238603b705cfSriastradh DBG(("%s: mask is source\n", __FUNCTION__)); 238703b705cfSriastradh *mc = *sc; 238803b705cfSriastradh mc->bo = kgem_bo_reference(mc->bo); 238903b705cfSriastradh return true; 239003b705cfSriastradh } 239103b705cfSriastradh 239203b705cfSriastradh if (sna_picture_is_solid(mask, &color)) 239303b705cfSriastradh return gen4_channel_init_solid(sna, mc, color); 239403b705cfSriastradh 239503b705cfSriastradh if (sc->is_solid) 239603b705cfSriastradh return false; 239703b705cfSriastradh 239803b705cfSriastradh if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable) 239903b705cfSriastradh return false; 240003b705cfSriastradh 240103b705cfSriastradh DBG(("%s: mask reuses source drawable\n", __FUNCTION__)); 240203b705cfSriastradh 240303b705cfSriastradh if (!sna_transform_equal(src->transform, mask->transform)) 240403b705cfSriastradh return false; 240503b705cfSriastradh 240603b705cfSriastradh if (!sna_picture_alphamap_equal(src, mask)) 240703b705cfSriastradh return false; 240803b705cfSriastradh 240903b705cfSriastradh if (!gen7_check_repeat(mask)) 241003b705cfSriastradh return false; 241103b705cfSriastradh 241203b705cfSriastradh if (!gen7_check_filter(mask)) 241303b705cfSriastradh return false; 241403b705cfSriastradh 241503b705cfSriastradh if (!gen7_check_format(mask->format)) 241603b705cfSriastradh return false; 241703b705cfSriastradh 241803b705cfSriastradh DBG(("%s: reusing source channel for mask with a twist\n", 241903b705cfSriastradh __FUNCTION__)); 242003b705cfSriastradh 242103b705cfSriastradh *mc = *sc; 242203b705cfSriastradh mc->repeat = gen7_repeat(mask->repeat ? mask->repeatType : RepeatNone); 242303b705cfSriastradh mc->filter = gen7_filter(mask->filter); 242403b705cfSriastradh mc->pict_format = mask->format; 242503b705cfSriastradh mc->card_format = gen7_get_card_format(mask->format); 242603b705cfSriastradh mc->bo = kgem_bo_reference(mc->bo); 242703b705cfSriastradh return true; 242803b705cfSriastradh} 242903b705cfSriastradh 243003b705cfSriastradhstatic bool 243103b705cfSriastradhgen7_render_composite(struct sna *sna, 243203b705cfSriastradh uint8_t op, 243303b705cfSriastradh PicturePtr src, 243403b705cfSriastradh PicturePtr mask, 243503b705cfSriastradh PicturePtr dst, 243603b705cfSriastradh int16_t src_x, int16_t src_y, 243703b705cfSriastradh int16_t msk_x, int16_t msk_y, 243803b705cfSriastradh int16_t dst_x, int16_t dst_y, 243903b705cfSriastradh int16_t width, int16_t height, 244042542f5fSchristos unsigned flags, 244103b705cfSriastradh struct sna_composite_op *tmp) 244203b705cfSriastradh{ 244303b705cfSriastradh if (op >= ARRAY_SIZE(gen7_blend_op)) 244403b705cfSriastradh return false; 244503b705cfSriastradh 244603b705cfSriastradh DBG(("%s: %dx%d, current mode=%d/%d\n", __FUNCTION__, 244703b705cfSriastradh width, height, sna->kgem.mode, sna->kgem.ring)); 244803b705cfSriastradh 244903b705cfSriastradh if (mask == NULL && 245003b705cfSriastradh try_blt(sna, dst, src, width, height) && 245103b705cfSriastradh sna_blt_composite(sna, op, 245203b705cfSriastradh src, dst, 245303b705cfSriastradh src_x, src_y, 245403b705cfSriastradh dst_x, dst_y, 245503b705cfSriastradh width, height, 245642542f5fSchristos flags, tmp)) 245703b705cfSriastradh return true; 245803b705cfSriastradh 245903b705cfSriastradh if (gen7_composite_fallback(sna, src, mask, dst)) 246042542f5fSchristos goto fallback; 246103b705cfSriastradh 246203b705cfSriastradh if (need_tiling(sna, width, height)) 246303b705cfSriastradh return sna_tiling_composite(op, src, mask, dst, 246403b705cfSriastradh src_x, src_y, 246503b705cfSriastradh msk_x, msk_y, 246603b705cfSriastradh dst_x, dst_y, 246703b705cfSriastradh width, height, 246803b705cfSriastradh tmp); 246903b705cfSriastradh 247042542f5fSchristos if (op == PictOpClear && src == sna->clear) 247103b705cfSriastradh op = PictOpSrc; 247203b705cfSriastradh tmp->op = op; 247303b705cfSriastradh if (!gen7_composite_set_target(sna, tmp, dst, 247403b705cfSriastradh dst_x, dst_y, width, height, 247542542f5fSchristos flags & COMPOSITE_PARTIAL || op > PictOpSrc)) 247642542f5fSchristos goto fallback; 247703b705cfSriastradh 247803b705cfSriastradh switch (gen7_composite_picture(sna, src, &tmp->src, 247903b705cfSriastradh src_x, src_y, 248003b705cfSriastradh width, height, 248103b705cfSriastradh dst_x, dst_y, 248203b705cfSriastradh dst->polyMode == PolyModePrecise)) { 248303b705cfSriastradh case -1: 248403b705cfSriastradh goto cleanup_dst; 248503b705cfSriastradh case 0: 248603b705cfSriastradh if (!gen4_channel_init_solid(sna, &tmp->src, 0)) 248703b705cfSriastradh goto cleanup_dst; 248803b705cfSriastradh /* fall through to fixup */ 248903b705cfSriastradh case 1: 249003b705cfSriastradh /* Did we just switch rings to prepare the source? */ 249103b705cfSriastradh if (mask == NULL && 249203b705cfSriastradh prefer_blt_composite(sna, tmp) && 249303b705cfSriastradh sna_blt_composite__convert(sna, 249403b705cfSriastradh dst_x, dst_y, width, height, 249503b705cfSriastradh tmp)) 249603b705cfSriastradh return true; 249703b705cfSriastradh 249803b705cfSriastradh gen7_composite_channel_convert(&tmp->src); 249903b705cfSriastradh break; 250003b705cfSriastradh } 250103b705cfSriastradh 250203b705cfSriastradh tmp->is_affine = tmp->src.is_affine; 250303b705cfSriastradh tmp->has_component_alpha = false; 250403b705cfSriastradh tmp->need_magic_ca_pass = false; 250503b705cfSriastradh 250603b705cfSriastradh tmp->mask.bo = NULL; 250703b705cfSriastradh tmp->mask.filter = SAMPLER_FILTER_NEAREST; 250803b705cfSriastradh tmp->mask.repeat = SAMPLER_EXTEND_NONE; 250903b705cfSriastradh 251003b705cfSriastradh if (mask) { 251103b705cfSriastradh if (mask->componentAlpha && PICT_FORMAT_RGB(mask->format)) { 251203b705cfSriastradh tmp->has_component_alpha = true; 251303b705cfSriastradh 251403b705cfSriastradh /* Check if it's component alpha that relies on a source alpha and on 251503b705cfSriastradh * the source value. We can only get one of those into the single 251603b705cfSriastradh * source value that we get to blend with. 251703b705cfSriastradh */ 251803b705cfSriastradh if (gen7_blend_op[op].src_alpha && 251903b705cfSriastradh (gen7_blend_op[op].src_blend != GEN7_BLENDFACTOR_ZERO)) { 252003b705cfSriastradh if (op != PictOpOver) 252103b705cfSriastradh goto cleanup_src; 252203b705cfSriastradh 252303b705cfSriastradh tmp->need_magic_ca_pass = true; 252403b705cfSriastradh tmp->op = PictOpOutReverse; 252503b705cfSriastradh } 252603b705cfSriastradh } 252703b705cfSriastradh 252803b705cfSriastradh if (!reuse_source(sna, 252903b705cfSriastradh src, &tmp->src, src_x, src_y, 253003b705cfSriastradh mask, &tmp->mask, msk_x, msk_y)) { 253103b705cfSriastradh switch (gen7_composite_picture(sna, mask, &tmp->mask, 253203b705cfSriastradh msk_x, msk_y, 253303b705cfSriastradh width, height, 253403b705cfSriastradh dst_x, dst_y, 253503b705cfSriastradh dst->polyMode == PolyModePrecise)) { 253603b705cfSriastradh case -1: 253703b705cfSriastradh goto cleanup_src; 253803b705cfSriastradh case 0: 253903b705cfSriastradh if (!gen4_channel_init_solid(sna, &tmp->mask, 0)) 254003b705cfSriastradh goto cleanup_src; 254103b705cfSriastradh /* fall through to fixup */ 254203b705cfSriastradh case 1: 254303b705cfSriastradh gen7_composite_channel_convert(&tmp->mask); 254403b705cfSriastradh break; 254503b705cfSriastradh } 254603b705cfSriastradh } 254703b705cfSriastradh 254803b705cfSriastradh tmp->is_affine &= tmp->mask.is_affine; 254903b705cfSriastradh } 255003b705cfSriastradh 255103b705cfSriastradh tmp->u.gen7.flags = 255203b705cfSriastradh GEN7_SET_FLAGS(SAMPLER_OFFSET(tmp->src.filter, 255303b705cfSriastradh tmp->src.repeat, 255403b705cfSriastradh tmp->mask.filter, 255503b705cfSriastradh tmp->mask.repeat), 255603b705cfSriastradh gen7_get_blend(tmp->op, 255703b705cfSriastradh tmp->has_component_alpha, 255803b705cfSriastradh tmp->dst.format), 255903b705cfSriastradh gen7_choose_composite_kernel(tmp->op, 256003b705cfSriastradh tmp->mask.bo != NULL, 256103b705cfSriastradh tmp->has_component_alpha, 256203b705cfSriastradh tmp->is_affine), 256303b705cfSriastradh gen4_choose_composite_emitter(sna, tmp)); 256403b705cfSriastradh 256503b705cfSriastradh tmp->blt = gen7_render_composite_blt; 256603b705cfSriastradh tmp->box = gen7_render_composite_box; 256703b705cfSriastradh tmp->boxes = gen7_render_composite_boxes__blt; 256803b705cfSriastradh if (tmp->emit_boxes){ 256903b705cfSriastradh tmp->boxes = gen7_render_composite_boxes; 257003b705cfSriastradh tmp->thread_boxes = gen7_render_composite_boxes__thread; 257103b705cfSriastradh } 257203b705cfSriastradh tmp->done = gen7_render_composite_done; 257303b705cfSriastradh 257403b705cfSriastradh kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp->dst.bo); 257503b705cfSriastradh if (!kgem_check_bo(&sna->kgem, 257603b705cfSriastradh tmp->dst.bo, tmp->src.bo, tmp->mask.bo, 257703b705cfSriastradh NULL)) { 257803b705cfSriastradh kgem_submit(&sna->kgem); 257903b705cfSriastradh if (!kgem_check_bo(&sna->kgem, 258003b705cfSriastradh tmp->dst.bo, tmp->src.bo, tmp->mask.bo, 258103b705cfSriastradh NULL)) 258203b705cfSriastradh goto cleanup_mask; 258303b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 258403b705cfSriastradh } 258503b705cfSriastradh 258603b705cfSriastradh gen7_align_vertex(sna, tmp); 258742542f5fSchristos gen7_emit_composite_state(sna, tmp); 258803b705cfSriastradh return true; 258903b705cfSriastradh 259003b705cfSriastradhcleanup_mask: 259142542f5fSchristos if (tmp->mask.bo) { 259203b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->mask.bo); 259342542f5fSchristos tmp->mask.bo = NULL; 259442542f5fSchristos } 259503b705cfSriastradhcleanup_src: 259642542f5fSchristos if (tmp->src.bo) { 259703b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->src.bo); 259842542f5fSchristos tmp->src.bo = NULL; 259942542f5fSchristos } 260003b705cfSriastradhcleanup_dst: 260142542f5fSchristos if (tmp->redirect.real_bo) { 260203b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->dst.bo); 260342542f5fSchristos tmp->redirect.real_bo = NULL; 260442542f5fSchristos } 260542542f5fSchristosfallback: 260642542f5fSchristos return (mask == NULL && 260742542f5fSchristos sna_blt_composite(sna, op, 260842542f5fSchristos src, dst, 260942542f5fSchristos src_x, src_y, 261042542f5fSchristos dst_x, dst_y, 261142542f5fSchristos width, height, 261242542f5fSchristos flags | COMPOSITE_FALLBACK, tmp)); 261303b705cfSriastradh} 261403b705cfSriastradh 261503b705cfSriastradh#if !NO_COMPOSITE_SPANS 261603b705cfSriastradhfastcall static void 261703b705cfSriastradhgen7_render_composite_spans_box(struct sna *sna, 261803b705cfSriastradh const struct sna_composite_spans_op *op, 261903b705cfSriastradh const BoxRec *box, float opacity) 262003b705cfSriastradh{ 262103b705cfSriastradh DBG(("%s: src=+(%d, %d), opacity=%f, dst=+(%d, %d), box=(%d, %d) x (%d, %d)\n", 262203b705cfSriastradh __FUNCTION__, 262303b705cfSriastradh op->base.src.offset[0], op->base.src.offset[1], 262403b705cfSriastradh opacity, 262503b705cfSriastradh op->base.dst.x, op->base.dst.y, 262603b705cfSriastradh box->x1, box->y1, 262703b705cfSriastradh box->x2 - box->x1, 262803b705cfSriastradh box->y2 - box->y1)); 262903b705cfSriastradh 263003b705cfSriastradh gen7_get_rectangles(sna, &op->base, 1, gen7_emit_composite_state); 263103b705cfSriastradh op->prim_emit(sna, op, box, opacity); 263203b705cfSriastradh} 263303b705cfSriastradh 263403b705cfSriastradhstatic void 263503b705cfSriastradhgen7_render_composite_spans_boxes(struct sna *sna, 263603b705cfSriastradh const struct sna_composite_spans_op *op, 263703b705cfSriastradh const BoxRec *box, int nbox, 263803b705cfSriastradh float opacity) 263903b705cfSriastradh{ 264003b705cfSriastradh DBG(("%s: nbox=%d, src=+(%d, %d), opacity=%f, dst=+(%d, %d)\n", 264103b705cfSriastradh __FUNCTION__, nbox, 264203b705cfSriastradh op->base.src.offset[0], op->base.src.offset[1], 264303b705cfSriastradh opacity, 264403b705cfSriastradh op->base.dst.x, op->base.dst.y)); 264503b705cfSriastradh 264603b705cfSriastradh do { 264703b705cfSriastradh int nbox_this_time; 264803b705cfSriastradh 264903b705cfSriastradh nbox_this_time = gen7_get_rectangles(sna, &op->base, nbox, 265003b705cfSriastradh gen7_emit_composite_state); 265103b705cfSriastradh nbox -= nbox_this_time; 265203b705cfSriastradh 265303b705cfSriastradh do { 265403b705cfSriastradh DBG((" %s: (%d, %d) x (%d, %d)\n", __FUNCTION__, 265503b705cfSriastradh box->x1, box->y1, 265603b705cfSriastradh box->x2 - box->x1, 265703b705cfSriastradh box->y2 - box->y1)); 265803b705cfSriastradh 265903b705cfSriastradh op->prim_emit(sna, op, box++, opacity); 266003b705cfSriastradh } while (--nbox_this_time); 266103b705cfSriastradh } while (nbox); 266203b705cfSriastradh} 266303b705cfSriastradh 266403b705cfSriastradhfastcall static void 266503b705cfSriastradhgen7_render_composite_spans_boxes__thread(struct sna *sna, 266603b705cfSriastradh const struct sna_composite_spans_op *op, 266703b705cfSriastradh const struct sna_opacity_box *box, 266803b705cfSriastradh int nbox) 266903b705cfSriastradh{ 267003b705cfSriastradh DBG(("%s: nbox=%d, src=+(%d, %d), dst=+(%d, %d)\n", 267103b705cfSriastradh __FUNCTION__, nbox, 267203b705cfSriastradh op->base.src.offset[0], op->base.src.offset[1], 267303b705cfSriastradh op->base.dst.x, op->base.dst.y)); 267403b705cfSriastradh 267503b705cfSriastradh sna_vertex_lock(&sna->render); 267603b705cfSriastradh do { 267703b705cfSriastradh int nbox_this_time; 267803b705cfSriastradh float *v; 267903b705cfSriastradh 268003b705cfSriastradh nbox_this_time = gen7_get_rectangles(sna, &op->base, nbox, 268103b705cfSriastradh gen7_emit_composite_state); 268203b705cfSriastradh assert(nbox_this_time); 268303b705cfSriastradh nbox -= nbox_this_time; 268403b705cfSriastradh 268503b705cfSriastradh v = sna->render.vertices + sna->render.vertex_used; 268603b705cfSriastradh sna->render.vertex_used += nbox_this_time * op->base.floats_per_rect; 268703b705cfSriastradh 268803b705cfSriastradh sna_vertex_acquire__locked(&sna->render); 268903b705cfSriastradh sna_vertex_unlock(&sna->render); 269003b705cfSriastradh 269103b705cfSriastradh op->emit_boxes(op, box, nbox_this_time, v); 269203b705cfSriastradh box += nbox_this_time; 269303b705cfSriastradh 269403b705cfSriastradh sna_vertex_lock(&sna->render); 269503b705cfSriastradh sna_vertex_release__locked(&sna->render); 269603b705cfSriastradh } while (nbox); 269703b705cfSriastradh sna_vertex_unlock(&sna->render); 269803b705cfSriastradh} 269903b705cfSriastradh 270003b705cfSriastradhfastcall static void 270103b705cfSriastradhgen7_render_composite_spans_done(struct sna *sna, 270203b705cfSriastradh const struct sna_composite_spans_op *op) 270303b705cfSriastradh{ 270403b705cfSriastradh if (sna->render.vertex_offset) 270503b705cfSriastradh gen4_vertex_flush(sna); 270603b705cfSriastradh 270703b705cfSriastradh DBG(("%s()\n", __FUNCTION__)); 270803b705cfSriastradh 270903b705cfSriastradh if (op->base.src.bo) 271003b705cfSriastradh kgem_bo_destroy(&sna->kgem, op->base.src.bo); 271103b705cfSriastradh 271203b705cfSriastradh sna_render_composite_redirect_done(sna, &op->base); 271303b705cfSriastradh} 271403b705cfSriastradh 271503b705cfSriastradhstatic bool 271603b705cfSriastradhgen7_check_composite_spans(struct sna *sna, 271703b705cfSriastradh uint8_t op, PicturePtr src, PicturePtr dst, 271803b705cfSriastradh int16_t width, int16_t height, unsigned flags) 271903b705cfSriastradh{ 272003b705cfSriastradh if (op >= ARRAY_SIZE(gen7_blend_op)) 272103b705cfSriastradh return false; 272203b705cfSriastradh 272303b705cfSriastradh if (gen7_composite_fallback(sna, src, NULL, dst)) 272403b705cfSriastradh return false; 272503b705cfSriastradh 272603b705cfSriastradh if (need_tiling(sna, width, height) && 272703b705cfSriastradh !is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) { 272803b705cfSriastradh DBG(("%s: fallback, tiled operation not on GPU\n", 272903b705cfSriastradh __FUNCTION__)); 273003b705cfSriastradh return false; 273103b705cfSriastradh } 273203b705cfSriastradh 273303b705cfSriastradh return true; 273403b705cfSriastradh} 273503b705cfSriastradh 273603b705cfSriastradhstatic bool 273703b705cfSriastradhgen7_render_composite_spans(struct sna *sna, 273803b705cfSriastradh uint8_t op, 273903b705cfSriastradh PicturePtr src, 274003b705cfSriastradh PicturePtr dst, 274103b705cfSriastradh int16_t src_x, int16_t src_y, 274203b705cfSriastradh int16_t dst_x, int16_t dst_y, 274303b705cfSriastradh int16_t width, int16_t height, 274403b705cfSriastradh unsigned flags, 274503b705cfSriastradh struct sna_composite_spans_op *tmp) 274603b705cfSriastradh{ 274703b705cfSriastradh DBG(("%s: %dx%d with flags=%x, current mode=%d/%d\n", __FUNCTION__, 274803b705cfSriastradh width, height, flags, sna->kgem.mode, sna->kgem.ring)); 274903b705cfSriastradh 275003b705cfSriastradh assert(gen7_check_composite_spans(sna, op, src, dst, width, height, flags)); 275103b705cfSriastradh 275203b705cfSriastradh if (need_tiling(sna, width, height)) { 275303b705cfSriastradh DBG(("%s: tiling, operation (%dx%d) too wide for pipeline\n", 275403b705cfSriastradh __FUNCTION__, width, height)); 275503b705cfSriastradh return sna_tiling_composite_spans(op, src, dst, 275603b705cfSriastradh src_x, src_y, dst_x, dst_y, 275703b705cfSriastradh width, height, flags, tmp); 275803b705cfSriastradh } 275903b705cfSriastradh 276003b705cfSriastradh tmp->base.op = op; 276103b705cfSriastradh if (!gen7_composite_set_target(sna, &tmp->base, dst, 276203b705cfSriastradh dst_x, dst_y, width, height, true)) 276303b705cfSriastradh return false; 276403b705cfSriastradh 276503b705cfSriastradh switch (gen7_composite_picture(sna, src, &tmp->base.src, 276603b705cfSriastradh src_x, src_y, 276703b705cfSriastradh width, height, 276803b705cfSriastradh dst_x, dst_y, 276903b705cfSriastradh dst->polyMode == PolyModePrecise)) { 277003b705cfSriastradh case -1: 277103b705cfSriastradh goto cleanup_dst; 277203b705cfSriastradh case 0: 277303b705cfSriastradh if (!gen4_channel_init_solid(sna, &tmp->base.src, 0)) 277403b705cfSriastradh goto cleanup_dst; 277503b705cfSriastradh /* fall through to fixup */ 277603b705cfSriastradh case 1: 277703b705cfSriastradh gen7_composite_channel_convert(&tmp->base.src); 277803b705cfSriastradh break; 277903b705cfSriastradh } 278003b705cfSriastradh tmp->base.mask.bo = NULL; 278103b705cfSriastradh 278203b705cfSriastradh tmp->base.is_affine = tmp->base.src.is_affine; 278303b705cfSriastradh tmp->base.need_magic_ca_pass = false; 278403b705cfSriastradh 278503b705cfSriastradh tmp->base.u.gen7.flags = 278603b705cfSriastradh GEN7_SET_FLAGS(SAMPLER_OFFSET(tmp->base.src.filter, 278703b705cfSriastradh tmp->base.src.repeat, 278803b705cfSriastradh SAMPLER_FILTER_NEAREST, 278903b705cfSriastradh SAMPLER_EXTEND_PAD), 279003b705cfSriastradh gen7_get_blend(tmp->base.op, false, tmp->base.dst.format), 279103b705cfSriastradh GEN7_WM_KERNEL_OPACITY | !tmp->base.is_affine, 279203b705cfSriastradh gen4_choose_spans_emitter(sna, tmp)); 279303b705cfSriastradh 279403b705cfSriastradh tmp->box = gen7_render_composite_spans_box; 279503b705cfSriastradh tmp->boxes = gen7_render_composite_spans_boxes; 279603b705cfSriastradh if (tmp->emit_boxes) 279703b705cfSriastradh tmp->thread_boxes = gen7_render_composite_spans_boxes__thread; 279803b705cfSriastradh tmp->done = gen7_render_composite_spans_done; 279903b705cfSriastradh 280003b705cfSriastradh kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp->base.dst.bo); 280103b705cfSriastradh if (!kgem_check_bo(&sna->kgem, 280203b705cfSriastradh tmp->base.dst.bo, tmp->base.src.bo, 280303b705cfSriastradh NULL)) { 280403b705cfSriastradh kgem_submit(&sna->kgem); 280503b705cfSriastradh if (!kgem_check_bo(&sna->kgem, 280603b705cfSriastradh tmp->base.dst.bo, tmp->base.src.bo, 280703b705cfSriastradh NULL)) 280803b705cfSriastradh goto cleanup_src; 280903b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 281003b705cfSriastradh } 281103b705cfSriastradh 281203b705cfSriastradh gen7_align_vertex(sna, &tmp->base); 281342542f5fSchristos gen7_emit_composite_state(sna, &tmp->base); 281403b705cfSriastradh return true; 281503b705cfSriastradh 281603b705cfSriastradhcleanup_src: 281703b705cfSriastradh if (tmp->base.src.bo) 281803b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->base.src.bo); 281903b705cfSriastradhcleanup_dst: 282003b705cfSriastradh if (tmp->base.redirect.real_bo) 282103b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->base.dst.bo); 282203b705cfSriastradh return false; 282303b705cfSriastradh} 282403b705cfSriastradh#endif 282503b705cfSriastradh 282603b705cfSriastradhstatic void 282703b705cfSriastradhgen7_emit_copy_state(struct sna *sna, 282803b705cfSriastradh const struct sna_composite_op *op) 282903b705cfSriastradh{ 283003b705cfSriastradh uint32_t *binding_table; 283142542f5fSchristos uint16_t offset, dirty; 283203b705cfSriastradh 283303b705cfSriastradh gen7_get_batch(sna, op); 283403b705cfSriastradh 283503b705cfSriastradh binding_table = gen7_composite_get_binding_table(sna, &offset); 283603b705cfSriastradh 283742542f5fSchristos dirty = kgem_bo_is_dirty(op->dst.bo); 283842542f5fSchristos 283903b705cfSriastradh binding_table[0] = 284003b705cfSriastradh gen7_bind_bo(sna, 284103b705cfSriastradh op->dst.bo, op->dst.width, op->dst.height, 284203b705cfSriastradh gen7_get_dest_format(op->dst.format), 284303b705cfSriastradh true); 284403b705cfSriastradh binding_table[1] = 284503b705cfSriastradh gen7_bind_bo(sna, 284603b705cfSriastradh op->src.bo, op->src.width, op->src.height, 284703b705cfSriastradh op->src.card_format, 284803b705cfSriastradh false); 284903b705cfSriastradh 285003b705cfSriastradh if (sna->kgem.surface == offset && 285103b705cfSriastradh *(uint64_t *)(sna->kgem.batch + sna->render_state.gen7.surface_table) == *(uint64_t*)binding_table) { 285203b705cfSriastradh sna->kgem.surface += sizeof(struct gen7_surface_state) / sizeof(uint32_t); 285303b705cfSriastradh offset = sna->render_state.gen7.surface_table; 285403b705cfSriastradh } 285503b705cfSriastradh 285642542f5fSchristos if (sna->kgem.batch[sna->render_state.gen7.surface_table] == binding_table[0]) 285742542f5fSchristos dirty = 0; 285842542f5fSchristos 285903b705cfSriastradh assert(!GEN7_READS_DST(op->u.gen7.flags)); 286042542f5fSchristos gen7_emit_state(sna, op, offset | dirty); 286103b705cfSriastradh} 286203b705cfSriastradh 286342542f5fSchristosstatic inline bool 286442542f5fSchristosprefer_blt_copy(struct sna *sna, 286542542f5fSchristos struct kgem_bo *src_bo, 286642542f5fSchristos struct kgem_bo *dst_bo, 286742542f5fSchristos unsigned flags) 286803b705cfSriastradh{ 286903b705cfSriastradh if (sna->kgem.mode == KGEM_BLT) 287003b705cfSriastradh return true; 287103b705cfSriastradh 287203b705cfSriastradh assert((flags & COPY_SYNC) == 0); 287303b705cfSriastradh 287403b705cfSriastradh if (src_bo == dst_bo && can_switch_to_blt(sna, dst_bo, flags)) 287503b705cfSriastradh return true; 287603b705cfSriastradh 287703b705cfSriastradh if (untiled_tlb_miss(src_bo) || 287803b705cfSriastradh untiled_tlb_miss(dst_bo)) 287903b705cfSriastradh return true; 288003b705cfSriastradh 288142542f5fSchristos if (force_blt_ring(sna)) 288242542f5fSchristos return true; 288342542f5fSchristos 288403b705cfSriastradh if (kgem_bo_is_render(dst_bo) || 288503b705cfSriastradh kgem_bo_is_render(src_bo)) 288603b705cfSriastradh return false; 288703b705cfSriastradh 288842542f5fSchristos if (prefer_render_ring(sna, dst_bo)) 288903b705cfSriastradh return false; 289003b705cfSriastradh 289142542f5fSchristos if (!prefer_blt_ring(sna, dst_bo, flags)) 289203b705cfSriastradh return false; 289303b705cfSriastradh 289442542f5fSchristos return prefer_blt_bo(sna, src_bo) || prefer_blt_bo(sna, dst_bo); 289503b705cfSriastradh} 289603b705cfSriastradh 289703b705cfSriastradhstatic bool 289803b705cfSriastradhgen7_render_copy_boxes(struct sna *sna, uint8_t alu, 289942542f5fSchristos const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, 290042542f5fSchristos const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, 290103b705cfSriastradh const BoxRec *box, int n, unsigned flags) 290203b705cfSriastradh{ 290303b705cfSriastradh struct sna_composite_op tmp; 290403b705cfSriastradh BoxRec extents; 290503b705cfSriastradh 290603b705cfSriastradh DBG(("%s (%d, %d)->(%d, %d) x %d, alu=%x, flags=%x, self-copy=%d, overlaps? %d\n", 290703b705cfSriastradh __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n, alu, flags, 290803b705cfSriastradh src_bo == dst_bo, 290903b705cfSriastradh overlaps(sna, 291003b705cfSriastradh src_bo, src_dx, src_dy, 291103b705cfSriastradh dst_bo, dst_dx, dst_dy, 291242542f5fSchristos box, n, flags, &extents))); 291303b705cfSriastradh 291403b705cfSriastradh if (prefer_blt_copy(sna, src_bo, dst_bo, flags) && 291542542f5fSchristos sna_blt_compare_depth(src, dst) && 291603b705cfSriastradh sna_blt_copy_boxes(sna, alu, 291703b705cfSriastradh src_bo, src_dx, src_dy, 291803b705cfSriastradh dst_bo, dst_dx, dst_dy, 291942542f5fSchristos dst->bitsPerPixel, 292003b705cfSriastradh box, n)) 292103b705cfSriastradh return true; 292203b705cfSriastradh 292303b705cfSriastradh if (!(alu == GXcopy || alu == GXclear)) { 292403b705cfSriastradhfallback_blt: 292542542f5fSchristos DBG(("%s: fallback blt\n", __FUNCTION__)); 292642542f5fSchristos if (!sna_blt_compare_depth(src, dst)) 292703b705cfSriastradh return false; 292803b705cfSriastradh 292903b705cfSriastradh return sna_blt_copy_boxes_fallback(sna, alu, 293003b705cfSriastradh src, src_bo, src_dx, src_dy, 293103b705cfSriastradh dst, dst_bo, dst_dx, dst_dy, 293203b705cfSriastradh box, n); 293303b705cfSriastradh } 293403b705cfSriastradh 293503b705cfSriastradh if (overlaps(sna, 293603b705cfSriastradh src_bo, src_dx, src_dy, 293703b705cfSriastradh dst_bo, dst_dx, dst_dy, 293842542f5fSchristos box, n, flags, 293942542f5fSchristos &extents)) { 294042542f5fSchristos bool big = too_large(extents.x2-extents.x1, extents.y2-extents.y1); 294103b705cfSriastradh 294242542f5fSchristos if ((big || can_switch_to_blt(sna, dst_bo, flags)) && 294303b705cfSriastradh sna_blt_copy_boxes(sna, alu, 294403b705cfSriastradh src_bo, src_dx, src_dy, 294503b705cfSriastradh dst_bo, dst_dx, dst_dy, 294642542f5fSchristos dst->bitsPerPixel, 294703b705cfSriastradh box, n)) 294803b705cfSriastradh return true; 294903b705cfSriastradh 295042542f5fSchristos if (big) 295142542f5fSchristos goto fallback_blt; 295242542f5fSchristos 295342542f5fSchristos assert(src_bo == dst_bo); 295442542f5fSchristos assert(src->depth == dst->depth); 295542542f5fSchristos assert(src->width == dst->width); 295642542f5fSchristos assert(src->height == dst->height); 295703b705cfSriastradh return sna_render_copy_boxes__overlap(sna, alu, 295842542f5fSchristos src, src_bo, 295942542f5fSchristos src_dx, src_dy, 296042542f5fSchristos dst_dx, dst_dy, 296103b705cfSriastradh box, n, &extents); 296203b705cfSriastradh } 296303b705cfSriastradh 296442542f5fSchristos if (dst->depth == src->depth) { 296542542f5fSchristos tmp.dst.format = sna_render_format_for_depth(dst->depth); 296603b705cfSriastradh tmp.src.pict_format = tmp.dst.format; 296703b705cfSriastradh } else { 296842542f5fSchristos tmp.dst.format = sna_format_for_depth(dst->depth); 296942542f5fSchristos tmp.src.pict_format = sna_format_for_depth(src->depth); 297003b705cfSriastradh } 297103b705cfSriastradh if (!gen7_check_format(tmp.src.pict_format)) 297203b705cfSriastradh goto fallback_blt; 297303b705cfSriastradh 297442542f5fSchristos tmp.dst.pixmap = (PixmapPtr)dst; 297542542f5fSchristos tmp.dst.width = dst->width; 297642542f5fSchristos tmp.dst.height = dst->height; 297703b705cfSriastradh tmp.dst.bo = dst_bo; 297803b705cfSriastradh tmp.dst.x = tmp.dst.y = 0; 297903b705cfSriastradh tmp.damage = NULL; 298003b705cfSriastradh 298103b705cfSriastradh sna_render_composite_redirect_init(&tmp); 298203b705cfSriastradh if (too_large(tmp.dst.width, tmp.dst.height)) { 298303b705cfSriastradh int i; 298403b705cfSriastradh 298503b705cfSriastradh extents = box[0]; 298603b705cfSriastradh for (i = 1; i < n; i++) { 298703b705cfSriastradh if (box[i].x1 < extents.x1) 298803b705cfSriastradh extents.x1 = box[i].x1; 298903b705cfSriastradh if (box[i].y1 < extents.y1) 299003b705cfSriastradh extents.y1 = box[i].y1; 299103b705cfSriastradh 299203b705cfSriastradh if (box[i].x2 > extents.x2) 299303b705cfSriastradh extents.x2 = box[i].x2; 299403b705cfSriastradh if (box[i].y2 > extents.y2) 299503b705cfSriastradh extents.y2 = box[i].y2; 299603b705cfSriastradh } 299703b705cfSriastradh 299803b705cfSriastradh if (!sna_render_composite_redirect(sna, &tmp, 299903b705cfSriastradh extents.x1 + dst_dx, 300003b705cfSriastradh extents.y1 + dst_dy, 300103b705cfSriastradh extents.x2 - extents.x1, 300203b705cfSriastradh extents.y2 - extents.y1, 300303b705cfSriastradh n > 1)) 300403b705cfSriastradh goto fallback_tiled; 300503b705cfSriastradh } 300603b705cfSriastradh 300703b705cfSriastradh tmp.src.card_format = gen7_get_card_format(tmp.src.pict_format); 300842542f5fSchristos if (too_large(src->width, src->height)) { 300903b705cfSriastradh int i; 301003b705cfSriastradh 301103b705cfSriastradh extents = box[0]; 301203b705cfSriastradh for (i = 1; i < n; i++) { 301303b705cfSriastradh if (box[i].x1 < extents.x1) 301403b705cfSriastradh extents.x1 = box[i].x1; 301503b705cfSriastradh if (box[i].y1 < extents.y1) 301603b705cfSriastradh extents.y1 = box[i].y1; 301703b705cfSriastradh 301803b705cfSriastradh if (box[i].x2 > extents.x2) 301903b705cfSriastradh extents.x2 = box[i].x2; 302003b705cfSriastradh if (box[i].y2 > extents.y2) 302103b705cfSriastradh extents.y2 = box[i].y2; 302203b705cfSriastradh } 302303b705cfSriastradh 302403b705cfSriastradh if (!sna_render_pixmap_partial(sna, src, src_bo, &tmp.src, 302503b705cfSriastradh extents.x1 + src_dx, 302603b705cfSriastradh extents.y1 + src_dy, 302703b705cfSriastradh extents.x2 - extents.x1, 302803b705cfSriastradh extents.y2 - extents.y1)) 302903b705cfSriastradh goto fallback_tiled_dst; 303003b705cfSriastradh } else { 303103b705cfSriastradh tmp.src.bo = src_bo; 303242542f5fSchristos tmp.src.width = src->width; 303342542f5fSchristos tmp.src.height = src->height; 303442542f5fSchristos tmp.src.offset[0] = tmp.src.offset[1] = 0; 303503b705cfSriastradh } 303603b705cfSriastradh 303703b705cfSriastradh tmp.mask.bo = NULL; 303803b705cfSriastradh 303903b705cfSriastradh tmp.floats_per_vertex = 2; 304003b705cfSriastradh tmp.floats_per_rect = 6; 304103b705cfSriastradh tmp.need_magic_ca_pass = 0; 304203b705cfSriastradh 304303b705cfSriastradh tmp.u.gen7.flags = COPY_FLAGS(alu); 304403b705cfSriastradh 304503b705cfSriastradh kgem_set_mode(&sna->kgem, KGEM_RENDER, tmp.dst.bo); 304603b705cfSriastradh if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, tmp.src.bo, NULL)) { 304703b705cfSriastradh kgem_submit(&sna->kgem); 304842542f5fSchristos if (!kgem_check_bo(&sna->kgem, tmp.dst.bo, tmp.src.bo, NULL)) { 304942542f5fSchristos if (tmp.src.bo != src_bo) 305042542f5fSchristos kgem_bo_destroy(&sna->kgem, tmp.src.bo); 305142542f5fSchristos if (tmp.redirect.real_bo) 305242542f5fSchristos kgem_bo_destroy(&sna->kgem, tmp.dst.bo); 305342542f5fSchristos goto fallback_blt; 305442542f5fSchristos } 305503b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 305603b705cfSriastradh } 305703b705cfSriastradh 305842542f5fSchristos src_dx += tmp.src.offset[0]; 305942542f5fSchristos src_dy += tmp.src.offset[1]; 306042542f5fSchristos 306142542f5fSchristos dst_dx += tmp.dst.x; 306242542f5fSchristos dst_dy += tmp.dst.y; 306342542f5fSchristos 306442542f5fSchristos tmp.dst.x = tmp.dst.y = 0; 306542542f5fSchristos 306603b705cfSriastradh gen7_align_vertex(sna, &tmp); 306742542f5fSchristos gen7_emit_copy_state(sna, &tmp); 306803b705cfSriastradh 306903b705cfSriastradh do { 307003b705cfSriastradh int16_t *v; 307103b705cfSriastradh int n_this_time; 307203b705cfSriastradh 307303b705cfSriastradh n_this_time = gen7_get_rectangles(sna, &tmp, n, 307403b705cfSriastradh gen7_emit_copy_state); 307503b705cfSriastradh n -= n_this_time; 307603b705cfSriastradh 307703b705cfSriastradh v = (int16_t *)(sna->render.vertices + sna->render.vertex_used); 307803b705cfSriastradh sna->render.vertex_used += 6 * n_this_time; 307903b705cfSriastradh assert(sna->render.vertex_used <= sna->render.vertex_size); 308003b705cfSriastradh do { 308103b705cfSriastradh 308203b705cfSriastradh DBG((" (%d, %d) -> (%d, %d) + (%d, %d)\n", 308303b705cfSriastradh box->x1 + src_dx, box->y1 + src_dy, 308403b705cfSriastradh box->x1 + dst_dx, box->y1 + dst_dy, 308503b705cfSriastradh box->x2 - box->x1, box->y2 - box->y1)); 308603b705cfSriastradh v[0] = box->x2 + dst_dx; 308703b705cfSriastradh v[2] = box->x2 + src_dx; 308803b705cfSriastradh v[1] = v[5] = box->y2 + dst_dy; 308903b705cfSriastradh v[3] = v[7] = box->y2 + src_dy; 309003b705cfSriastradh v[8] = v[4] = box->x1 + dst_dx; 309103b705cfSriastradh v[10] = v[6] = box->x1 + src_dx; 309203b705cfSriastradh v[9] = box->y1 + dst_dy; 309303b705cfSriastradh v[11] = box->y1 + src_dy; 309403b705cfSriastradh v += 12; box++; 309503b705cfSriastradh } while (--n_this_time); 309603b705cfSriastradh } while (n); 309703b705cfSriastradh 309803b705cfSriastradh gen4_vertex_flush(sna); 309903b705cfSriastradh sna_render_composite_redirect_done(sna, &tmp); 310003b705cfSriastradh if (tmp.src.bo != src_bo) 310103b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp.src.bo); 310203b705cfSriastradh return true; 310303b705cfSriastradh 310403b705cfSriastradhfallback_tiled_dst: 310503b705cfSriastradh if (tmp.redirect.real_bo) 310603b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp.dst.bo); 310703b705cfSriastradhfallback_tiled: 310842542f5fSchristos DBG(("%s: fallback tiled\n", __FUNCTION__)); 310942542f5fSchristos if (sna_blt_compare_depth(src, dst) && 311003b705cfSriastradh sna_blt_copy_boxes(sna, alu, 311103b705cfSriastradh src_bo, src_dx, src_dy, 311203b705cfSriastradh dst_bo, dst_dx, dst_dy, 311342542f5fSchristos dst->bitsPerPixel, 311403b705cfSriastradh box, n)) 311503b705cfSriastradh return true; 311603b705cfSriastradh 311703b705cfSriastradh return sna_tiling_copy_boxes(sna, alu, 311803b705cfSriastradh src, src_bo, src_dx, src_dy, 311903b705cfSriastradh dst, dst_bo, dst_dx, dst_dy, 312003b705cfSriastradh box, n); 312103b705cfSriastradh} 312203b705cfSriastradh 312303b705cfSriastradhstatic void 312403b705cfSriastradhgen7_render_copy_blt(struct sna *sna, 312503b705cfSriastradh const struct sna_copy_op *op, 312603b705cfSriastradh int16_t sx, int16_t sy, 312703b705cfSriastradh int16_t w, int16_t h, 312803b705cfSriastradh int16_t dx, int16_t dy) 312903b705cfSriastradh{ 313003b705cfSriastradh int16_t *v; 313103b705cfSriastradh 313203b705cfSriastradh gen7_get_rectangles(sna, &op->base, 1, gen7_emit_copy_state); 313303b705cfSriastradh 313403b705cfSriastradh v = (int16_t *)&sna->render.vertices[sna->render.vertex_used]; 313503b705cfSriastradh sna->render.vertex_used += 6; 313603b705cfSriastradh assert(sna->render.vertex_used <= sna->render.vertex_size); 313703b705cfSriastradh 313803b705cfSriastradh v[0] = dx+w; v[1] = dy+h; 313903b705cfSriastradh v[2] = sx+w; v[3] = sy+h; 314003b705cfSriastradh v[4] = dx; v[5] = dy+h; 314103b705cfSriastradh v[6] = sx; v[7] = sy+h; 314203b705cfSriastradh v[8] = dx; v[9] = dy; 314303b705cfSriastradh v[10] = sx; v[11] = sy; 314403b705cfSriastradh} 314503b705cfSriastradh 314603b705cfSriastradhstatic void 314703b705cfSriastradhgen7_render_copy_done(struct sna *sna, const struct sna_copy_op *op) 314803b705cfSriastradh{ 314903b705cfSriastradh if (sna->render.vertex_offset) 315003b705cfSriastradh gen4_vertex_flush(sna); 315103b705cfSriastradh} 315203b705cfSriastradh 315303b705cfSriastradhstatic bool 315403b705cfSriastradhgen7_render_copy(struct sna *sna, uint8_t alu, 315503b705cfSriastradh PixmapPtr src, struct kgem_bo *src_bo, 315603b705cfSriastradh PixmapPtr dst, struct kgem_bo *dst_bo, 315703b705cfSriastradh struct sna_copy_op *op) 315803b705cfSriastradh{ 315903b705cfSriastradh DBG(("%s (alu=%d, src=(%dx%d), dst=(%dx%d))\n", 316003b705cfSriastradh __FUNCTION__, alu, 316103b705cfSriastradh src->drawable.width, src->drawable.height, 316203b705cfSriastradh dst->drawable.width, dst->drawable.height)); 316303b705cfSriastradh 316403b705cfSriastradh if (prefer_blt_copy(sna, src_bo, dst_bo, 0) && 316503b705cfSriastradh sna_blt_compare_depth(&src->drawable, &dst->drawable) && 316603b705cfSriastradh sna_blt_copy(sna, alu, 316703b705cfSriastradh src_bo, dst_bo, 316803b705cfSriastradh dst->drawable.bitsPerPixel, 316903b705cfSriastradh op)) 317003b705cfSriastradh return true; 317103b705cfSriastradh 317203b705cfSriastradh if (!(alu == GXcopy || alu == GXclear) || src_bo == dst_bo || 317303b705cfSriastradh too_large(src->drawable.width, src->drawable.height) || 317403b705cfSriastradh too_large(dst->drawable.width, dst->drawable.height)) { 317503b705cfSriastradhfallback: 317603b705cfSriastradh if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) 317703b705cfSriastradh return false; 317803b705cfSriastradh 317903b705cfSriastradh return sna_blt_copy(sna, alu, src_bo, dst_bo, 318003b705cfSriastradh dst->drawable.bitsPerPixel, 318103b705cfSriastradh op); 318203b705cfSriastradh } 318303b705cfSriastradh 318403b705cfSriastradh if (dst->drawable.depth == src->drawable.depth) { 318503b705cfSriastradh op->base.dst.format = sna_render_format_for_depth(dst->drawable.depth); 318603b705cfSriastradh op->base.src.pict_format = op->base.dst.format; 318703b705cfSriastradh } else { 318803b705cfSriastradh op->base.dst.format = sna_format_for_depth(dst->drawable.depth); 318903b705cfSriastradh op->base.src.pict_format = sna_format_for_depth(src->drawable.depth); 319003b705cfSriastradh } 319103b705cfSriastradh if (!gen7_check_format(op->base.src.pict_format)) 319203b705cfSriastradh goto fallback; 319303b705cfSriastradh 319403b705cfSriastradh op->base.dst.pixmap = dst; 319503b705cfSriastradh op->base.dst.width = dst->drawable.width; 319603b705cfSriastradh op->base.dst.height = dst->drawable.height; 319703b705cfSriastradh op->base.dst.bo = dst_bo; 319803b705cfSriastradh 319903b705cfSriastradh op->base.src.bo = src_bo; 320003b705cfSriastradh op->base.src.card_format = 320103b705cfSriastradh gen7_get_card_format(op->base.src.pict_format); 320203b705cfSriastradh op->base.src.width = src->drawable.width; 320303b705cfSriastradh op->base.src.height = src->drawable.height; 320403b705cfSriastradh 320503b705cfSriastradh op->base.mask.bo = NULL; 320603b705cfSriastradh 320703b705cfSriastradh op->base.floats_per_vertex = 2; 320803b705cfSriastradh op->base.floats_per_rect = 6; 320903b705cfSriastradh 321003b705cfSriastradh op->base.u.gen7.flags = COPY_FLAGS(alu); 321103b705cfSriastradh 321203b705cfSriastradh kgem_set_mode(&sna->kgem, KGEM_RENDER, dst_bo); 321303b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) { 321403b705cfSriastradh kgem_submit(&sna->kgem); 321503b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) 321603b705cfSriastradh goto fallback; 321703b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 321803b705cfSriastradh } 321903b705cfSriastradh 322003b705cfSriastradh gen7_align_vertex(sna, &op->base); 322142542f5fSchristos gen7_emit_copy_state(sna, &op->base); 322203b705cfSriastradh 322303b705cfSriastradh op->blt = gen7_render_copy_blt; 322403b705cfSriastradh op->done = gen7_render_copy_done; 322503b705cfSriastradh return true; 322603b705cfSriastradh} 322703b705cfSriastradh 322803b705cfSriastradhstatic void 322903b705cfSriastradhgen7_emit_fill_state(struct sna *sna, const struct sna_composite_op *op) 323003b705cfSriastradh{ 323142542f5fSchristos uint16_t dirty; 323203b705cfSriastradh uint32_t *binding_table; 323303b705cfSriastradh uint16_t offset; 323403b705cfSriastradh 323503b705cfSriastradh /* XXX Render Target Fast Clear 323603b705cfSriastradh * Set RTFC Enable in PS and render a rectangle. 323703b705cfSriastradh * Limited to a clearing the full MSC surface only with a 323803b705cfSriastradh * specific kernel. 323903b705cfSriastradh */ 324003b705cfSriastradh 324103b705cfSriastradh gen7_get_batch(sna, op); 324203b705cfSriastradh 324303b705cfSriastradh binding_table = gen7_composite_get_binding_table(sna, &offset); 324403b705cfSriastradh 324542542f5fSchristos dirty = kgem_bo_is_dirty(op->dst.bo); 324642542f5fSchristos 324703b705cfSriastradh binding_table[0] = 324803b705cfSriastradh gen7_bind_bo(sna, 324903b705cfSriastradh op->dst.bo, op->dst.width, op->dst.height, 325003b705cfSriastradh gen7_get_dest_format(op->dst.format), 325103b705cfSriastradh true); 325203b705cfSriastradh binding_table[1] = 325303b705cfSriastradh gen7_bind_bo(sna, 325403b705cfSriastradh op->src.bo, 1, 1, 325503b705cfSriastradh GEN7_SURFACEFORMAT_B8G8R8A8_UNORM, 325603b705cfSriastradh false); 325703b705cfSriastradh 325803b705cfSriastradh if (sna->kgem.surface == offset && 325903b705cfSriastradh *(uint64_t *)(sna->kgem.batch + sna->render_state.gen7.surface_table) == *(uint64_t*)binding_table) { 326003b705cfSriastradh sna->kgem.surface += 326103b705cfSriastradh sizeof(struct gen7_surface_state)/sizeof(uint32_t); 326203b705cfSriastradh offset = sna->render_state.gen7.surface_table; 326303b705cfSriastradh } 326403b705cfSriastradh 326542542f5fSchristos if (sna->kgem.batch[sna->render_state.gen7.surface_table] == binding_table[0]) 326642542f5fSchristos dirty = 0; 326703b705cfSriastradh 326842542f5fSchristos gen7_emit_state(sna, op, offset | dirty); 326903b705cfSriastradh} 327003b705cfSriastradh 327103b705cfSriastradhstatic bool 327203b705cfSriastradhgen7_render_fill_boxes(struct sna *sna, 327303b705cfSriastradh CARD8 op, 327403b705cfSriastradh PictFormat format, 327503b705cfSriastradh const xRenderColor *color, 327642542f5fSchristos const DrawableRec *dst, struct kgem_bo *dst_bo, 327703b705cfSriastradh const BoxRec *box, int n) 327803b705cfSriastradh{ 327903b705cfSriastradh struct sna_composite_op tmp; 328003b705cfSriastradh uint32_t pixel; 328103b705cfSriastradh 328203b705cfSriastradh DBG(("%s (op=%d, color=(%04x, %04x, %04x, %04x) [%08x])\n", 328303b705cfSriastradh __FUNCTION__, op, 328403b705cfSriastradh color->red, color->green, color->blue, color->alpha, (int)format)); 328503b705cfSriastradh 328603b705cfSriastradh if (op >= ARRAY_SIZE(gen7_blend_op)) { 328703b705cfSriastradh DBG(("%s: fallback due to unhandled blend op: %d\n", 328803b705cfSriastradh __FUNCTION__, op)); 328903b705cfSriastradh return false; 329003b705cfSriastradh } 329103b705cfSriastradh 329242542f5fSchristos if (prefer_blt_fill(sna, dst_bo, FILL_BOXES) || 329342542f5fSchristos !gen7_check_dst_format(format)) { 329403b705cfSriastradh uint8_t alu = GXinvalid; 329503b705cfSriastradh 329603b705cfSriastradh if (op <= PictOpSrc) { 329703b705cfSriastradh pixel = 0; 329803b705cfSriastradh if (op == PictOpClear) 329903b705cfSriastradh alu = GXclear; 330003b705cfSriastradh else if (sna_get_pixel_from_rgba(&pixel, 330103b705cfSriastradh color->red, 330203b705cfSriastradh color->green, 330303b705cfSriastradh color->blue, 330403b705cfSriastradh color->alpha, 330503b705cfSriastradh format)) 330603b705cfSriastradh alu = GXcopy; 330703b705cfSriastradh } 330803b705cfSriastradh 330903b705cfSriastradh if (alu != GXinvalid && 331003b705cfSriastradh sna_blt_fill_boxes(sna, alu, 331142542f5fSchristos dst_bo, dst->bitsPerPixel, 331203b705cfSriastradh pixel, box, n)) 331303b705cfSriastradh return true; 331403b705cfSriastradh 331503b705cfSriastradh if (!gen7_check_dst_format(format)) 331603b705cfSriastradh return false; 331703b705cfSriastradh } 331803b705cfSriastradh 331903b705cfSriastradh if (op == PictOpClear) { 332003b705cfSriastradh pixel = 0; 332103b705cfSriastradh op = PictOpSrc; 332203b705cfSriastradh } else if (!sna_get_pixel_from_rgba(&pixel, 332303b705cfSriastradh color->red, 332403b705cfSriastradh color->green, 332503b705cfSriastradh color->blue, 332603b705cfSriastradh color->alpha, 332703b705cfSriastradh PICT_a8r8g8b8)) 332803b705cfSriastradh return false; 332903b705cfSriastradh 333003b705cfSriastradh DBG(("%s(%08x x %d [(%d, %d), (%d, %d) ...])\n", 333103b705cfSriastradh __FUNCTION__, pixel, n, 333203b705cfSriastradh box[0].x1, box[0].y1, box[0].x2, box[0].y2)); 333303b705cfSriastradh 333442542f5fSchristos tmp.dst.pixmap = (PixmapPtr)dst; 333542542f5fSchristos tmp.dst.width = dst->width; 333642542f5fSchristos tmp.dst.height = dst->height; 333703b705cfSriastradh tmp.dst.format = format; 333803b705cfSriastradh tmp.dst.bo = dst_bo; 333903b705cfSriastradh tmp.dst.x = tmp.dst.y = 0; 334003b705cfSriastradh tmp.damage = NULL; 334103b705cfSriastradh 334203b705cfSriastradh sna_render_composite_redirect_init(&tmp); 334342542f5fSchristos if (too_large(dst->width, dst->height)) { 334403b705cfSriastradh BoxRec extents; 334503b705cfSriastradh 334603b705cfSriastradh boxes_extents(box, n, &extents); 334703b705cfSriastradh if (!sna_render_composite_redirect(sna, &tmp, 334803b705cfSriastradh extents.x1, extents.y1, 334903b705cfSriastradh extents.x2 - extents.x1, 335003b705cfSriastradh extents.y2 - extents.y1, 335103b705cfSriastradh n > 1)) 335203b705cfSriastradh return sna_tiling_fill_boxes(sna, op, format, color, 335303b705cfSriastradh dst, dst_bo, box, n); 335403b705cfSriastradh } 335503b705cfSriastradh 335603b705cfSriastradh tmp.src.bo = sna_render_get_solid(sna, pixel); 335703b705cfSriastradh tmp.mask.bo = NULL; 335803b705cfSriastradh 335903b705cfSriastradh tmp.floats_per_vertex = 2; 336003b705cfSriastradh tmp.floats_per_rect = 6; 336103b705cfSriastradh tmp.need_magic_ca_pass = false; 336203b705cfSriastradh 336303b705cfSriastradh tmp.u.gen7.flags = FILL_FLAGS(op, format); 336403b705cfSriastradh 336503b705cfSriastradh kgem_set_mode(&sna->kgem, KGEM_RENDER, dst_bo); 336603b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) { 336703b705cfSriastradh kgem_submit(&sna->kgem); 336842542f5fSchristos if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) { 336942542f5fSchristos kgem_bo_destroy(&sna->kgem, tmp.src.bo); 337042542f5fSchristos if (tmp.redirect.real_bo) 337142542f5fSchristos kgem_bo_destroy(&sna->kgem, tmp.dst.bo); 337242542f5fSchristos 337342542f5fSchristos return false; 337442542f5fSchristos } 337542542f5fSchristos _kgem_set_mode(&sna->kgem, KGEM_RENDER); 337603b705cfSriastradh } 337703b705cfSriastradh 337803b705cfSriastradh gen7_align_vertex(sna, &tmp); 337942542f5fSchristos gen7_emit_fill_state(sna, &tmp); 338003b705cfSriastradh 338103b705cfSriastradh do { 338203b705cfSriastradh int n_this_time; 338303b705cfSriastradh int16_t *v; 338403b705cfSriastradh 338503b705cfSriastradh n_this_time = gen7_get_rectangles(sna, &tmp, n, 338603b705cfSriastradh gen7_emit_fill_state); 338703b705cfSriastradh n -= n_this_time; 338803b705cfSriastradh 338903b705cfSriastradh v = (int16_t *)(sna->render.vertices + sna->render.vertex_used); 339003b705cfSriastradh sna->render.vertex_used += 6 * n_this_time; 339103b705cfSriastradh assert(sna->render.vertex_used <= sna->render.vertex_size); 339203b705cfSriastradh do { 339303b705cfSriastradh DBG((" (%d, %d), (%d, %d)\n", 339403b705cfSriastradh box->x1, box->y1, box->x2, box->y2)); 339503b705cfSriastradh 339603b705cfSriastradh v[0] = box->x2; 339703b705cfSriastradh v[5] = v[1] = box->y2; 339803b705cfSriastradh v[8] = v[4] = box->x1; 339903b705cfSriastradh v[9] = box->y1; 340003b705cfSriastradh v[2] = v[3] = v[7] = 1; 340103b705cfSriastradh v[6] = v[10] = v[11] = 0; 340203b705cfSriastradh v += 12; box++; 340303b705cfSriastradh } while (--n_this_time); 340403b705cfSriastradh } while (n); 340503b705cfSriastradh 340603b705cfSriastradh gen4_vertex_flush(sna); 340703b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp.src.bo); 340803b705cfSriastradh sna_render_composite_redirect_done(sna, &tmp); 340903b705cfSriastradh return true; 341003b705cfSriastradh} 341103b705cfSriastradh 341203b705cfSriastradhstatic void 341303b705cfSriastradhgen7_render_fill_op_blt(struct sna *sna, 341403b705cfSriastradh const struct sna_fill_op *op, 341503b705cfSriastradh int16_t x, int16_t y, int16_t w, int16_t h) 341603b705cfSriastradh{ 341703b705cfSriastradh int16_t *v; 341803b705cfSriastradh 341903b705cfSriastradh DBG(("%s: (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, w, h)); 342003b705cfSriastradh 342103b705cfSriastradh gen7_get_rectangles(sna, &op->base, 1, gen7_emit_fill_state); 342203b705cfSriastradh 342303b705cfSriastradh v = (int16_t *)&sna->render.vertices[sna->render.vertex_used]; 342403b705cfSriastradh sna->render.vertex_used += 6; 342503b705cfSriastradh assert(sna->render.vertex_used <= sna->render.vertex_size); 342603b705cfSriastradh 342703b705cfSriastradh v[0] = x+w; 342803b705cfSriastradh v[4] = v[8] = x; 342903b705cfSriastradh v[1] = v[5] = y+h; 343003b705cfSriastradh v[9] = y; 343103b705cfSriastradh 343203b705cfSriastradh v[2] = v[3] = v[7] = 1; 343303b705cfSriastradh v[6] = v[10] = v[11] = 0; 343403b705cfSriastradh} 343503b705cfSriastradh 343603b705cfSriastradhfastcall static void 343703b705cfSriastradhgen7_render_fill_op_box(struct sna *sna, 343803b705cfSriastradh const struct sna_fill_op *op, 343903b705cfSriastradh const BoxRec *box) 344003b705cfSriastradh{ 344103b705cfSriastradh int16_t *v; 344203b705cfSriastradh 344303b705cfSriastradh DBG(("%s: (%d, %d),(%d, %d)\n", __FUNCTION__, 344403b705cfSriastradh box->x1, box->y1, box->x2, box->y2)); 344503b705cfSriastradh 344603b705cfSriastradh gen7_get_rectangles(sna, &op->base, 1, gen7_emit_fill_state); 344703b705cfSriastradh 344803b705cfSriastradh v = (int16_t *)&sna->render.vertices[sna->render.vertex_used]; 344903b705cfSriastradh sna->render.vertex_used += 6; 345003b705cfSriastradh assert(sna->render.vertex_used <= sna->render.vertex_size); 345103b705cfSriastradh 345203b705cfSriastradh v[0] = box->x2; 345303b705cfSriastradh v[8] = v[4] = box->x1; 345403b705cfSriastradh v[5] = v[1] = box->y2; 345503b705cfSriastradh v[9] = box->y1; 345603b705cfSriastradh 345703b705cfSriastradh v[7] = v[2] = v[3] = 1; 345803b705cfSriastradh v[6] = v[10] = v[11] = 0; 345903b705cfSriastradh} 346003b705cfSriastradh 346103b705cfSriastradhfastcall static void 346203b705cfSriastradhgen7_render_fill_op_boxes(struct sna *sna, 346303b705cfSriastradh const struct sna_fill_op *op, 346403b705cfSriastradh const BoxRec *box, 346503b705cfSriastradh int nbox) 346603b705cfSriastradh{ 346703b705cfSriastradh DBG(("%s: (%d, %d),(%d, %d)... x %d\n", __FUNCTION__, 346803b705cfSriastradh box->x1, box->y1, box->x2, box->y2, nbox)); 346903b705cfSriastradh 347003b705cfSriastradh do { 347103b705cfSriastradh int nbox_this_time; 347203b705cfSriastradh int16_t *v; 347303b705cfSriastradh 347403b705cfSriastradh nbox_this_time = gen7_get_rectangles(sna, &op->base, nbox, 347503b705cfSriastradh gen7_emit_fill_state); 347603b705cfSriastradh nbox -= nbox_this_time; 347703b705cfSriastradh 347803b705cfSriastradh v = (int16_t *)&sna->render.vertices[sna->render.vertex_used]; 347903b705cfSriastradh sna->render.vertex_used += 6 * nbox_this_time; 348003b705cfSriastradh assert(sna->render.vertex_used <= sna->render.vertex_size); 348103b705cfSriastradh 348203b705cfSriastradh do { 348303b705cfSriastradh v[0] = box->x2; 348403b705cfSriastradh v[8] = v[4] = box->x1; 348503b705cfSriastradh v[5] = v[1] = box->y2; 348603b705cfSriastradh v[9] = box->y1; 348703b705cfSriastradh v[7] = v[2] = v[3] = 1; 348803b705cfSriastradh v[6] = v[10] = v[11] = 0; 348903b705cfSriastradh box++; v += 12; 349003b705cfSriastradh } while (--nbox_this_time); 349103b705cfSriastradh } while (nbox); 349203b705cfSriastradh} 349303b705cfSriastradh 349403b705cfSriastradhstatic void 349503b705cfSriastradhgen7_render_fill_op_done(struct sna *sna, const struct sna_fill_op *op) 349603b705cfSriastradh{ 349703b705cfSriastradh if (sna->render.vertex_offset) 349803b705cfSriastradh gen4_vertex_flush(sna); 349903b705cfSriastradh kgem_bo_destroy(&sna->kgem, op->base.src.bo); 350003b705cfSriastradh} 350103b705cfSriastradh 350203b705cfSriastradhstatic bool 350303b705cfSriastradhgen7_render_fill(struct sna *sna, uint8_t alu, 350403b705cfSriastradh PixmapPtr dst, struct kgem_bo *dst_bo, 350542542f5fSchristos uint32_t color, unsigned flags, 350603b705cfSriastradh struct sna_fill_op *op) 350703b705cfSriastradh{ 350803b705cfSriastradh DBG(("%s: (alu=%d, color=%x)\n", __FUNCTION__, alu, color)); 350903b705cfSriastradh 351042542f5fSchristos if (prefer_blt_fill(sna, dst_bo, flags) && 351103b705cfSriastradh sna_blt_fill(sna, alu, 351203b705cfSriastradh dst_bo, dst->drawable.bitsPerPixel, 351303b705cfSriastradh color, 351403b705cfSriastradh op)) 351503b705cfSriastradh return true; 351603b705cfSriastradh 351703b705cfSriastradh if (!(alu == GXcopy || alu == GXclear) || 351803b705cfSriastradh too_large(dst->drawable.width, dst->drawable.height)) 351903b705cfSriastradh return sna_blt_fill(sna, alu, 352003b705cfSriastradh dst_bo, dst->drawable.bitsPerPixel, 352103b705cfSriastradh color, 352203b705cfSriastradh op); 352303b705cfSriastradh 352403b705cfSriastradh if (alu == GXclear) 352503b705cfSriastradh color = 0; 352603b705cfSriastradh 352703b705cfSriastradh op->base.dst.pixmap = dst; 352803b705cfSriastradh op->base.dst.width = dst->drawable.width; 352903b705cfSriastradh op->base.dst.height = dst->drawable.height; 353003b705cfSriastradh op->base.dst.format = sna_format_for_depth(dst->drawable.depth); 353103b705cfSriastradh op->base.dst.bo = dst_bo; 353203b705cfSriastradh op->base.dst.x = op->base.dst.y = 0; 353303b705cfSriastradh 353403b705cfSriastradh op->base.src.bo = 353503b705cfSriastradh sna_render_get_solid(sna, 353603b705cfSriastradh sna_rgba_for_color(color, 353703b705cfSriastradh dst->drawable.depth)); 353803b705cfSriastradh op->base.mask.bo = NULL; 353903b705cfSriastradh 354003b705cfSriastradh op->base.need_magic_ca_pass = false; 354103b705cfSriastradh op->base.floats_per_vertex = 2; 354203b705cfSriastradh op->base.floats_per_rect = 6; 354303b705cfSriastradh 354403b705cfSriastradh op->base.u.gen7.flags = FILL_FLAGS_NOBLEND; 354503b705cfSriastradh 354603b705cfSriastradh kgem_set_mode(&sna->kgem, KGEM_RENDER, dst_bo); 354703b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) { 354803b705cfSriastradh kgem_submit(&sna->kgem); 354942542f5fSchristos if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) { 355042542f5fSchristos kgem_bo_destroy(&sna->kgem, op->base.src.bo); 355142542f5fSchristos return false; 355242542f5fSchristos } 355342542f5fSchristos 355442542f5fSchristos _kgem_set_mode(&sna->kgem, KGEM_RENDER); 355503b705cfSriastradh } 355603b705cfSriastradh 355703b705cfSriastradh gen7_align_vertex(sna, &op->base); 355842542f5fSchristos gen7_emit_fill_state(sna, &op->base); 355903b705cfSriastradh 356003b705cfSriastradh op->blt = gen7_render_fill_op_blt; 356103b705cfSriastradh op->box = gen7_render_fill_op_box; 356203b705cfSriastradh op->boxes = gen7_render_fill_op_boxes; 356342542f5fSchristos op->points = NULL; 356403b705cfSriastradh op->done = gen7_render_fill_op_done; 356503b705cfSriastradh return true; 356603b705cfSriastradh} 356703b705cfSriastradh 356803b705cfSriastradhstatic bool 356903b705cfSriastradhgen7_render_fill_one_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo, 357003b705cfSriastradh uint32_t color, 357103b705cfSriastradh int16_t x1, int16_t y1, int16_t x2, int16_t y2, 357203b705cfSriastradh uint8_t alu) 357303b705cfSriastradh{ 357403b705cfSriastradh BoxRec box; 357503b705cfSriastradh 357603b705cfSriastradh box.x1 = x1; 357703b705cfSriastradh box.y1 = y1; 357803b705cfSriastradh box.x2 = x2; 357903b705cfSriastradh box.y2 = y2; 358003b705cfSriastradh 358103b705cfSriastradh return sna_blt_fill_boxes(sna, alu, 358203b705cfSriastradh bo, dst->drawable.bitsPerPixel, 358303b705cfSriastradh color, &box, 1); 358403b705cfSriastradh} 358503b705cfSriastradh 358603b705cfSriastradhstatic bool 358703b705cfSriastradhgen7_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo, 358803b705cfSriastradh uint32_t color, 358903b705cfSriastradh int16_t x1, int16_t y1, 359003b705cfSriastradh int16_t x2, int16_t y2, 359103b705cfSriastradh uint8_t alu) 359203b705cfSriastradh{ 359303b705cfSriastradh struct sna_composite_op tmp; 359403b705cfSriastradh int16_t *v; 359503b705cfSriastradh 359603b705cfSriastradh /* Prefer to use the BLT if already engaged */ 359742542f5fSchristos if (prefer_blt_fill(sna, bo, FILL_BOXES) && 359803b705cfSriastradh gen7_render_fill_one_try_blt(sna, dst, bo, color, 359903b705cfSriastradh x1, y1, x2, y2, alu)) 360003b705cfSriastradh return true; 360103b705cfSriastradh 360203b705cfSriastradh /* Must use the BLT if we can't RENDER... */ 360303b705cfSriastradh if (!(alu == GXcopy || alu == GXclear) || 360403b705cfSriastradh too_large(dst->drawable.width, dst->drawable.height)) 360503b705cfSriastradh return gen7_render_fill_one_try_blt(sna, dst, bo, color, 360603b705cfSriastradh x1, y1, x2, y2, alu); 360703b705cfSriastradh 360803b705cfSriastradh if (alu == GXclear) 360903b705cfSriastradh color = 0; 361003b705cfSriastradh 361103b705cfSriastradh tmp.dst.pixmap = dst; 361203b705cfSriastradh tmp.dst.width = dst->drawable.width; 361303b705cfSriastradh tmp.dst.height = dst->drawable.height; 361403b705cfSriastradh tmp.dst.format = sna_format_for_depth(dst->drawable.depth); 361503b705cfSriastradh tmp.dst.bo = bo; 361603b705cfSriastradh tmp.dst.x = tmp.dst.y = 0; 361703b705cfSriastradh 361803b705cfSriastradh tmp.src.bo = 361903b705cfSriastradh sna_render_get_solid(sna, 362003b705cfSriastradh sna_rgba_for_color(color, 362103b705cfSriastradh dst->drawable.depth)); 362203b705cfSriastradh tmp.mask.bo = NULL; 362303b705cfSriastradh 362403b705cfSriastradh tmp.floats_per_vertex = 2; 362503b705cfSriastradh tmp.floats_per_rect = 6; 362603b705cfSriastradh tmp.need_magic_ca_pass = false; 362703b705cfSriastradh 362803b705cfSriastradh tmp.u.gen7.flags = FILL_FLAGS_NOBLEND; 362903b705cfSriastradh 363003b705cfSriastradh kgem_set_mode(&sna->kgem, KGEM_RENDER, bo); 363103b705cfSriastradh if (!kgem_check_bo(&sna->kgem, bo, NULL)) { 363203b705cfSriastradh kgem_submit(&sna->kgem); 363342542f5fSchristos if (!kgem_check_bo(&sna->kgem, bo, NULL)) { 363403b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp.src.bo); 363503b705cfSriastradh return false; 363603b705cfSriastradh } 363742542f5fSchristos _kgem_set_mode(&sna->kgem, KGEM_RENDER); 363803b705cfSriastradh } 363903b705cfSriastradh 364003b705cfSriastradh gen7_align_vertex(sna, &tmp); 364142542f5fSchristos gen7_emit_fill_state(sna, &tmp); 364203b705cfSriastradh 364303b705cfSriastradh gen7_get_rectangles(sna, &tmp, 1, gen7_emit_fill_state); 364403b705cfSriastradh 364503b705cfSriastradh DBG((" (%d, %d), (%d, %d)\n", x1, y1, x2, y2)); 364603b705cfSriastradh 364703b705cfSriastradh v = (int16_t *)&sna->render.vertices[sna->render.vertex_used]; 364803b705cfSriastradh sna->render.vertex_used += 6; 364903b705cfSriastradh assert(sna->render.vertex_used <= sna->render.vertex_size); 365003b705cfSriastradh 365103b705cfSriastradh v[0] = x2; 365203b705cfSriastradh v[8] = v[4] = x1; 365303b705cfSriastradh v[5] = v[1] = y2; 365403b705cfSriastradh v[9] = y1; 365503b705cfSriastradh v[7] = v[2] = v[3] = 1; 365603b705cfSriastradh v[6] = v[10] = v[11] = 0; 365703b705cfSriastradh 365803b705cfSriastradh gen4_vertex_flush(sna); 365903b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp.src.bo); 366003b705cfSriastradh 366103b705cfSriastradh return true; 366203b705cfSriastradh} 366303b705cfSriastradh 366403b705cfSriastradhstatic bool 366503b705cfSriastradhgen7_render_clear_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo) 366603b705cfSriastradh{ 366703b705cfSriastradh BoxRec box; 366803b705cfSriastradh 366903b705cfSriastradh box.x1 = 0; 367003b705cfSriastradh box.y1 = 0; 367103b705cfSriastradh box.x2 = dst->drawable.width; 367203b705cfSriastradh box.y2 = dst->drawable.height; 367303b705cfSriastradh 367403b705cfSriastradh return sna_blt_fill_boxes(sna, GXclear, 367503b705cfSriastradh bo, dst->drawable.bitsPerPixel, 367603b705cfSriastradh 0, &box, 1); 367703b705cfSriastradh} 367803b705cfSriastradh 367903b705cfSriastradhstatic bool 368003b705cfSriastradhgen7_render_clear(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo) 368103b705cfSriastradh{ 368203b705cfSriastradh struct sna_composite_op tmp; 368303b705cfSriastradh int16_t *v; 368403b705cfSriastradh 368503b705cfSriastradh DBG(("%s: %dx%d\n", 368603b705cfSriastradh __FUNCTION__, 368703b705cfSriastradh dst->drawable.width, 368803b705cfSriastradh dst->drawable.height)); 368903b705cfSriastradh 369003b705cfSriastradh /* Prefer to use the BLT if already engaged */ 369103b705cfSriastradh if (sna->kgem.mode == KGEM_BLT && 369203b705cfSriastradh gen7_render_clear_try_blt(sna, dst, bo)) 369303b705cfSriastradh return true; 369403b705cfSriastradh 369503b705cfSriastradh /* Must use the BLT if we can't RENDER... */ 369603b705cfSriastradh if (too_large(dst->drawable.width, dst->drawable.height)) 369703b705cfSriastradh return gen7_render_clear_try_blt(sna, dst, bo); 369803b705cfSriastradh 369903b705cfSriastradh tmp.dst.pixmap = dst; 370003b705cfSriastradh tmp.dst.width = dst->drawable.width; 370103b705cfSriastradh tmp.dst.height = dst->drawable.height; 370203b705cfSriastradh tmp.dst.format = sna_format_for_depth(dst->drawable.depth); 370303b705cfSriastradh tmp.dst.bo = bo; 370403b705cfSriastradh tmp.dst.x = tmp.dst.y = 0; 370503b705cfSriastradh 370603b705cfSriastradh tmp.src.bo = sna_render_get_solid(sna, 0); 370703b705cfSriastradh tmp.mask.bo = NULL; 370803b705cfSriastradh 370903b705cfSriastradh tmp.floats_per_vertex = 2; 371003b705cfSriastradh tmp.floats_per_rect = 6; 371103b705cfSriastradh tmp.need_magic_ca_pass = false; 371203b705cfSriastradh 371303b705cfSriastradh tmp.u.gen7.flags = FILL_FLAGS_NOBLEND; 371403b705cfSriastradh 371503b705cfSriastradh kgem_set_mode(&sna->kgem, KGEM_RENDER, bo); 371603b705cfSriastradh if (!kgem_check_bo(&sna->kgem, bo, NULL)) { 371703b705cfSriastradh kgem_submit(&sna->kgem); 371803b705cfSriastradh if (!kgem_check_bo(&sna->kgem, bo, NULL)) { 371903b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp.src.bo); 372003b705cfSriastradh return false; 372103b705cfSriastradh } 372242542f5fSchristos _kgem_set_mode(&sna->kgem, KGEM_RENDER); 372303b705cfSriastradh } 372403b705cfSriastradh 372503b705cfSriastradh gen7_align_vertex(sna, &tmp); 372642542f5fSchristos gen7_emit_fill_state(sna, &tmp); 372703b705cfSriastradh 372803b705cfSriastradh gen7_get_rectangles(sna, &tmp, 1, gen7_emit_fill_state); 372903b705cfSriastradh 373003b705cfSriastradh v = (int16_t *)&sna->render.vertices[sna->render.vertex_used]; 373103b705cfSriastradh sna->render.vertex_used += 6; 373203b705cfSriastradh assert(sna->render.vertex_used <= sna->render.vertex_size); 373303b705cfSriastradh 373403b705cfSriastradh v[0] = dst->drawable.width; 373503b705cfSriastradh v[5] = v[1] = dst->drawable.height; 373603b705cfSriastradh v[8] = v[4] = 0; 373703b705cfSriastradh v[9] = 0; 373803b705cfSriastradh 373903b705cfSriastradh v[7] = v[2] = v[3] = 1; 374003b705cfSriastradh v[6] = v[10] = v[11] = 0; 374103b705cfSriastradh 374203b705cfSriastradh gen4_vertex_flush(sna); 374303b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp.src.bo); 374403b705cfSriastradh 374503b705cfSriastradh return true; 374603b705cfSriastradh} 374703b705cfSriastradhstatic void gen7_render_reset(struct sna *sna) 374803b705cfSriastradh{ 374903b705cfSriastradh sna->render_state.gen7.emit_flush = false; 375003b705cfSriastradh sna->render_state.gen7.needs_invariant = true; 375103b705cfSriastradh sna->render_state.gen7.ve_id = 3 << 2; 375203b705cfSriastradh sna->render_state.gen7.last_primitive = -1; 375303b705cfSriastradh 375403b705cfSriastradh sna->render_state.gen7.num_sf_outputs = 0; 375503b705cfSriastradh sna->render_state.gen7.samplers = -1; 375603b705cfSriastradh sna->render_state.gen7.blend = -1; 375703b705cfSriastradh sna->render_state.gen7.kernel = -1; 375803b705cfSriastradh sna->render_state.gen7.drawrect_offset = -1; 375903b705cfSriastradh sna->render_state.gen7.drawrect_limit = -1; 376042542f5fSchristos sna->render_state.gen7.surface_table = 0; 376142542f5fSchristos 376242542f5fSchristos if (sna->render.vbo && !kgem_bo_can_map(&sna->kgem, sna->render.vbo)) { 376342542f5fSchristos DBG(("%s: discarding unmappable vbo\n", __FUNCTION__)); 376442542f5fSchristos discard_vbo(sna); 376542542f5fSchristos } 376603b705cfSriastradh 376703b705cfSriastradh sna->render.vertex_offset = 0; 376803b705cfSriastradh sna->render.nvertex_reloc = 0; 376903b705cfSriastradh sna->render.vb_id = 0; 377003b705cfSriastradh} 377103b705cfSriastradh 377203b705cfSriastradhstatic void gen7_render_fini(struct sna *sna) 377303b705cfSriastradh{ 377403b705cfSriastradh kgem_bo_destroy(&sna->kgem, sna->render_state.gen7.general_bo); 377503b705cfSriastradh} 377603b705cfSriastradh 377742542f5fSchristosstatic bool is_gt3(struct sna *sna, int devid) 377803b705cfSriastradh{ 377903b705cfSriastradh assert(sna->kgem.gen == 075); 378042542f5fSchristos return devid & 0x20; 378103b705cfSriastradh} 378203b705cfSriastradh 378342542f5fSchristosstatic bool is_gt2(struct sna *sna, int devid) 378403b705cfSriastradh{ 378542542f5fSchristos return devid & (is_hsw(sna)? 0x30 : 0x20); 378603b705cfSriastradh} 378703b705cfSriastradh 378842542f5fSchristosstatic bool is_mobile(struct sna *sna, int devid) 378903b705cfSriastradh{ 379042542f5fSchristos return (devid & 0xf) == 0x6; 379103b705cfSriastradh} 379203b705cfSriastradh 379342542f5fSchristosstatic bool gen7_render_setup(struct sna *sna, int devid) 379403b705cfSriastradh{ 379503b705cfSriastradh struct gen7_render_state *state = &sna->render_state.gen7; 379603b705cfSriastradh struct sna_static_stream general; 379703b705cfSriastradh struct gen7_sampler_state *ss; 379803b705cfSriastradh int i, j, k, l, m; 379903b705cfSriastradh 380003b705cfSriastradh if (is_ivb(sna)) { 380103b705cfSriastradh state->info = &ivb_gt_info; 380242542f5fSchristos if (devid & 0xf) { 380303b705cfSriastradh state->info = &ivb_gt1_info; 380442542f5fSchristos if (is_gt2(sna, devid)) 380503b705cfSriastradh state->info = &ivb_gt2_info; /* XXX requires GT_MODE WiZ disabled */ 380603b705cfSriastradh } 380703b705cfSriastradh } else if (is_byt(sna)) { 380803b705cfSriastradh state->info = &byt_gt_info; 380903b705cfSriastradh } else if (is_hsw(sna)) { 381003b705cfSriastradh state->info = &hsw_gt_info; 381142542f5fSchristos if (devid & 0xf) { 381242542f5fSchristos if (is_gt3(sna, devid)) 381303b705cfSriastradh state->info = &hsw_gt3_info; 381442542f5fSchristos else if (is_gt2(sna, devid)) 381503b705cfSriastradh state->info = &hsw_gt2_info; 381603b705cfSriastradh else 381703b705cfSriastradh state->info = &hsw_gt1_info; 381803b705cfSriastradh } 381903b705cfSriastradh } else 382003b705cfSriastradh return false; 382103b705cfSriastradh 382242542f5fSchristos state->gt = state->info->gt; 382342542f5fSchristos 382403b705cfSriastradh sna_static_stream_init(&general); 382503b705cfSriastradh 382603b705cfSriastradh /* Zero pad the start. If you see an offset of 0x0 in the batchbuffer 382703b705cfSriastradh * dumps, you know it points to zero. 382803b705cfSriastradh */ 382903b705cfSriastradh null_create(&general); 383003b705cfSriastradh 383103b705cfSriastradh for (m = 0; m < GEN7_WM_KERNEL_COUNT; m++) { 383203b705cfSriastradh if (wm_kernels[m].size) { 383303b705cfSriastradh state->wm_kernel[m][1] = 383403b705cfSriastradh sna_static_stream_add(&general, 383503b705cfSriastradh wm_kernels[m].data, 383603b705cfSriastradh wm_kernels[m].size, 383703b705cfSriastradh 64); 383803b705cfSriastradh } else { 383903b705cfSriastradh if (USE_8_PIXEL_DISPATCH) { 384003b705cfSriastradh state->wm_kernel[m][0] = 384103b705cfSriastradh sna_static_stream_compile_wm(sna, &general, 384203b705cfSriastradh wm_kernels[m].data, 8); 384303b705cfSriastradh } 384403b705cfSriastradh 384503b705cfSriastradh if (USE_16_PIXEL_DISPATCH) { 384603b705cfSriastradh state->wm_kernel[m][1] = 384703b705cfSriastradh sna_static_stream_compile_wm(sna, &general, 384803b705cfSriastradh wm_kernels[m].data, 16); 384903b705cfSriastradh } 385003b705cfSriastradh 385103b705cfSriastradh if (USE_32_PIXEL_DISPATCH) { 385203b705cfSriastradh state->wm_kernel[m][2] = 385303b705cfSriastradh sna_static_stream_compile_wm(sna, &general, 385403b705cfSriastradh wm_kernels[m].data, 32); 385503b705cfSriastradh } 385603b705cfSriastradh } 385703b705cfSriastradh assert(state->wm_kernel[m][0]|state->wm_kernel[m][1]|state->wm_kernel[m][2]); 385803b705cfSriastradh } 385903b705cfSriastradh 386003b705cfSriastradh ss = sna_static_stream_map(&general, 386103b705cfSriastradh 2 * sizeof(*ss) * 386203b705cfSriastradh (2 + 386303b705cfSriastradh FILTER_COUNT * EXTEND_COUNT * 386403b705cfSriastradh FILTER_COUNT * EXTEND_COUNT), 386503b705cfSriastradh 32); 386603b705cfSriastradh state->wm_state = sna_static_stream_offsetof(&general, ss); 386703b705cfSriastradh sampler_copy_init(ss); ss += 2; 386803b705cfSriastradh sampler_fill_init(ss); ss += 2; 386903b705cfSriastradh for (i = 0; i < FILTER_COUNT; i++) { 387003b705cfSriastradh for (j = 0; j < EXTEND_COUNT; j++) { 387103b705cfSriastradh for (k = 0; k < FILTER_COUNT; k++) { 387203b705cfSriastradh for (l = 0; l < EXTEND_COUNT; l++) { 387303b705cfSriastradh sampler_state_init(ss++, i, j); 387403b705cfSriastradh sampler_state_init(ss++, k, l); 387503b705cfSriastradh } 387603b705cfSriastradh } 387703b705cfSriastradh } 387803b705cfSriastradh } 387903b705cfSriastradh 388003b705cfSriastradh state->cc_blend = gen7_composite_create_blend_state(&general); 388103b705cfSriastradh 388203b705cfSriastradh state->general_bo = sna_static_stream_fini(sna, &general); 388303b705cfSriastradh return state->general_bo != NULL; 388403b705cfSriastradh} 388503b705cfSriastradh 388603b705cfSriastradhconst char *gen7_render_init(struct sna *sna, const char *backend) 388703b705cfSriastradh{ 388842542f5fSchristos int devid = intel_get_device_id(sna->scrn); 388942542f5fSchristos 389042542f5fSchristos if (!gen7_render_setup(sna, devid)) 389103b705cfSriastradh return backend; 389203b705cfSriastradh 389342542f5fSchristos sna->kgem.context_switch = gen6_render_context_switch; 389442542f5fSchristos sna->kgem.retire = gen6_render_retire; 389542542f5fSchristos sna->kgem.expire = gen4_render_expire; 389603b705cfSriastradh 389703b705cfSriastradh#if !NO_COMPOSITE 389803b705cfSriastradh sna->render.composite = gen7_render_composite; 389903b705cfSriastradh sna->render.prefer_gpu |= PREFER_GPU_RENDER; 390003b705cfSriastradh#endif 390103b705cfSriastradh#if !NO_COMPOSITE_SPANS 390203b705cfSriastradh sna->render.check_composite_spans = gen7_check_composite_spans; 390303b705cfSriastradh sna->render.composite_spans = gen7_render_composite_spans; 390442542f5fSchristos if (is_mobile(sna, devid) || is_gt2(sna, devid) || is_byt(sna)) 390503b705cfSriastradh sna->render.prefer_gpu |= PREFER_GPU_SPANS; 390603b705cfSriastradh#endif 390703b705cfSriastradh sna->render.video = gen7_render_video; 390803b705cfSriastradh 390903b705cfSriastradh#if !NO_COPY_BOXES 391003b705cfSriastradh sna->render.copy_boxes = gen7_render_copy_boxes; 391103b705cfSriastradh#endif 391203b705cfSriastradh#if !NO_COPY 391303b705cfSriastradh sna->render.copy = gen7_render_copy; 391403b705cfSriastradh#endif 391503b705cfSriastradh 391603b705cfSriastradh#if !NO_FILL_BOXES 391703b705cfSriastradh sna->render.fill_boxes = gen7_render_fill_boxes; 391803b705cfSriastradh#endif 391903b705cfSriastradh#if !NO_FILL 392003b705cfSriastradh sna->render.fill = gen7_render_fill; 392103b705cfSriastradh#endif 392203b705cfSriastradh#if !NO_FILL_ONE 392303b705cfSriastradh sna->render.fill_one = gen7_render_fill_one; 392403b705cfSriastradh#endif 392503b705cfSriastradh#if !NO_FILL_CLEAR 392603b705cfSriastradh sna->render.clear = gen7_render_clear; 392703b705cfSriastradh#endif 392803b705cfSriastradh 392942542f5fSchristos sna->render.flush = gen4_render_flush; 393003b705cfSriastradh sna->render.reset = gen7_render_reset; 393103b705cfSriastradh sna->render.fini = gen7_render_fini; 393203b705cfSriastradh 393303b705cfSriastradh sna->render.max_3d_size = GEN7_MAX_SIZE; 393403b705cfSriastradh sna->render.max_3d_pitch = 1 << 18; 393503b705cfSriastradh return sna->render_state.gen7.info->name; 393603b705cfSriastradh} 3937