103b705cfSriastradh/* 203b705cfSriastradh * Copyright © 2006,2011 Intel Corporation 303b705cfSriastradh * 403b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a 503b705cfSriastradh * copy of this software and associated documentation files (the "Software"), 603b705cfSriastradh * to deal in the Software without restriction, including without limitation 703b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 803b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the 903b705cfSriastradh * Software is furnished to do so, subject to the following conditions: 1003b705cfSriastradh * 1103b705cfSriastradh * The above copyright notice and this permission notice (including the next 1203b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the 1303b705cfSriastradh * Software. 1403b705cfSriastradh * 1503b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1603b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1703b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1803b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1903b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2003b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2103b705cfSriastradh * SOFTWARE. 2203b705cfSriastradh * 2303b705cfSriastradh * Authors: 2403b705cfSriastradh * Wang Zhenyu <zhenyu.z.wang@intel.com> 2503b705cfSriastradh * Eric Anholt <eric@anholt.net> 2603b705cfSriastradh * Chris Wilson <chris@chris-wilson.co.uk> 2703b705cfSriastradh * 2803b705cfSriastradh */ 2903b705cfSriastradh 3003b705cfSriastradh#ifdef HAVE_CONFIG_H 3103b705cfSriastradh#include "config.h" 3203b705cfSriastradh#endif 3303b705cfSriastradh 3403b705cfSriastradh#include "sna.h" 3503b705cfSriastradh#include "sna_reg.h" 3603b705cfSriastradh#include "sna_render.h" 3703b705cfSriastradh#include "sna_render_inline.h" 38fe8aea9eSmrg#include "sna_video.h" 3903b705cfSriastradh 4003b705cfSriastradh#include "gen2_render.h" 4103b705cfSriastradh 4203b705cfSriastradh#define NO_COMPOSITE 0 4303b705cfSriastradh#define NO_COMPOSITE_SPANS 0 4403b705cfSriastradh#define NO_COPY 0 4503b705cfSriastradh#define NO_COPY_BOXES 0 4603b705cfSriastradh#define NO_FILL 0 4703b705cfSriastradh#define NO_FILL_ONE 0 4803b705cfSriastradh#define NO_FILL_BOXES 0 4903b705cfSriastradh 5003b705cfSriastradh#define MAX_3D_SIZE 2048 5103b705cfSriastradh#define MAX_3D_PITCH 8192 52fe8aea9eSmrg#define MAX_INLINE (1 << 18) 5303b705cfSriastradh 5403b705cfSriastradh#define BATCH(v) batch_emit(sna, v) 55fe8aea9eSmrg#define BATCH_ALIGNED(v, a) batch_emit_aligned(sna, v, a) 5603b705cfSriastradh#define BATCH_F(v) batch_emit_float(sna, v) 5703b705cfSriastradh#define VERTEX(v) batch_emit_float(sna, v) 5803b705cfSriastradh 5903b705cfSriastradhstatic const struct blendinfo { 6003b705cfSriastradh bool dst_alpha; 6103b705cfSriastradh bool src_alpha; 6203b705cfSriastradh uint32_t src_blend; 6303b705cfSriastradh uint32_t dst_blend; 6403b705cfSriastradh} gen2_blend_op[] = { 6503b705cfSriastradh /* Clear */ 6603b705cfSriastradh {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO}, 6703b705cfSriastradh /* Src */ 6803b705cfSriastradh {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ZERO}, 6903b705cfSriastradh /* Dst */ 7003b705cfSriastradh {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ONE}, 7103b705cfSriastradh /* Over */ 7203b705cfSriastradh {0, 1, BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA}, 7303b705cfSriastradh /* OverReverse */ 7403b705cfSriastradh {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ONE}, 7503b705cfSriastradh /* In */ 7603b705cfSriastradh {1, 0, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_ZERO}, 7703b705cfSriastradh /* InReverse */ 7803b705cfSriastradh {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA}, 7903b705cfSriastradh /* Out */ 8003b705cfSriastradh {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ZERO}, 8103b705cfSriastradh /* OutReverse */ 8203b705cfSriastradh {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_INV_SRC_ALPHA}, 8303b705cfSriastradh /* Atop */ 8403b705cfSriastradh {1, 1, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA}, 8503b705cfSriastradh /* AtopReverse */ 8603b705cfSriastradh {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_SRC_ALPHA}, 8703b705cfSriastradh /* Xor */ 8803b705cfSriastradh {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA}, 8903b705cfSriastradh /* Add */ 9003b705cfSriastradh {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ONE}, 9103b705cfSriastradh}; 9203b705cfSriastradh 9303b705cfSriastradhstatic const struct formatinfo { 9403b705cfSriastradh unsigned int fmt; 9503b705cfSriastradh uint32_t card_fmt; 9603b705cfSriastradh} i8xx_tex_formats[] = { 9703b705cfSriastradh {PICT_a8, MAPSURF_8BIT | MT_8BIT_A8}, 9803b705cfSriastradh {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888}, 9903b705cfSriastradh {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888}, 10003b705cfSriastradh {PICT_r5g6b5, MAPSURF_16BIT | MT_16BIT_RGB565}, 10103b705cfSriastradh {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555}, 10203b705cfSriastradh {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444}, 10303b705cfSriastradh}, i85x_tex_formats[] = { 10403b705cfSriastradh {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888}, 10503b705cfSriastradh {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888}, 10603b705cfSriastradh}; 10703b705cfSriastradh 10803b705cfSriastradhstatic inline bool 10903b705cfSriastradhtoo_large(int width, int height) 11003b705cfSriastradh{ 11103b705cfSriastradh return width > MAX_3D_SIZE || height > MAX_3D_SIZE; 11203b705cfSriastradh} 11303b705cfSriastradh 11403b705cfSriastradhstatic inline uint32_t 11503b705cfSriastradhgen2_buf_tiling(uint32_t tiling) 11603b705cfSriastradh{ 11703b705cfSriastradh uint32_t v = 0; 11803b705cfSriastradh switch (tiling) { 11903b705cfSriastradh default: assert(0); 12003b705cfSriastradh case I915_TILING_Y: v |= BUF_3D_TILE_WALK_Y; 12103b705cfSriastradh case I915_TILING_X: v |= BUF_3D_TILED_SURFACE; 12203b705cfSriastradh case I915_TILING_NONE: break; 12303b705cfSriastradh } 12403b705cfSriastradh return v; 12503b705cfSriastradh} 12603b705cfSriastradh 12703b705cfSriastradhstatic uint32_t 12803b705cfSriastradhgen2_get_dst_format(uint32_t format) 12903b705cfSriastradh{ 13003b705cfSriastradh#define BIAS DSTORG_HORT_BIAS(0x8) | DSTORG_VERT_BIAS(0x8) 13103b705cfSriastradh switch (format) { 13203b705cfSriastradh default: 13303b705cfSriastradh assert(0); 13403b705cfSriastradh case PICT_a8r8g8b8: 13503b705cfSriastradh case PICT_x8r8g8b8: 13603b705cfSriastradh return COLR_BUF_ARGB8888 | BIAS; 13703b705cfSriastradh case PICT_r5g6b5: 13803b705cfSriastradh return COLR_BUF_RGB565 | BIAS; 13903b705cfSriastradh case PICT_a1r5g5b5: 14003b705cfSriastradh case PICT_x1r5g5b5: 14103b705cfSriastradh return COLR_BUF_ARGB1555 | BIAS; 14203b705cfSriastradh case PICT_a8: 14303b705cfSriastradh return COLR_BUF_8BIT | BIAS; 14403b705cfSriastradh case PICT_a4r4g4b4: 14503b705cfSriastradh case PICT_x4r4g4b4: 14603b705cfSriastradh return COLR_BUF_ARGB4444 | BIAS; 14703b705cfSriastradh } 14803b705cfSriastradh#undef BIAS 14903b705cfSriastradh} 15003b705cfSriastradh 15103b705cfSriastradhstatic bool 15203b705cfSriastradhgen2_check_dst_format(uint32_t format) 15303b705cfSriastradh{ 15403b705cfSriastradh switch (format) { 15503b705cfSriastradh case PICT_a8r8g8b8: 15603b705cfSriastradh case PICT_x8r8g8b8: 15703b705cfSriastradh case PICT_r5g6b5: 15803b705cfSriastradh case PICT_a1r5g5b5: 15903b705cfSriastradh case PICT_x1r5g5b5: 16003b705cfSriastradh case PICT_a8: 16103b705cfSriastradh case PICT_a4r4g4b4: 16203b705cfSriastradh case PICT_x4r4g4b4: 16303b705cfSriastradh return true; 16403b705cfSriastradh default: 16503b705cfSriastradh return false; 16603b705cfSriastradh } 16703b705cfSriastradh} 16803b705cfSriastradh 16903b705cfSriastradhstatic uint32_t 17003b705cfSriastradhgen2_get_card_format(struct sna *sna, uint32_t format) 17103b705cfSriastradh{ 17203b705cfSriastradh unsigned int i; 17303b705cfSriastradh 17403b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i8xx_tex_formats); i++) 17503b705cfSriastradh if (i8xx_tex_formats[i].fmt == format) 17603b705cfSriastradh return i8xx_tex_formats[i].card_fmt; 17703b705cfSriastradh 17803b705cfSriastradh if (sna->kgem.gen < 021) { 17903b705cfSriastradh /* Whilst these are not directly supported on 830/845, 18003b705cfSriastradh * we only enable them when we can implicitly convert 18103b705cfSriastradh * them to a supported variant through the texture 18203b705cfSriastradh * combiners. 18303b705cfSriastradh */ 18403b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i85x_tex_formats); i++) 18503b705cfSriastradh if (i85x_tex_formats[i].fmt == format) 18603b705cfSriastradh return i8xx_tex_formats[1+i].card_fmt; 18703b705cfSriastradh } else { 18803b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i85x_tex_formats); i++) 18903b705cfSriastradh if (i85x_tex_formats[i].fmt == format) 19003b705cfSriastradh return i85x_tex_formats[i].card_fmt; 19103b705cfSriastradh } 19203b705cfSriastradh 19303b705cfSriastradh assert(0); 19403b705cfSriastradh return 0; 19503b705cfSriastradh} 19603b705cfSriastradh 19703b705cfSriastradhstatic uint32_t 19803b705cfSriastradhgen2_check_format(struct sna *sna, PicturePtr p) 19903b705cfSriastradh{ 20003b705cfSriastradh unsigned int i; 20103b705cfSriastradh 20203b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i8xx_tex_formats); i++) 20303b705cfSriastradh if (i8xx_tex_formats[i].fmt == p->format) 20403b705cfSriastradh return true; 20503b705cfSriastradh 20603b705cfSriastradh if (sna->kgem.gen > 021) { 20703b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i85x_tex_formats); i++) 20803b705cfSriastradh if (i85x_tex_formats[i].fmt == p->format) 20903b705cfSriastradh return true; 21003b705cfSriastradh } 21103b705cfSriastradh 21203b705cfSriastradh return false; 21303b705cfSriastradh} 21403b705cfSriastradh 21503b705cfSriastradhstatic uint32_t 21603b705cfSriastradhgen2_sampler_tiling_bits(uint32_t tiling) 21703b705cfSriastradh{ 21803b705cfSriastradh uint32_t bits = 0; 21903b705cfSriastradh switch (tiling) { 22003b705cfSriastradh default: 22103b705cfSriastradh assert(0); 22203b705cfSriastradh case I915_TILING_Y: 22303b705cfSriastradh bits |= TM0S1_TILE_WALK; 22403b705cfSriastradh case I915_TILING_X: 22503b705cfSriastradh bits |= TM0S1_TILED_SURFACE; 22603b705cfSriastradh case I915_TILING_NONE: 22703b705cfSriastradh break; 22803b705cfSriastradh } 22903b705cfSriastradh return bits; 23003b705cfSriastradh} 23103b705cfSriastradh 23203b705cfSriastradhstatic bool 23303b705cfSriastradhgen2_check_filter(PicturePtr picture) 23403b705cfSriastradh{ 23503b705cfSriastradh switch (picture->filter) { 23603b705cfSriastradh case PictFilterNearest: 23703b705cfSriastradh case PictFilterBilinear: 23803b705cfSriastradh return true; 23903b705cfSriastradh default: 24003b705cfSriastradh return false; 24103b705cfSriastradh } 24203b705cfSriastradh} 24303b705cfSriastradh 24403b705cfSriastradhstatic bool 24503b705cfSriastradhgen2_check_repeat(PicturePtr picture) 24603b705cfSriastradh{ 24703b705cfSriastradh if (!picture->repeat) 24803b705cfSriastradh return true; 24903b705cfSriastradh 25003b705cfSriastradh switch (picture->repeatType) { 25103b705cfSriastradh case RepeatNone: 25203b705cfSriastradh case RepeatNormal: 25303b705cfSriastradh case RepeatPad: 25403b705cfSriastradh case RepeatReflect: 25503b705cfSriastradh return true; 25603b705cfSriastradh default: 25703b705cfSriastradh return false; 25803b705cfSriastradh } 25903b705cfSriastradh} 26003b705cfSriastradh 26103b705cfSriastradhstatic void 26203b705cfSriastradhgen2_emit_texture(struct sna *sna, 26303b705cfSriastradh const struct sna_composite_channel *channel, 26403b705cfSriastradh int unit) 26503b705cfSriastradh{ 26603b705cfSriastradh uint32_t wrap_mode_u, wrap_mode_v; 26703b705cfSriastradh uint32_t texcoordtype; 26803b705cfSriastradh uint32_t filter; 26903b705cfSriastradh 27042542f5fSchristos assert(channel->bo); 27142542f5fSchristos 27203b705cfSriastradh if (channel->is_affine) 27303b705cfSriastradh texcoordtype = TEXCOORDTYPE_CARTESIAN; 27403b705cfSriastradh else 27503b705cfSriastradh texcoordtype = TEXCOORDTYPE_HOMOGENEOUS; 27603b705cfSriastradh 27703b705cfSriastradh switch (channel->repeat) { 27803b705cfSriastradh default: 27903b705cfSriastradh assert(0); 28003b705cfSriastradh case RepeatNone: 28103b705cfSriastradh wrap_mode_u = TEXCOORDMODE_CLAMP_BORDER; 28203b705cfSriastradh break; 28303b705cfSriastradh case RepeatNormal: 28403b705cfSriastradh wrap_mode_u = TEXCOORDMODE_WRAP; 28503b705cfSriastradh break; 28603b705cfSriastradh case RepeatPad: 28703b705cfSriastradh wrap_mode_u = TEXCOORDMODE_CLAMP; 28803b705cfSriastradh break; 28903b705cfSriastradh case RepeatReflect: 29003b705cfSriastradh wrap_mode_u = TEXCOORDMODE_MIRROR; 29103b705cfSriastradh break; 29203b705cfSriastradh } 29303b705cfSriastradh if (channel->is_linear) 29403b705cfSriastradh wrap_mode_v = TEXCOORDMODE_WRAP; 29503b705cfSriastradh else 29603b705cfSriastradh wrap_mode_v = wrap_mode_u; 29703b705cfSriastradh 29803b705cfSriastradh switch (channel->filter) { 29903b705cfSriastradh default: 30003b705cfSriastradh assert(0); 30103b705cfSriastradh case PictFilterNearest: 30203b705cfSriastradh filter = (FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT | 30303b705cfSriastradh FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT | 30403b705cfSriastradh MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT); 30503b705cfSriastradh break; 30603b705cfSriastradh case PictFilterBilinear: 30703b705cfSriastradh filter = (FILTER_LINEAR << TM0S3_MAG_FILTER_SHIFT | 30803b705cfSriastradh FILTER_LINEAR << TM0S3_MIN_FILTER_SHIFT | 30903b705cfSriastradh MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT); 31003b705cfSriastradh break; 31103b705cfSriastradh } 31203b705cfSriastradh 31303b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4); 31403b705cfSriastradh BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch, 31503b705cfSriastradh channel->bo, 31603b705cfSriastradh I915_GEM_DOMAIN_SAMPLER << 16, 31703b705cfSriastradh 0)); 31803b705cfSriastradh BATCH(((channel->height - 1) << TM0S1_HEIGHT_SHIFT) | 31903b705cfSriastradh ((channel->width - 1) << TM0S1_WIDTH_SHIFT) | 32003b705cfSriastradh gen2_get_card_format(sna, channel->pict_format) | 32103b705cfSriastradh gen2_sampler_tiling_bits(channel->bo->tiling)); 32203b705cfSriastradh BATCH((channel->bo->pitch / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D); 32303b705cfSriastradh BATCH(filter); 32403b705cfSriastradh BATCH(0); /* default color */ 32503b705cfSriastradh 32603b705cfSriastradh BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | 32703b705cfSriastradh ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | texcoordtype | 32803b705cfSriastradh ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(wrap_mode_v) | 32903b705cfSriastradh ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode_u)); 33003b705cfSriastradh} 33103b705cfSriastradh 33203b705cfSriastradhstatic void 33303b705cfSriastradhgen2_get_blend_factors(const struct sna_composite_op *op, 33403b705cfSriastradh int blend, 33503b705cfSriastradh uint32_t *c_out, 33603b705cfSriastradh uint32_t *a_out) 33703b705cfSriastradh{ 33803b705cfSriastradh uint32_t cblend, ablend; 33903b705cfSriastradh 34003b705cfSriastradh /* If component alpha is active in the mask and the blend operation 34103b705cfSriastradh * uses the source alpha, then we know we don't need the source 34203b705cfSriastradh * value (otherwise we would have hit a fallback earlier), so we 34303b705cfSriastradh * provide the source alpha (src.A * mask.X) as output color. 34403b705cfSriastradh * Conversely, if CA is set and we don't need the source alpha, then 34503b705cfSriastradh * we produce the source value (src.X * mask.X) and the source alpha 34603b705cfSriastradh * is unused.. Otherwise, we provide the non-CA source value 34703b705cfSriastradh * (src.X * mask.A). 34803b705cfSriastradh * 34903b705cfSriastradh * The PICT_FORMAT_RGB(pict) == 0 fixups are not needed on 855+'s a8 35003b705cfSriastradh * pictures, but we need to implement it for 830/845 and there's no 35103b705cfSriastradh * harm done in leaving it in. 35203b705cfSriastradh */ 35303b705cfSriastradh cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OUTPUT_WRITE_CURRENT; 35403b705cfSriastradh ablend = TB0A_RESULT_SCALE_1X | TB0A_OUTPUT_WRITE_CURRENT; 35503b705cfSriastradh 35603b705cfSriastradh /* Get the source picture's channels into TBx_ARG1 */ 35703b705cfSriastradh if ((op->has_component_alpha && gen2_blend_op[blend].src_alpha) || 35803b705cfSriastradh op->dst.format == PICT_a8) { 35903b705cfSriastradh /* Producing source alpha value, so the first set of channels 36003b705cfSriastradh * is src.A instead of src.X. We also do this if the destination 36103b705cfSriastradh * is a8, in which case src.G is what's written, and the other 36203b705cfSriastradh * channels are ignored. 36303b705cfSriastradh */ 36442542f5fSchristos if (op->src.is_opaque) { 36542542f5fSchristos ablend |= TB0C_ARG1_SEL_ONE; 36642542f5fSchristos cblend |= TB0C_ARG1_SEL_ONE; 36742542f5fSchristos } else if (op->src.is_solid) { 36842542f5fSchristos ablend |= TB0C_ARG1_SEL_DIFFUSE; 36903b705cfSriastradh cblend |= TB0C_ARG1_SEL_DIFFUSE | TB0C_ARG1_REPLICATE_ALPHA; 37003b705cfSriastradh } else { 37142542f5fSchristos ablend |= TB0C_ARG1_SEL_TEXEL0; 37203b705cfSriastradh cblend |= TB0C_ARG1_SEL_TEXEL0 | TB0C_ARG1_REPLICATE_ALPHA; 37303b705cfSriastradh } 37403b705cfSriastradh } else { 37503b705cfSriastradh if (op->src.is_solid) 37603b705cfSriastradh cblend |= TB0C_ARG1_SEL_DIFFUSE; 37703b705cfSriastradh else if (PICT_FORMAT_RGB(op->src.pict_format) != 0) 37803b705cfSriastradh cblend |= TB0C_ARG1_SEL_TEXEL0; 37903b705cfSriastradh else 38003b705cfSriastradh cblend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT; /* 0.0 */ 38142542f5fSchristos 38242542f5fSchristos if (op->src.is_opaque) 38303b705cfSriastradh ablend |= TB0A_ARG1_SEL_ONE; 38442542f5fSchristos else if (op->src.is_solid) 38542542f5fSchristos ablend |= TB0A_ARG1_SEL_DIFFUSE; 38603b705cfSriastradh else 38703b705cfSriastradh ablend |= TB0A_ARG1_SEL_TEXEL0; 38803b705cfSriastradh } 38903b705cfSriastradh 39003b705cfSriastradh if (op->mask.bo) { 39103b705cfSriastradh if (op->src.is_solid) { 39203b705cfSriastradh cblend |= TB0C_ARG2_SEL_TEXEL0; 39303b705cfSriastradh ablend |= TB0A_ARG2_SEL_TEXEL0; 39403b705cfSriastradh } else { 39503b705cfSriastradh cblend |= TB0C_ARG2_SEL_TEXEL1; 39603b705cfSriastradh ablend |= TB0A_ARG2_SEL_TEXEL1; 39703b705cfSriastradh } 39803b705cfSriastradh 39903b705cfSriastradh if (op->dst.format == PICT_a8 || !op->has_component_alpha) 40003b705cfSriastradh cblend |= TB0C_ARG2_REPLICATE_ALPHA; 40103b705cfSriastradh 40203b705cfSriastradh cblend |= TB0C_OP_MODULATE; 40303b705cfSriastradh ablend |= TB0A_OP_MODULATE; 40403b705cfSriastradh } else if (op->mask.is_solid) { 40503b705cfSriastradh cblend |= TB0C_ARG2_SEL_DIFFUSE; 40603b705cfSriastradh ablend |= TB0A_ARG2_SEL_DIFFUSE; 40703b705cfSriastradh 40803b705cfSriastradh if (op->dst.format == PICT_a8 || !op->has_component_alpha) 40903b705cfSriastradh cblend |= TB0C_ARG2_REPLICATE_ALPHA; 41003b705cfSriastradh 41103b705cfSriastradh cblend |= TB0C_OP_MODULATE; 41203b705cfSriastradh ablend |= TB0A_OP_MODULATE; 41303b705cfSriastradh } else { 41403b705cfSriastradh cblend |= TB0C_OP_ARG1; 41503b705cfSriastradh ablend |= TB0A_OP_ARG1; 41603b705cfSriastradh } 41703b705cfSriastradh 41803b705cfSriastradh *c_out = cblend; 41903b705cfSriastradh *a_out = ablend; 42003b705cfSriastradh} 42103b705cfSriastradh 42203b705cfSriastradhstatic uint32_t gen2_get_blend_cntl(int op, 42303b705cfSriastradh bool has_component_alpha, 42403b705cfSriastradh uint32_t dst_format) 42503b705cfSriastradh{ 42603b705cfSriastradh uint32_t sblend, dblend; 42703b705cfSriastradh 42803b705cfSriastradh if (op <= PictOpSrc) 42903b705cfSriastradh return S8_ENABLE_COLOR_BUFFER_WRITE; 43003b705cfSriastradh 43103b705cfSriastradh sblend = gen2_blend_op[op].src_blend; 43203b705cfSriastradh dblend = gen2_blend_op[op].dst_blend; 43303b705cfSriastradh 43442542f5fSchristos if (gen2_blend_op[op].dst_alpha) { 43542542f5fSchristos /* If there's no dst alpha channel, adjust the blend op so that 43642542f5fSchristos * we'll treat it as always 1. 43742542f5fSchristos */ 43842542f5fSchristos if (PICT_FORMAT_A(dst_format) == 0) { 43942542f5fSchristos if (sblend == BLENDFACTOR_DST_ALPHA) 44042542f5fSchristos sblend = BLENDFACTOR_ONE; 44142542f5fSchristos else if (sblend == BLENDFACTOR_INV_DST_ALPHA) 44242542f5fSchristos sblend = BLENDFACTOR_ZERO; 44342542f5fSchristos } 44442542f5fSchristos 44542542f5fSchristos /* gen2 engine reads 8bit color buffer into green channel 44642542f5fSchristos * in cases like color buffer blending etc., and also writes 44742542f5fSchristos * back green channel. So with dst_alpha blend we should use 44842542f5fSchristos * color factor. 44942542f5fSchristos */ 45042542f5fSchristos if (dst_format == PICT_a8) { 45142542f5fSchristos if (sblend == BLENDFACTOR_DST_ALPHA) 45242542f5fSchristos sblend = BLENDFACTOR_DST_COLR; 45342542f5fSchristos else if (sblend == BLENDFACTOR_INV_DST_ALPHA) 45442542f5fSchristos sblend = BLENDFACTOR_INV_DST_COLR; 45542542f5fSchristos } 45603b705cfSriastradh } 45703b705cfSriastradh 45803b705cfSriastradh /* If the source alpha is being used, then we should only be in a case 45903b705cfSriastradh * where the source blend factor is 0, and the source blend value is 46003b705cfSriastradh * the mask channels multiplied by the source picture's alpha. 46103b705cfSriastradh */ 46203b705cfSriastradh if (has_component_alpha && gen2_blend_op[op].src_alpha) { 46303b705cfSriastradh if (dblend == BLENDFACTOR_SRC_ALPHA) 46403b705cfSriastradh dblend = BLENDFACTOR_SRC_COLR; 46503b705cfSriastradh else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) 46603b705cfSriastradh dblend = BLENDFACTOR_INV_SRC_COLR; 46703b705cfSriastradh } 46803b705cfSriastradh 46903b705cfSriastradh return (sblend << S8_SRC_BLEND_FACTOR_SHIFT | 47003b705cfSriastradh dblend << S8_DST_BLEND_FACTOR_SHIFT | 47103b705cfSriastradh S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | 47203b705cfSriastradh S8_ENABLE_COLOR_BUFFER_WRITE); 47303b705cfSriastradh} 47403b705cfSriastradh 47503b705cfSriastradhstatic void gen2_emit_invariant(struct sna *sna) 47603b705cfSriastradh{ 47703b705cfSriastradh int i; 47803b705cfSriastradh 47903b705cfSriastradh for (i = 0; i < 4; i++) { 48003b705cfSriastradh BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(i)); 48103b705cfSriastradh BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | MAP_UNIT(i) | 48203b705cfSriastradh DISABLE_TEX_STREAM_BUMP | 48303b705cfSriastradh ENABLE_TEX_STREAM_COORD_SET | TEX_STREAM_COORD_SET(i) | 48403b705cfSriastradh ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(i)); 48503b705cfSriastradh BATCH(_3DSTATE_MAP_COORD_TRANSFORM); 48603b705cfSriastradh BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(i)); 48703b705cfSriastradh } 48803b705cfSriastradh 48903b705cfSriastradh BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD); 49003b705cfSriastradh BATCH(TEXBIND_SET3(TEXCOORDSRC_VTXSET_3) | 49103b705cfSriastradh TEXBIND_SET2(TEXCOORDSRC_VTXSET_2) | 49203b705cfSriastradh TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) | 49303b705cfSriastradh TEXBIND_SET0(TEXCOORDSRC_VTXSET_0)); 49403b705cfSriastradh 49503b705cfSriastradh BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); 49603b705cfSriastradh 49703b705cfSriastradh BATCH(_3DSTATE_VERTEX_TRANSFORM); 49803b705cfSriastradh BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE); 49903b705cfSriastradh 50003b705cfSriastradh BATCH(_3DSTATE_W_STATE_CMD); 50103b705cfSriastradh BATCH(MAGIC_W_STATE_DWORD1); 50203b705cfSriastradh BATCH_F(1.0); 50303b705cfSriastradh 50403b705cfSriastradh BATCH(_3DSTATE_INDPT_ALPHA_BLEND_CMD | 50503b705cfSriastradh DISABLE_INDPT_ALPHA_BLEND | 50603b705cfSriastradh ENABLE_ALPHA_BLENDFUNC | ABLENDFUNC_ADD); 50703b705cfSriastradh 50803b705cfSriastradh BATCH(_3DSTATE_CONST_BLEND_COLOR_CMD); 50903b705cfSriastradh BATCH(0); 51003b705cfSriastradh 51103b705cfSriastradh BATCH(_3DSTATE_MODES_1_CMD | 51203b705cfSriastradh ENABLE_COLR_BLND_FUNC | BLENDFUNC_ADD | 51303b705cfSriastradh ENABLE_SRC_BLND_FACTOR | SRC_BLND_FACT(BLENDFACTOR_ONE) | 51403b705cfSriastradh ENABLE_DST_BLND_FACTOR | DST_BLND_FACT(BLENDFACTOR_ZERO)); 51503b705cfSriastradh 51603b705cfSriastradh BATCH(_3DSTATE_ENABLES_1_CMD | 51703b705cfSriastradh DISABLE_LOGIC_OP | 51803b705cfSriastradh DISABLE_STENCIL_TEST | 51903b705cfSriastradh DISABLE_DEPTH_BIAS | 52003b705cfSriastradh DISABLE_SPEC_ADD | 52103b705cfSriastradh DISABLE_FOG | 52203b705cfSriastradh DISABLE_ALPHA_TEST | 52303b705cfSriastradh DISABLE_DEPTH_TEST | 52403b705cfSriastradh ENABLE_COLOR_BLEND); 52503b705cfSriastradh 52603b705cfSriastradh BATCH(_3DSTATE_ENABLES_2_CMD | 52703b705cfSriastradh DISABLE_STENCIL_WRITE | 52803b705cfSriastradh DISABLE_DITHER | 52903b705cfSriastradh DISABLE_DEPTH_WRITE | 53003b705cfSriastradh ENABLE_COLOR_MASK | 53103b705cfSriastradh ENABLE_COLOR_WRITE | 53203b705cfSriastradh ENABLE_TEX_CACHE); 53303b705cfSriastradh 53403b705cfSriastradh BATCH(_3DSTATE_STIPPLE); 53503b705cfSriastradh BATCH(0); 53603b705cfSriastradh 53703b705cfSriastradh BATCH(_3DSTATE_MAP_BLEND_OP_CMD(0) | 53803b705cfSriastradh TEXPIPE_COLOR | 53903b705cfSriastradh ENABLE_TEXOUTPUT_WRT_SEL | 54003b705cfSriastradh TEXOP_OUTPUT_CURRENT | 54103b705cfSriastradh DISABLE_TEX_CNTRL_STAGE | 54203b705cfSriastradh TEXOP_SCALE_1X | 54303b705cfSriastradh TEXOP_MODIFY_PARMS | TEXOP_LAST_STAGE | 54403b705cfSriastradh TEXBLENDOP_ARG1); 54503b705cfSriastradh BATCH(_3DSTATE_MAP_BLEND_OP_CMD(0) | 54603b705cfSriastradh TEXPIPE_ALPHA | 54703b705cfSriastradh ENABLE_TEXOUTPUT_WRT_SEL | 54803b705cfSriastradh TEXOP_OUTPUT_CURRENT | 54903b705cfSriastradh TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | 55003b705cfSriastradh TEXBLENDOP_ARG1); 55103b705cfSriastradh BATCH(_3DSTATE_MAP_BLEND_ARG_CMD(0) | 55203b705cfSriastradh TEXPIPE_COLOR | 55303b705cfSriastradh TEXBLEND_ARG1 | 55403b705cfSriastradh TEXBLENDARG_MODIFY_PARMS | 55503b705cfSriastradh TEXBLENDARG_DIFFUSE); 55603b705cfSriastradh BATCH(_3DSTATE_MAP_BLEND_ARG_CMD(0) | 55703b705cfSriastradh TEXPIPE_ALPHA | 55803b705cfSriastradh TEXBLEND_ARG1 | 55903b705cfSriastradh TEXBLENDARG_MODIFY_PARMS | 56003b705cfSriastradh TEXBLENDARG_DIFFUSE); 56103b705cfSriastradh 56203b705cfSriastradh#define INVARIANT_SIZE 35 56303b705cfSriastradh 56403b705cfSriastradh sna->render_state.gen2.need_invariant = false; 56503b705cfSriastradh} 56603b705cfSriastradh 56703b705cfSriastradhstatic void 56803b705cfSriastradhgen2_get_batch(struct sna *sna, const struct sna_composite_op *op) 56903b705cfSriastradh{ 57003b705cfSriastradh kgem_set_mode(&sna->kgem, KGEM_RENDER, op->dst.bo); 57103b705cfSriastradh 572fe8aea9eSmrg /* +7 for i830 3DSTATE_BUFFER_INFO w/a */ 573fe8aea9eSmrg if (!kgem_check_batch(&sna->kgem, INVARIANT_SIZE+40+7)) { 57403b705cfSriastradh DBG(("%s: flushing batch: size %d > %d\n", 57503b705cfSriastradh __FUNCTION__, INVARIANT_SIZE+40, 57603b705cfSriastradh sna->kgem.surface-sna->kgem.nbatch)); 57703b705cfSriastradh kgem_submit(&sna->kgem); 57803b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 57903b705cfSriastradh } 58003b705cfSriastradh 58103b705cfSriastradh if (!kgem_check_reloc(&sna->kgem, 3)) { 58203b705cfSriastradh DBG(("%s: flushing batch: reloc %d >= %d\n", 58303b705cfSriastradh __FUNCTION__, 58403b705cfSriastradh sna->kgem.nreloc + 3, 58503b705cfSriastradh (int)KGEM_RELOC_SIZE(&sna->kgem))); 58603b705cfSriastradh kgem_submit(&sna->kgem); 58703b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 58803b705cfSriastradh } 58903b705cfSriastradh 59003b705cfSriastradh if (!kgem_check_exec(&sna->kgem, 3)) { 59103b705cfSriastradh DBG(("%s: flushing batch: exec %d >= %d\n", 59203b705cfSriastradh __FUNCTION__, 59303b705cfSriastradh sna->kgem.nexec + 1, 59403b705cfSriastradh (int)KGEM_EXEC_SIZE(&sna->kgem))); 59503b705cfSriastradh kgem_submit(&sna->kgem); 59603b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 59703b705cfSriastradh } 59803b705cfSriastradh 59903b705cfSriastradh if (sna->render_state.gen2.need_invariant) 60003b705cfSriastradh gen2_emit_invariant(sna); 60103b705cfSriastradh} 60203b705cfSriastradh 603fe8aea9eSmrgstatic void gen2_emit_target(struct sna *sna, 604fe8aea9eSmrg struct kgem_bo *bo, 605fe8aea9eSmrg int width, 606fe8aea9eSmrg int height, 607fe8aea9eSmrg int format) 60803b705cfSriastradh{ 609fe8aea9eSmrg assert(!too_large(width, height)); 610fe8aea9eSmrg assert(bo->pitch >= 8 && bo->pitch <= MAX_3D_PITCH); 61103b705cfSriastradh assert(sna->render.vertex_offset == 0); 61203b705cfSriastradh 613fe8aea9eSmrg assert(bo->unique_id); 614fe8aea9eSmrg if (sna->render_state.gen2.target == bo->unique_id) { 615fe8aea9eSmrg kgem_bo_mark_dirty(bo); 61603b705cfSriastradh return; 61703b705cfSriastradh } 61803b705cfSriastradh 619fe8aea9eSmrg /* 620fe8aea9eSmrg * i830 w/a: 3DSTATE_BUFFER_INFO 621fe8aea9eSmrg * must not straddle two cachelines. 622fe8aea9eSmrg */ 623fe8aea9eSmrg if (intel_get_device_id(sna->dev) == 0x3577) 624fe8aea9eSmrg BATCH_ALIGNED(_3DSTATE_BUF_INFO_CMD, 8); 625fe8aea9eSmrg else 626fe8aea9eSmrg BATCH(_3DSTATE_BUF_INFO_CMD); 62703b705cfSriastradh BATCH(BUF_3D_ID_COLOR_BACK | 628fe8aea9eSmrg gen2_buf_tiling(bo->tiling) | 629fe8aea9eSmrg BUF_3D_PITCH(bo->pitch)); 63003b705cfSriastradh BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch, 631fe8aea9eSmrg bo, 63203b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 63303b705cfSriastradh I915_GEM_DOMAIN_RENDER, 63403b705cfSriastradh 0)); 63503b705cfSriastradh 63603b705cfSriastradh BATCH(_3DSTATE_DST_BUF_VARS_CMD); 637fe8aea9eSmrg BATCH(gen2_get_dst_format(format)); 63803b705cfSriastradh 63903b705cfSriastradh BATCH(_3DSTATE_DRAW_RECT_CMD); 64003b705cfSriastradh BATCH(0); 64103b705cfSriastradh BATCH(0); /* ymin, xmin */ 642fe8aea9eSmrg BATCH(DRAW_YMAX(height - 1) | 643fe8aea9eSmrg DRAW_XMAX(width - 1)); 64403b705cfSriastradh BATCH(0); /* yorig, xorig */ 64503b705cfSriastradh 646fe8aea9eSmrg sna->render_state.gen2.target = bo->unique_id; 64703b705cfSriastradh} 64803b705cfSriastradh 64903b705cfSriastradhstatic void gen2_disable_logic_op(struct sna *sna) 65003b705cfSriastradh{ 65103b705cfSriastradh if (!sna->render_state.gen2.logic_op_enabled) 65203b705cfSriastradh return; 65303b705cfSriastradh 65403b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 65503b705cfSriastradh 65603b705cfSriastradh BATCH(_3DSTATE_ENABLES_1_CMD | 65703b705cfSriastradh DISABLE_LOGIC_OP | ENABLE_COLOR_BLEND); 65803b705cfSriastradh 65903b705cfSriastradh sna->render_state.gen2.logic_op_enabled = 0; 66003b705cfSriastradh} 66103b705cfSriastradh 66203b705cfSriastradhstatic void gen2_enable_logic_op(struct sna *sna, int op) 66303b705cfSriastradh{ 66403b705cfSriastradh static const uint8_t logic_op[] = { 66503b705cfSriastradh LOGICOP_CLEAR, /* GXclear */ 66603b705cfSriastradh LOGICOP_AND, /* GXand */ 66703b705cfSriastradh LOGICOP_AND_RVRSE, /* GXandReverse */ 66803b705cfSriastradh LOGICOP_COPY, /* GXcopy */ 66903b705cfSriastradh LOGICOP_AND_INV, /* GXandInverted */ 67003b705cfSriastradh LOGICOP_NOOP, /* GXnoop */ 67103b705cfSriastradh LOGICOP_XOR, /* GXxor */ 67203b705cfSriastradh LOGICOP_OR, /* GXor */ 67303b705cfSriastradh LOGICOP_NOR, /* GXnor */ 67403b705cfSriastradh LOGICOP_EQUIV, /* GXequiv */ 67503b705cfSriastradh LOGICOP_INV, /* GXinvert */ 67603b705cfSriastradh LOGICOP_OR_RVRSE, /* GXorReverse */ 67703b705cfSriastradh LOGICOP_COPY_INV, /* GXcopyInverted */ 67803b705cfSriastradh LOGICOP_OR_INV, /* GXorInverted */ 67903b705cfSriastradh LOGICOP_NAND, /* GXnand */ 68003b705cfSriastradh LOGICOP_SET /* GXset */ 68103b705cfSriastradh }; 68203b705cfSriastradh 68303b705cfSriastradh if (sna->render_state.gen2.logic_op_enabled != op+1) { 68403b705cfSriastradh if (!sna->render_state.gen2.logic_op_enabled) { 68503b705cfSriastradh if (op == GXclear || op == GXcopy) 68603b705cfSriastradh return; 68703b705cfSriastradh 68803b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 68903b705cfSriastradh 69003b705cfSriastradh BATCH(_3DSTATE_ENABLES_1_CMD | 69103b705cfSriastradh ENABLE_LOGIC_OP | DISABLE_COLOR_BLEND); 69203b705cfSriastradh } 69303b705cfSriastradh 69403b705cfSriastradh BATCH(_3DSTATE_MODES_4_CMD | 69503b705cfSriastradh ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(logic_op[op])); 69603b705cfSriastradh sna->render_state.gen2.logic_op_enabled = op+1; 69703b705cfSriastradh } 69803b705cfSriastradh} 69903b705cfSriastradh 70003b705cfSriastradhstatic void gen2_emit_composite_state(struct sna *sna, 70103b705cfSriastradh const struct sna_composite_op *op) 70203b705cfSriastradh{ 70303b705cfSriastradh uint32_t texcoordfmt, v, unwind; 70403b705cfSriastradh uint32_t cblend, ablend; 70503b705cfSriastradh int tex; 70603b705cfSriastradh 70703b705cfSriastradh gen2_get_batch(sna, op); 70803b705cfSriastradh 70903b705cfSriastradh if (kgem_bo_is_dirty(op->src.bo) || kgem_bo_is_dirty(op->mask.bo)) { 71003b705cfSriastradh if (op->src.bo == op->dst.bo || op->mask.bo == op->dst.bo) 71103b705cfSriastradh BATCH(MI_FLUSH | MI_INVALIDATE_MAP_CACHE); 71203b705cfSriastradh else 71303b705cfSriastradh BATCH(_3DSTATE_MODES_5_CMD | 71403b705cfSriastradh PIPELINE_FLUSH_RENDER_CACHE | 71503b705cfSriastradh PIPELINE_FLUSH_TEXTURE_CACHE); 71603b705cfSriastradh kgem_clear_dirty(&sna->kgem); 71703b705cfSriastradh } 71803b705cfSriastradh 719fe8aea9eSmrg gen2_emit_target(sna, 720fe8aea9eSmrg op->dst.bo, 721fe8aea9eSmrg op->dst.width, 722fe8aea9eSmrg op->dst.height, 723fe8aea9eSmrg op->dst.format); 72403b705cfSriastradh 72503b705cfSriastradh unwind = sna->kgem.nbatch; 72603b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 72703b705cfSriastradh I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2); 72803b705cfSriastradh BATCH((!op->src.is_solid + (op->mask.bo != NULL)) << 12); 72903b705cfSriastradh BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY); 73003b705cfSriastradh BATCH(gen2_get_blend_cntl(op->op, 73103b705cfSriastradh op->has_component_alpha, 73203b705cfSriastradh op->dst.format)); 73303b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1, 73403b705cfSriastradh sna->kgem.batch + unwind + 1, 73503b705cfSriastradh 3 * sizeof(uint32_t)) == 0) 73603b705cfSriastradh sna->kgem.nbatch = unwind; 73703b705cfSriastradh else 73803b705cfSriastradh sna->render_state.gen2.ls1 = unwind; 73903b705cfSriastradh 74003b705cfSriastradh gen2_disable_logic_op(sna); 74103b705cfSriastradh 74203b705cfSriastradh gen2_get_blend_factors(op, op->op, &cblend, &ablend); 74303b705cfSriastradh unwind = sna->kgem.nbatch; 74403b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 74503b705cfSriastradh LOAD_TEXTURE_BLEND_STAGE(0) | 1); 74603b705cfSriastradh BATCH(cblend); 74703b705cfSriastradh BATCH(ablend); 74803b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1, 74903b705cfSriastradh sna->kgem.batch + unwind + 1, 75003b705cfSriastradh 2 * sizeof(uint32_t)) == 0) 75103b705cfSriastradh sna->kgem.nbatch = unwind; 75203b705cfSriastradh else 75303b705cfSriastradh sna->render_state.gen2.ls2 = unwind; 75403b705cfSriastradh 75503b705cfSriastradh tex = texcoordfmt = 0; 75603b705cfSriastradh if (!op->src.is_solid) { 75703b705cfSriastradh if (op->src.is_affine) 75803b705cfSriastradh texcoordfmt |= TEXCOORDFMT_2D << (2*tex); 75903b705cfSriastradh else 76003b705cfSriastradh texcoordfmt |= TEXCOORDFMT_3D << (2*tex); 76103b705cfSriastradh gen2_emit_texture(sna, &op->src, tex++); 76203b705cfSriastradh } else { 76303b705cfSriastradh if (op->src.u.gen2.pixel != sna->render_state.gen2.diffuse) { 76403b705cfSriastradh BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); 76503b705cfSriastradh BATCH(op->src.u.gen2.pixel); 76603b705cfSriastradh sna->render_state.gen2.diffuse = op->src.u.gen2.pixel; 76703b705cfSriastradh } 76803b705cfSriastradh } 76903b705cfSriastradh if (op->mask.bo) { 77003b705cfSriastradh if (op->mask.is_affine) 77103b705cfSriastradh texcoordfmt |= TEXCOORDFMT_2D << (2*tex); 77203b705cfSriastradh else 77303b705cfSriastradh texcoordfmt |= TEXCOORDFMT_3D << (2*tex); 77403b705cfSriastradh gen2_emit_texture(sna, &op->mask, tex++); 77503b705cfSriastradh } else if (op->mask.is_solid) { 77603b705cfSriastradh if (op->mask.u.gen2.pixel != sna->render_state.gen2.diffuse) { 77703b705cfSriastradh BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); 77803b705cfSriastradh BATCH(op->mask.u.gen2.pixel); 77903b705cfSriastradh sna->render_state.gen2.diffuse = op->mask.u.gen2.pixel; 78003b705cfSriastradh } 78103b705cfSriastradh } 78203b705cfSriastradh 78303b705cfSriastradh v = _3DSTATE_VERTEX_FORMAT_2_CMD | texcoordfmt; 78403b705cfSriastradh if (sna->render_state.gen2.vft != v) { 78503b705cfSriastradh BATCH(v); 78603b705cfSriastradh sna->render_state.gen2.vft = v; 78703b705cfSriastradh } 78803b705cfSriastradh} 78903b705cfSriastradh 79003b705cfSriastradhstatic inline void 79103b705cfSriastradhgen2_emit_composite_dstcoord(struct sna *sna, int dstX, int dstY) 79203b705cfSriastradh{ 79303b705cfSriastradh VERTEX(dstX); 79403b705cfSriastradh VERTEX(dstY); 79503b705cfSriastradh} 79603b705cfSriastradh 79703b705cfSriastradhinline static void 79803b705cfSriastradhgen2_emit_composite_linear(struct sna *sna, 79903b705cfSriastradh const struct sna_composite_channel *channel, 80003b705cfSriastradh int16_t x, int16_t y) 80103b705cfSriastradh{ 80203b705cfSriastradh float v; 80303b705cfSriastradh 80403b705cfSriastradh v = (x * channel->u.linear.dx + 80503b705cfSriastradh y * channel->u.linear.dy + 80603b705cfSriastradh channel->u.linear.offset); 80703b705cfSriastradh DBG(("%s: (%d, %d) -> %f\n", __FUNCTION__, x, y, v)); 80803b705cfSriastradh VERTEX(v); 80903b705cfSriastradh VERTEX(v); 81003b705cfSriastradh} 81103b705cfSriastradh 81203b705cfSriastradhstatic void 81303b705cfSriastradhgen2_emit_composite_texcoord(struct sna *sna, 81403b705cfSriastradh const struct sna_composite_channel *channel, 81503b705cfSriastradh int16_t x, int16_t y) 81603b705cfSriastradh{ 81703b705cfSriastradh float s = 0, t = 0, w = 1; 81803b705cfSriastradh 81903b705cfSriastradh x += channel->offset[0]; 82003b705cfSriastradh y += channel->offset[1]; 82103b705cfSriastradh 82203b705cfSriastradh if (channel->is_affine) { 82303b705cfSriastradh sna_get_transformed_coordinates(x, y, 82403b705cfSriastradh channel->transform, 82503b705cfSriastradh &s, &t); 82603b705cfSriastradh VERTEX(s * channel->scale[0]); 82703b705cfSriastradh VERTEX(t * channel->scale[1]); 82803b705cfSriastradh } else { 82903b705cfSriastradh sna_get_transformed_coordinates_3d(x, y, 83003b705cfSriastradh channel->transform, 83103b705cfSriastradh &s, &t, &w); 83203b705cfSriastradh VERTEX(s * channel->scale[0]); 83303b705cfSriastradh VERTEX(t * channel->scale[1]); 83403b705cfSriastradh VERTEX(w); 83503b705cfSriastradh } 83603b705cfSriastradh} 83703b705cfSriastradh 83803b705cfSriastradhstatic void 83903b705cfSriastradhgen2_emit_composite_vertex(struct sna *sna, 84003b705cfSriastradh const struct sna_composite_op *op, 84103b705cfSriastradh int16_t srcX, int16_t srcY, 84203b705cfSriastradh int16_t mskX, int16_t mskY, 84303b705cfSriastradh int16_t dstX, int16_t dstY) 84403b705cfSriastradh{ 84503b705cfSriastradh gen2_emit_composite_dstcoord(sna, dstX, dstY); 84603b705cfSriastradh if (op->src.is_linear) 84703b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, srcX, srcY); 84803b705cfSriastradh else if (!op->src.is_solid) 84903b705cfSriastradh gen2_emit_composite_texcoord(sna, &op->src, srcX, srcY); 85003b705cfSriastradh 85103b705cfSriastradh if (op->mask.is_linear) 85203b705cfSriastradh gen2_emit_composite_linear(sna, &op->mask, mskX, mskY); 85303b705cfSriastradh else if (op->mask.bo) 85403b705cfSriastradh gen2_emit_composite_texcoord(sna, &op->mask, mskX, mskY); 85503b705cfSriastradh} 85603b705cfSriastradh 85703b705cfSriastradhfastcall static void 85803b705cfSriastradhgen2_emit_composite_primitive(struct sna *sna, 85903b705cfSriastradh const struct sna_composite_op *op, 86003b705cfSriastradh const struct sna_composite_rectangles *r) 86103b705cfSriastradh{ 86203b705cfSriastradh gen2_emit_composite_vertex(sna, op, 86303b705cfSriastradh r->src.x + r->width, 86403b705cfSriastradh r->src.y + r->height, 86503b705cfSriastradh r->mask.x + r->width, 86603b705cfSriastradh r->mask.y + r->height, 86703b705cfSriastradh op->dst.x + r->dst.x + r->width, 86803b705cfSriastradh op->dst.y + r->dst.y + r->height); 86903b705cfSriastradh gen2_emit_composite_vertex(sna, op, 87003b705cfSriastradh r->src.x, 87103b705cfSriastradh r->src.y + r->height, 87203b705cfSriastradh r->mask.x, 87303b705cfSriastradh r->mask.y + r->height, 87403b705cfSriastradh op->dst.x + r->dst.x, 87503b705cfSriastradh op->dst.y + r->dst.y + r->height); 87603b705cfSriastradh gen2_emit_composite_vertex(sna, op, 87703b705cfSriastradh r->src.x, 87803b705cfSriastradh r->src.y, 87903b705cfSriastradh r->mask.x, 88003b705cfSriastradh r->mask.y, 88103b705cfSriastradh op->dst.x + r->dst.x, 88203b705cfSriastradh op->dst.y + r->dst.y); 88303b705cfSriastradh} 88403b705cfSriastradh 88503b705cfSriastradhfastcall static void 88603b705cfSriastradhgen2_emit_composite_primitive_constant(struct sna *sna, 88703b705cfSriastradh const struct sna_composite_op *op, 88803b705cfSriastradh const struct sna_composite_rectangles *r) 88903b705cfSriastradh{ 89003b705cfSriastradh int16_t dst_x = r->dst.x + op->dst.x; 89103b705cfSriastradh int16_t dst_y = r->dst.y + op->dst.y; 89203b705cfSriastradh 89303b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x + r->width, dst_y + r->height); 89403b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y + r->height); 89503b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y); 89603b705cfSriastradh} 89703b705cfSriastradh 89803b705cfSriastradhfastcall static void 89903b705cfSriastradhgen2_emit_composite_primitive_linear(struct sna *sna, 90003b705cfSriastradh const struct sna_composite_op *op, 90103b705cfSriastradh const struct sna_composite_rectangles *r) 90203b705cfSriastradh{ 90303b705cfSriastradh int16_t dst_x = r->dst.x + op->dst.x; 90403b705cfSriastradh int16_t dst_y = r->dst.y + op->dst.y; 90503b705cfSriastradh 90603b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x + r->width, dst_y + r->height); 90703b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, 90803b705cfSriastradh r->src.x + r->width, r->src.y + r->height); 90903b705cfSriastradh 91003b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y + r->height); 91103b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, 91203b705cfSriastradh r->src.x, r->src.y + r->height); 91303b705cfSriastradh 91403b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y); 91503b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, 91603b705cfSriastradh r->src.x, r->src.y); 91703b705cfSriastradh} 91803b705cfSriastradh 91903b705cfSriastradhfastcall static void 92003b705cfSriastradhgen2_emit_composite_primitive_identity(struct sna *sna, 92103b705cfSriastradh const struct sna_composite_op *op, 92203b705cfSriastradh const struct sna_composite_rectangles *r) 92303b705cfSriastradh{ 92403b705cfSriastradh float w = r->width; 92503b705cfSriastradh float h = r->height; 92603b705cfSriastradh float *v; 92703b705cfSriastradh 92803b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 92903b705cfSriastradh sna->kgem.nbatch += 12; 93003b705cfSriastradh 93103b705cfSriastradh v[8] = v[4] = r->dst.x + op->dst.x; 93203b705cfSriastradh v[0] = v[4] + w; 93303b705cfSriastradh 93403b705cfSriastradh v[9] = r->dst.y + op->dst.y; 93503b705cfSriastradh v[5] = v[1] = v[9] + h; 93603b705cfSriastradh 93703b705cfSriastradh v[10] = v[6] = (r->src.x + op->src.offset[0]) * op->src.scale[0]; 93803b705cfSriastradh v[2] = v[6] + w * op->src.scale[0]; 93903b705cfSriastradh 94003b705cfSriastradh v[11] = (r->src.y + op->src.offset[1]) * op->src.scale[1]; 94103b705cfSriastradh v[7] = v[3] = v[11] + h * op->src.scale[1]; 94203b705cfSriastradh} 94303b705cfSriastradh 94403b705cfSriastradhfastcall static void 94503b705cfSriastradhgen2_emit_composite_primitive_affine(struct sna *sna, 94603b705cfSriastradh const struct sna_composite_op *op, 94703b705cfSriastradh const struct sna_composite_rectangles *r) 94803b705cfSriastradh{ 94903b705cfSriastradh PictTransform *transform = op->src.transform; 95003b705cfSriastradh int src_x = r->src.x + (int)op->src.offset[0]; 95103b705cfSriastradh int src_y = r->src.y + (int)op->src.offset[1]; 95203b705cfSriastradh float *v; 95303b705cfSriastradh 95403b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 95503b705cfSriastradh sna->kgem.nbatch += 12; 95603b705cfSriastradh 95703b705cfSriastradh v[8] = v[4] = r->dst.x + op->dst.x; 95803b705cfSriastradh v[0] = v[4] + r->width; 95903b705cfSriastradh 96003b705cfSriastradh v[9] = r->dst.y + op->dst.y; 96103b705cfSriastradh v[5] = v[1] = v[9] + r->height; 96203b705cfSriastradh 96303b705cfSriastradh _sna_get_transformed_scaled(src_x + r->width, src_y + r->height, 96403b705cfSriastradh transform, op->src.scale, 96503b705cfSriastradh &v[2], &v[3]); 96603b705cfSriastradh 96703b705cfSriastradh _sna_get_transformed_scaled(src_x, src_y + r->height, 96803b705cfSriastradh transform, op->src.scale, 96903b705cfSriastradh &v[6], &v[7]); 97003b705cfSriastradh 97103b705cfSriastradh _sna_get_transformed_scaled(src_x, src_y, 97203b705cfSriastradh transform, op->src.scale, 97303b705cfSriastradh &v[10], &v[11]); 97403b705cfSriastradh} 97503b705cfSriastradh 97603b705cfSriastradhfastcall static void 97703b705cfSriastradhgen2_emit_composite_primitive_constant_identity_mask(struct sna *sna, 97803b705cfSriastradh const struct sna_composite_op *op, 97903b705cfSriastradh const struct sna_composite_rectangles *r) 98003b705cfSriastradh{ 98103b705cfSriastradh float w = r->width; 98203b705cfSriastradh float h = r->height; 98303b705cfSriastradh float *v; 98403b705cfSriastradh 98503b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 98603b705cfSriastradh sna->kgem.nbatch += 12; 98703b705cfSriastradh 98803b705cfSriastradh v[8] = v[4] = r->dst.x + op->dst.x; 98903b705cfSriastradh v[0] = v[4] + w; 99003b705cfSriastradh 99103b705cfSriastradh v[9] = r->dst.y + op->dst.y; 99203b705cfSriastradh v[5] = v[1] = v[9] + h; 99303b705cfSriastradh 99403b705cfSriastradh v[10] = v[6] = (r->mask.x + op->mask.offset[0]) * op->mask.scale[0]; 99503b705cfSriastradh v[2] = v[6] + w * op->mask.scale[0]; 99603b705cfSriastradh 99703b705cfSriastradh v[11] = (r->mask.y + op->mask.offset[1]) * op->mask.scale[1]; 99803b705cfSriastradh v[7] = v[3] = v[11] + h * op->mask.scale[1]; 99903b705cfSriastradh} 100003b705cfSriastradh 100103b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 100203b705cfSriastradhsse2 fastcall static void 100303b705cfSriastradhgen2_emit_composite_primitive_constant__sse2(struct sna *sna, 100403b705cfSriastradh const struct sna_composite_op *op, 100503b705cfSriastradh const struct sna_composite_rectangles *r) 100603b705cfSriastradh{ 100703b705cfSriastradh int16_t dst_x = r->dst.x + op->dst.x; 100803b705cfSriastradh int16_t dst_y = r->dst.y + op->dst.y; 100903b705cfSriastradh 101003b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x + r->width, dst_y + r->height); 101103b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y + r->height); 101203b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y); 101303b705cfSriastradh} 101403b705cfSriastradh 101503b705cfSriastradhsse2 fastcall static void 101603b705cfSriastradhgen2_emit_composite_primitive_linear__sse2(struct sna *sna, 101703b705cfSriastradh const struct sna_composite_op *op, 101803b705cfSriastradh const struct sna_composite_rectangles *r) 101903b705cfSriastradh{ 102003b705cfSriastradh int16_t dst_x = r->dst.x + op->dst.x; 102103b705cfSriastradh int16_t dst_y = r->dst.y + op->dst.y; 102203b705cfSriastradh 102303b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x + r->width, dst_y + r->height); 102403b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, 102503b705cfSriastradh r->src.x + r->width, r->src.y + r->height); 102603b705cfSriastradh 102703b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y + r->height); 102803b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, 102903b705cfSriastradh r->src.x, r->src.y + r->height); 103003b705cfSriastradh 103103b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y); 103203b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, 103303b705cfSriastradh r->src.x, r->src.y); 103403b705cfSriastradh} 103503b705cfSriastradh 103603b705cfSriastradhsse2 fastcall static void 103703b705cfSriastradhgen2_emit_composite_primitive_identity__sse2(struct sna *sna, 103803b705cfSriastradh const struct sna_composite_op *op, 103903b705cfSriastradh const struct sna_composite_rectangles *r) 104003b705cfSriastradh{ 104103b705cfSriastradh float w = r->width; 104203b705cfSriastradh float h = r->height; 104303b705cfSriastradh float *v; 104403b705cfSriastradh 104503b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 104603b705cfSriastradh sna->kgem.nbatch += 12; 104703b705cfSriastradh 104803b705cfSriastradh v[8] = v[4] = r->dst.x + op->dst.x; 104903b705cfSriastradh v[0] = v[4] + w; 105003b705cfSriastradh 105103b705cfSriastradh v[9] = r->dst.y + op->dst.y; 105203b705cfSriastradh v[5] = v[1] = v[9] + h; 105303b705cfSriastradh 105403b705cfSriastradh v[10] = v[6] = (r->src.x + op->src.offset[0]) * op->src.scale[0]; 105503b705cfSriastradh v[2] = v[6] + w * op->src.scale[0]; 105603b705cfSriastradh 105703b705cfSriastradh v[11] = (r->src.y + op->src.offset[1]) * op->src.scale[1]; 105803b705cfSriastradh v[7] = v[3] = v[11] + h * op->src.scale[1]; 105903b705cfSriastradh} 106003b705cfSriastradh 106103b705cfSriastradhsse2 fastcall static void 106203b705cfSriastradhgen2_emit_composite_primitive_affine__sse2(struct sna *sna, 106303b705cfSriastradh const struct sna_composite_op *op, 106403b705cfSriastradh const struct sna_composite_rectangles *r) 106503b705cfSriastradh{ 106603b705cfSriastradh PictTransform *transform = op->src.transform; 106703b705cfSriastradh int src_x = r->src.x + (int)op->src.offset[0]; 106803b705cfSriastradh int src_y = r->src.y + (int)op->src.offset[1]; 106903b705cfSriastradh float *v; 107003b705cfSriastradh 107103b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 107203b705cfSriastradh sna->kgem.nbatch += 12; 107303b705cfSriastradh 107403b705cfSriastradh v[8] = v[4] = r->dst.x + op->dst.x; 107503b705cfSriastradh v[0] = v[4] + r->width; 107603b705cfSriastradh 107703b705cfSriastradh v[9] = r->dst.y + op->dst.y; 107803b705cfSriastradh v[5] = v[1] = v[9] + r->height; 107903b705cfSriastradh 108003b705cfSriastradh _sna_get_transformed_scaled(src_x + r->width, src_y + r->height, 108103b705cfSriastradh transform, op->src.scale, 108203b705cfSriastradh &v[2], &v[3]); 108303b705cfSriastradh 108403b705cfSriastradh _sna_get_transformed_scaled(src_x, src_y + r->height, 108503b705cfSriastradh transform, op->src.scale, 108603b705cfSriastradh &v[6], &v[7]); 108703b705cfSriastradh 108803b705cfSriastradh _sna_get_transformed_scaled(src_x, src_y, 108903b705cfSriastradh transform, op->src.scale, 109003b705cfSriastradh &v[10], &v[11]); 109103b705cfSriastradh} 109203b705cfSriastradh 109303b705cfSriastradhsse2 fastcall static void 109403b705cfSriastradhgen2_emit_composite_primitive_constant_identity_mask__sse2(struct sna *sna, 109503b705cfSriastradh const struct sna_composite_op *op, 109603b705cfSriastradh const struct sna_composite_rectangles *r) 109703b705cfSriastradh{ 109803b705cfSriastradh float w = r->width; 109903b705cfSriastradh float h = r->height; 110003b705cfSriastradh float *v; 110103b705cfSriastradh 110203b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 110303b705cfSriastradh sna->kgem.nbatch += 12; 110403b705cfSriastradh 110503b705cfSriastradh v[8] = v[4] = r->dst.x + op->dst.x; 110603b705cfSriastradh v[0] = v[4] + w; 110703b705cfSriastradh 110803b705cfSriastradh v[9] = r->dst.y + op->dst.y; 110903b705cfSriastradh v[5] = v[1] = v[9] + h; 111003b705cfSriastradh 111103b705cfSriastradh v[10] = v[6] = (r->mask.x + op->mask.offset[0]) * op->mask.scale[0]; 111203b705cfSriastradh v[2] = v[6] + w * op->mask.scale[0]; 111303b705cfSriastradh 111403b705cfSriastradh v[11] = (r->mask.y + op->mask.offset[1]) * op->mask.scale[1]; 111503b705cfSriastradh v[7] = v[3] = v[11] + h * op->mask.scale[1]; 111603b705cfSriastradh} 111703b705cfSriastradh#endif 111803b705cfSriastradh 111903b705cfSriastradhstatic void gen2_magic_ca_pass(struct sna *sna, 112003b705cfSriastradh const struct sna_composite_op *op) 112103b705cfSriastradh{ 112203b705cfSriastradh uint32_t ablend, cblend, *src, *dst; 112303b705cfSriastradh int n; 112403b705cfSriastradh 112503b705cfSriastradh if (!op->need_magic_ca_pass) 112603b705cfSriastradh return; 112703b705cfSriastradh 112803b705cfSriastradh DBG(("%s: batch=%x, vertex=%x\n", __FUNCTION__, 112903b705cfSriastradh sna->kgem.nbatch, sna->render.vertex_offset)); 113003b705cfSriastradh 113103b705cfSriastradh assert(op->mask.bo); 113203b705cfSriastradh assert(op->has_component_alpha); 113303b705cfSriastradh 113403b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0); 113503b705cfSriastradh BATCH(BLENDFACTOR_ONE << S8_SRC_BLEND_FACTOR_SHIFT | 113603b705cfSriastradh BLENDFACTOR_ONE << S8_DST_BLEND_FACTOR_SHIFT | 113703b705cfSriastradh S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | 113803b705cfSriastradh S8_ENABLE_COLOR_BUFFER_WRITE); 113903b705cfSriastradh sna->render_state.gen2.ls1 = 0; 114003b705cfSriastradh 114103b705cfSriastradh gen2_get_blend_factors(op, PictOpAdd, &cblend, &ablend); 114203b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 114303b705cfSriastradh LOAD_TEXTURE_BLEND_STAGE(0) | 1); 114403b705cfSriastradh BATCH(cblend); 114503b705cfSriastradh BATCH(ablend); 114603b705cfSriastradh sna->render_state.gen2.ls2 = 0; 114703b705cfSriastradh 114803b705cfSriastradh src = sna->kgem.batch + sna->render.vertex_offset; 114903b705cfSriastradh dst = sna->kgem.batch + sna->kgem.nbatch; 115003b705cfSriastradh n = 1 + sna->render.vertex_index; 115103b705cfSriastradh sna->kgem.nbatch += n; 115203b705cfSriastradh assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem)); 115303b705cfSriastradh while (n--) 115403b705cfSriastradh *dst++ = *src++; 115503b705cfSriastradh} 115603b705cfSriastradh 115703b705cfSriastradhstatic void gen2_vertex_flush(struct sna *sna, 115803b705cfSriastradh const struct sna_composite_op *op) 115903b705cfSriastradh{ 116003b705cfSriastradh if (sna->render.vertex_index == 0) 116103b705cfSriastradh return; 116203b705cfSriastradh 116303b705cfSriastradh sna->kgem.batch[sna->render.vertex_offset] |= 116403b705cfSriastradh sna->render.vertex_index - 1; 116503b705cfSriastradh 116603b705cfSriastradh gen2_magic_ca_pass(sna, op); 116703b705cfSriastradh 116803b705cfSriastradh sna->render.vertex_offset = 0; 116903b705cfSriastradh sna->render.vertex_index = 0; 117003b705cfSriastradh} 117103b705cfSriastradh 117203b705cfSriastradhinline static int gen2_get_rectangles(struct sna *sna, 117303b705cfSriastradh const struct sna_composite_op *op, 117403b705cfSriastradh int want) 117503b705cfSriastradh{ 117603b705cfSriastradh int rem = batch_space(sna), size, need; 117703b705cfSriastradh 117803b705cfSriastradh DBG(("%s: want=%d, floats_per_vertex=%d, rem=%d\n", 117903b705cfSriastradh __FUNCTION__, want, op->floats_per_vertex, rem)); 118003b705cfSriastradh 118103b705cfSriastradh assert(op->floats_per_vertex); 118203b705cfSriastradh assert(op->floats_per_rect == 3 * op->floats_per_vertex); 118303b705cfSriastradh 118403b705cfSriastradh need = 1; 118503b705cfSriastradh size = op->floats_per_rect; 118603b705cfSriastradh if (op->need_magic_ca_pass) 118703b705cfSriastradh need += 6 + size*sna->render.vertex_index, size *= 2; 118803b705cfSriastradh 118903b705cfSriastradh DBG(("%s: want=%d, need=%d,size=%d, rem=%d\n", 119003b705cfSriastradh __FUNCTION__, want, need, size, rem)); 119103b705cfSriastradh if (rem < need + size) { 119203b705cfSriastradh gen2_vertex_flush(sna, op); 119303b705cfSriastradh kgem_submit(&sna->kgem); 119403b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 119503b705cfSriastradh return 0; 119603b705cfSriastradh } 119703b705cfSriastradh 119803b705cfSriastradh rem -= need; 119903b705cfSriastradh if (sna->render.vertex_offset == 0) { 120003b705cfSriastradh if ((sna->kgem.batch[sna->kgem.nbatch-1] & ~0xffff) == 120103b705cfSriastradh (PRIM3D_INLINE | PRIM3D_RECTLIST)) { 120203b705cfSriastradh uint32_t *b = &sna->kgem.batch[sna->kgem.nbatch-1]; 120303b705cfSriastradh assert(*b & 0xffff); 120403b705cfSriastradh sna->render.vertex_index = 1 + (*b & 0xffff); 120503b705cfSriastradh *b = PRIM3D_INLINE | PRIM3D_RECTLIST; 120603b705cfSriastradh sna->render.vertex_offset = sna->kgem.nbatch - 1; 120703b705cfSriastradh assert(!op->need_magic_ca_pass); 120803b705cfSriastradh } else { 120903b705cfSriastradh sna->render.vertex_offset = sna->kgem.nbatch; 121003b705cfSriastradh BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST); 121103b705cfSriastradh } 1212fe8aea9eSmrg 1213fe8aea9eSmrg need = 0; 1214fe8aea9eSmrg } else 1215fe8aea9eSmrg need = sna->kgem.nbatch - sna->render.vertex_offset; 1216fe8aea9eSmrg 1217fe8aea9eSmrg if (rem > MAX_INLINE - need) 1218fe8aea9eSmrg rem = MAX_INLINE -need; 121903b705cfSriastradh 122003b705cfSriastradh if (want > 1 && want * size > rem) 122103b705cfSriastradh want = rem / size; 122203b705cfSriastradh 122303b705cfSriastradh assert(want); 122403b705cfSriastradh sna->render.vertex_index += want*op->floats_per_rect; 122503b705cfSriastradh return want; 122603b705cfSriastradh} 122703b705cfSriastradh 122803b705cfSriastradhfastcall static void 122903b705cfSriastradhgen2_render_composite_blt(struct sna *sna, 123003b705cfSriastradh const struct sna_composite_op *op, 123103b705cfSriastradh const struct sna_composite_rectangles *r) 123203b705cfSriastradh{ 123303b705cfSriastradh if (!gen2_get_rectangles(sna, op, 1)) { 123403b705cfSriastradh gen2_emit_composite_state(sna, op); 123503b705cfSriastradh gen2_get_rectangles(sna, op, 1); 123603b705cfSriastradh } 123703b705cfSriastradh 123803b705cfSriastradh op->prim_emit(sna, op, r); 123903b705cfSriastradh} 124003b705cfSriastradh 124103b705cfSriastradhfastcall static void 124203b705cfSriastradhgen2_render_composite_box(struct sna *sna, 124303b705cfSriastradh const struct sna_composite_op *op, 124403b705cfSriastradh const BoxRec *box) 124503b705cfSriastradh{ 124603b705cfSriastradh struct sna_composite_rectangles r; 124703b705cfSriastradh 124803b705cfSriastradh if (!gen2_get_rectangles(sna, op, 1)) { 124903b705cfSriastradh gen2_emit_composite_state(sna, op); 125003b705cfSriastradh gen2_get_rectangles(sna, op, 1); 125103b705cfSriastradh } 125203b705cfSriastradh 125303b705cfSriastradh DBG((" %s: (%d, %d) x (%d, %d)\n", __FUNCTION__, 125403b705cfSriastradh box->x1, box->y1, 125503b705cfSriastradh box->x2 - box->x1, 125603b705cfSriastradh box->y2 - box->y1)); 125703b705cfSriastradh 125803b705cfSriastradh r.dst.x = box->x1; r.dst.y = box->y1; 125903b705cfSriastradh r.width = box->x2 - box->x1; 126003b705cfSriastradh r.height = box->y2 - box->y1; 126103b705cfSriastradh r.src = r.mask = r.dst; 126203b705cfSriastradh 126303b705cfSriastradh op->prim_emit(sna, op, &r); 126403b705cfSriastradh} 126503b705cfSriastradh 126603b705cfSriastradhstatic void 126703b705cfSriastradhgen2_render_composite_boxes(struct sna *sna, 126803b705cfSriastradh const struct sna_composite_op *op, 126903b705cfSriastradh const BoxRec *box, int nbox) 127003b705cfSriastradh{ 127103b705cfSriastradh do { 127203b705cfSriastradh int nbox_this_time; 127303b705cfSriastradh 127403b705cfSriastradh nbox_this_time = gen2_get_rectangles(sna, op, nbox); 127503b705cfSriastradh if (nbox_this_time == 0) { 127603b705cfSriastradh gen2_emit_composite_state(sna, op); 127703b705cfSriastradh nbox_this_time = gen2_get_rectangles(sna, op, nbox); 127803b705cfSriastradh } 127903b705cfSriastradh nbox -= nbox_this_time; 128003b705cfSriastradh 128103b705cfSriastradh do { 128203b705cfSriastradh struct sna_composite_rectangles r; 128303b705cfSriastradh 128403b705cfSriastradh DBG((" %s: (%d, %d) x (%d, %d)\n", __FUNCTION__, 128503b705cfSriastradh box->x1, box->y1, 128603b705cfSriastradh box->x2 - box->x1, 128703b705cfSriastradh box->y2 - box->y1)); 128803b705cfSriastradh 128903b705cfSriastradh r.dst.x = box->x1; r.dst.y = box->y1; 129003b705cfSriastradh r.width = box->x2 - box->x1; 129103b705cfSriastradh r.height = box->y2 - box->y1; 129203b705cfSriastradh r.src = r.mask = r.dst; 129303b705cfSriastradh 129403b705cfSriastradh op->prim_emit(sna, op, &r); 129503b705cfSriastradh box++; 129603b705cfSriastradh } while (--nbox_this_time); 129703b705cfSriastradh } while (nbox); 129803b705cfSriastradh} 129903b705cfSriastradh 130003b705cfSriastradhstatic void gen2_render_composite_done(struct sna *sna, 130103b705cfSriastradh const struct sna_composite_op *op) 130203b705cfSriastradh{ 130303b705cfSriastradh gen2_vertex_flush(sna, op); 130403b705cfSriastradh 130503b705cfSriastradh if (op->mask.bo) 130603b705cfSriastradh kgem_bo_destroy(&sna->kgem, op->mask.bo); 130703b705cfSriastradh if (op->src.bo) 130803b705cfSriastradh kgem_bo_destroy(&sna->kgem, op->src.bo); 130903b705cfSriastradh sna_render_composite_redirect_done(sna, op); 131003b705cfSriastradh} 131103b705cfSriastradh 131203b705cfSriastradhstatic bool 131303b705cfSriastradhgen2_composite_solid_init(struct sna *sna, 131403b705cfSriastradh struct sna_composite_channel *channel, 131503b705cfSriastradh uint32_t color) 131603b705cfSriastradh{ 131703b705cfSriastradh channel->filter = PictFilterNearest; 131803b705cfSriastradh channel->repeat = RepeatNormal; 131903b705cfSriastradh channel->is_solid = true; 132003b705cfSriastradh channel->is_affine = true; 132103b705cfSriastradh channel->width = 1; 132203b705cfSriastradh channel->height = 1; 132303b705cfSriastradh channel->pict_format = PICT_a8r8g8b8; 132403b705cfSriastradh 132503b705cfSriastradh channel->bo = NULL; 132603b705cfSriastradh channel->u.gen2.pixel = color; 132703b705cfSriastradh 132803b705cfSriastradh channel->scale[0] = channel->scale[1] = 1; 132903b705cfSriastradh channel->offset[0] = channel->offset[1] = 0; 133003b705cfSriastradh return true; 133103b705cfSriastradh} 133203b705cfSriastradh 133303b705cfSriastradh#define xFixedToDouble(f) pixman_fixed_to_double(f) 133403b705cfSriastradh 133503b705cfSriastradhstatic bool 133603b705cfSriastradhgen2_composite_linear_init(struct sna *sna, 133703b705cfSriastradh PicturePtr picture, 133803b705cfSriastradh struct sna_composite_channel *channel, 133903b705cfSriastradh int x, int y, 134003b705cfSriastradh int w, int h, 134103b705cfSriastradh int dst_x, int dst_y) 134203b705cfSriastradh{ 134303b705cfSriastradh PictLinearGradient *linear = 134403b705cfSriastradh (PictLinearGradient *)picture->pSourcePict; 134503b705cfSriastradh pixman_fixed_t tx, ty; 134603b705cfSriastradh float x0, y0, sf; 134703b705cfSriastradh float dx, dy; 134803b705cfSriastradh 134903b705cfSriastradh DBG(("%s: p1=(%f, %f), p2=(%f, %f)\n", 135003b705cfSriastradh __FUNCTION__, 135103b705cfSriastradh xFixedToDouble(linear->p1.x), xFixedToDouble(linear->p1.y), 135203b705cfSriastradh xFixedToDouble(linear->p2.x), xFixedToDouble(linear->p2.y))); 135303b705cfSriastradh 135403b705cfSriastradh if (linear->p2.x == linear->p1.x && linear->p2.y == linear->p1.y) 135503b705cfSriastradh return 0; 135603b705cfSriastradh 135703b705cfSriastradh if (!sna_transform_is_affine(picture->transform)) { 135803b705cfSriastradh DBG(("%s: fallback due to projective transform\n", 135903b705cfSriastradh __FUNCTION__)); 136003b705cfSriastradh return sna_render_picture_fixup(sna, picture, channel, 136103b705cfSriastradh x, y, w, h, dst_x, dst_y); 136203b705cfSriastradh } 136303b705cfSriastradh 136403b705cfSriastradh channel->bo = sna_render_get_gradient(sna, (PictGradient *)linear); 136503b705cfSriastradh if (!channel->bo) 136603b705cfSriastradh return 0; 136703b705cfSriastradh 136803b705cfSriastradh channel->filter = PictFilterNearest; 136903b705cfSriastradh channel->repeat = picture->repeat ? picture->repeatType : RepeatNone; 137003b705cfSriastradh channel->is_linear = true; 137103b705cfSriastradh channel->width = channel->bo->pitch / 4; 137203b705cfSriastradh channel->height = 1; 137303b705cfSriastradh channel->pict_format = PICT_a8r8g8b8; 137403b705cfSriastradh 137503b705cfSriastradh channel->scale[0] = channel->scale[1] = 1; 137603b705cfSriastradh channel->offset[0] = channel->offset[1] = 0; 137703b705cfSriastradh 137803b705cfSriastradh if (sna_transform_is_translation(picture->transform, &tx, &ty)) { 137903b705cfSriastradh dx = xFixedToDouble(linear->p2.x - linear->p1.x); 138003b705cfSriastradh dy = xFixedToDouble(linear->p2.y - linear->p1.y); 138103b705cfSriastradh 138203b705cfSriastradh x0 = xFixedToDouble(linear->p1.x); 138303b705cfSriastradh y0 = xFixedToDouble(linear->p1.y); 138403b705cfSriastradh 138503b705cfSriastradh if (tx | ty) { 138603b705cfSriastradh x0 -= pixman_fixed_to_double(tx); 138703b705cfSriastradh y0 -= pixman_fixed_to_double(ty); 138803b705cfSriastradh } 138903b705cfSriastradh } else { 139003b705cfSriastradh struct pixman_f_vector p1, p2; 139103b705cfSriastradh struct pixman_f_transform m, inv; 139203b705cfSriastradh 139303b705cfSriastradh pixman_f_transform_from_pixman_transform(&m, picture->transform); 139403b705cfSriastradh DBG(("%s: transform = [%f %f %f, %f %f %f, %f %f %f]\n", 139503b705cfSriastradh __FUNCTION__, 139603b705cfSriastradh m.m[0][0], m.m[0][1], m.m[0][2], 139703b705cfSriastradh m.m[1][0], m.m[1][1], m.m[1][2], 139803b705cfSriastradh m.m[2][0], m.m[2][1], m.m[2][2])); 139903b705cfSriastradh if (!pixman_f_transform_invert(&inv, &m)) 140003b705cfSriastradh return 0; 140103b705cfSriastradh 140203b705cfSriastradh p1.v[0] = pixman_fixed_to_double(linear->p1.x); 140303b705cfSriastradh p1.v[1] = pixman_fixed_to_double(linear->p1.y); 140403b705cfSriastradh p1.v[2] = 1.; 140503b705cfSriastradh pixman_f_transform_point(&inv, &p1); 140603b705cfSriastradh 140703b705cfSriastradh p2.v[0] = pixman_fixed_to_double(linear->p2.x); 140803b705cfSriastradh p2.v[1] = pixman_fixed_to_double(linear->p2.y); 140903b705cfSriastradh p2.v[2] = 1.; 141003b705cfSriastradh pixman_f_transform_point(&inv, &p2); 141103b705cfSriastradh 141203b705cfSriastradh DBG(("%s: untransformed: p1=(%f, %f, %f), p2=(%f, %f, %f)\n", 141303b705cfSriastradh __FUNCTION__, 141403b705cfSriastradh p1.v[0], p1.v[1], p1.v[2], 141503b705cfSriastradh p2.v[0], p2.v[1], p2.v[2])); 141603b705cfSriastradh 141703b705cfSriastradh dx = p2.v[0] - p1.v[0]; 141803b705cfSriastradh dy = p2.v[1] - p1.v[1]; 141903b705cfSriastradh 142003b705cfSriastradh x0 = p1.v[0]; 142103b705cfSriastradh y0 = p1.v[1]; 142203b705cfSriastradh } 142303b705cfSriastradh 142403b705cfSriastradh sf = dx*dx + dy*dy; 142503b705cfSriastradh dx /= sf; 142603b705cfSriastradh dy /= sf; 142703b705cfSriastradh 142803b705cfSriastradh channel->u.linear.dx = dx; 142903b705cfSriastradh channel->u.linear.dy = dy; 143003b705cfSriastradh channel->u.linear.offset = -dx*(x0+dst_x-x) + -dy*(y0+dst_y-y); 143103b705cfSriastradh 143203b705cfSriastradh DBG(("%s: dx=%f, dy=%f, offset=%f\n", 143303b705cfSriastradh __FUNCTION__, dx, dy, channel->u.linear.offset)); 143403b705cfSriastradh 143503b705cfSriastradh return channel->bo != NULL; 143603b705cfSriastradh} 143703b705cfSriastradh 143803b705cfSriastradhstatic bool source_is_covered(PicturePtr picture, 143903b705cfSriastradh int x, int y, 144003b705cfSriastradh int width, int height) 144103b705cfSriastradh{ 144203b705cfSriastradh int x1, y1, x2, y2; 144303b705cfSriastradh 144403b705cfSriastradh if (picture->repeat && picture->repeatType != RepeatNone) 144503b705cfSriastradh return true; 144603b705cfSriastradh 144703b705cfSriastradh if (picture->pDrawable == NULL) 144803b705cfSriastradh return false; 144903b705cfSriastradh 145003b705cfSriastradh if (picture->transform) { 145103b705cfSriastradh pixman_box16_t sample; 145203b705cfSriastradh 145303b705cfSriastradh sample.x1 = x; 145403b705cfSriastradh sample.y1 = y; 145503b705cfSriastradh sample.x2 = x + width; 145603b705cfSriastradh sample.y2 = y + height; 145703b705cfSriastradh 145803b705cfSriastradh pixman_transform_bounds(picture->transform, &sample); 145903b705cfSriastradh 146003b705cfSriastradh x1 = sample.x1; 146103b705cfSriastradh x2 = sample.x2; 146203b705cfSriastradh y1 = sample.y1; 146303b705cfSriastradh y2 = sample.y2; 146403b705cfSriastradh } else { 146503b705cfSriastradh x1 = x; 146603b705cfSriastradh y1 = y; 146703b705cfSriastradh x2 = x + width; 146803b705cfSriastradh y2 = y + height; 146903b705cfSriastradh } 147003b705cfSriastradh 147103b705cfSriastradh return 147203b705cfSriastradh x1 >= 0 && y1 >= 0 && 147303b705cfSriastradh x2 <= picture->pDrawable->width && 147403b705cfSriastradh y2 <= picture->pDrawable->height; 147503b705cfSriastradh} 147603b705cfSriastradh 147703b705cfSriastradhstatic bool 147803b705cfSriastradhgen2_check_card_format(struct sna *sna, 147903b705cfSriastradh PicturePtr picture, 148003b705cfSriastradh struct sna_composite_channel *channel, 148103b705cfSriastradh int x, int y, int w, int h, 148203b705cfSriastradh bool *fixup_alpha) 148303b705cfSriastradh{ 148403b705cfSriastradh uint32_t format = picture->format; 148503b705cfSriastradh unsigned int i; 148603b705cfSriastradh 148703b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i8xx_tex_formats); i++) { 148803b705cfSriastradh if (i8xx_tex_formats[i].fmt == format) 148903b705cfSriastradh return true; 149003b705cfSriastradh } 149103b705cfSriastradh 149203b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i85x_tex_formats); i++) { 149303b705cfSriastradh if (i85x_tex_formats[i].fmt == format) { 149403b705cfSriastradh if (sna->kgem.gen >= 021) 149503b705cfSriastradh return true; 149603b705cfSriastradh 149703b705cfSriastradh if (source_is_covered(picture, x, y, w,h)) { 149803b705cfSriastradh channel->is_opaque = true; 149903b705cfSriastradh return true; 150003b705cfSriastradh } 150103b705cfSriastradh 150203b705cfSriastradh *fixup_alpha = true; 150303b705cfSriastradh return false; 150403b705cfSriastradh } 150503b705cfSriastradh } 150603b705cfSriastradh 150703b705cfSriastradh *fixup_alpha = false; 150803b705cfSriastradh return false; 150903b705cfSriastradh} 151003b705cfSriastradh 151103b705cfSriastradhstatic int 151203b705cfSriastradhgen2_composite_picture(struct sna *sna, 151303b705cfSriastradh PicturePtr picture, 151403b705cfSriastradh struct sna_composite_channel *channel, 151503b705cfSriastradh int x, int y, 151603b705cfSriastradh int w, int h, 151703b705cfSriastradh int dst_x, int dst_y, 151803b705cfSriastradh bool precise) 151903b705cfSriastradh{ 152003b705cfSriastradh PixmapPtr pixmap; 152103b705cfSriastradh uint32_t color; 152203b705cfSriastradh int16_t dx, dy; 152303b705cfSriastradh bool fixup_alpha; 152403b705cfSriastradh 152503b705cfSriastradh DBG(("%s: (%d, %d)x(%d, %d), dst=(%d, %d)\n", 152603b705cfSriastradh __FUNCTION__, x, y, w, h, dst_x, dst_y)); 152703b705cfSriastradh 152803b705cfSriastradh channel->is_solid = false; 152903b705cfSriastradh channel->is_linear = false; 153003b705cfSriastradh channel->is_opaque = false; 153103b705cfSriastradh channel->is_affine = true; 153203b705cfSriastradh channel->transform = NULL; 153342542f5fSchristos channel->card_format = -1; 153403b705cfSriastradh 153503b705cfSriastradh if (sna_picture_is_solid(picture, &color)) 153603b705cfSriastradh return gen2_composite_solid_init(sna, channel, color); 153703b705cfSriastradh 153803b705cfSriastradh if (!gen2_check_repeat(picture)) { 153903b705cfSriastradh DBG(("%s -- fallback, unhandled repeat %d\n", 154003b705cfSriastradh __FUNCTION__, picture->repeat)); 154103b705cfSriastradh return sna_render_picture_fixup(sna, picture, channel, 154203b705cfSriastradh x, y, w, h, dst_x, dst_y); 154303b705cfSriastradh } 154403b705cfSriastradh 154503b705cfSriastradh if (!gen2_check_filter(picture)) { 154603b705cfSriastradh DBG(("%s -- fallback, unhandled filter %d\n", 154703b705cfSriastradh __FUNCTION__, picture->filter)); 154803b705cfSriastradh return sna_render_picture_fixup(sna, picture, channel, 154903b705cfSriastradh x, y, w, h, dst_x, dst_y); 155003b705cfSriastradh } 155103b705cfSriastradh 155203b705cfSriastradh if (picture->pDrawable == NULL) { 155303b705cfSriastradh int ret; 155403b705cfSriastradh 155503b705cfSriastradh if (picture->pSourcePict->type == SourcePictTypeLinear) 155603b705cfSriastradh return gen2_composite_linear_init(sna, picture, channel, 155703b705cfSriastradh x, y, 155803b705cfSriastradh w, h, 155903b705cfSriastradh dst_x, dst_y); 156003b705cfSriastradh 156103b705cfSriastradh DBG(("%s -- fallback, unhandled source %d\n", 156203b705cfSriastradh __FUNCTION__, picture->pSourcePict->type)); 156303b705cfSriastradh ret = -1; 156403b705cfSriastradh if (!precise) 156503b705cfSriastradh ret = sna_render_picture_approximate_gradient(sna, picture, channel, 156603b705cfSriastradh x, y, w, h, dst_x, dst_y); 156703b705cfSriastradh if (ret == -1) 156803b705cfSriastradh ret = sna_render_picture_fixup(sna, picture, channel, 156903b705cfSriastradh x, y, w, h, dst_x, dst_y); 157003b705cfSriastradh return ret; 157103b705cfSriastradh } 157203b705cfSriastradh 157303b705cfSriastradh if (picture->alphaMap) { 157403b705cfSriastradh DBG(("%s -- fallback, alphamap\n", __FUNCTION__)); 157503b705cfSriastradh return sna_render_picture_fixup(sna, picture, channel, 157603b705cfSriastradh x, y, w, h, dst_x, dst_y); 157703b705cfSriastradh } 157803b705cfSriastradh 157903b705cfSriastradh channel->repeat = picture->repeat ? picture->repeatType : RepeatNone; 158003b705cfSriastradh channel->filter = picture->filter; 158103b705cfSriastradh 158203b705cfSriastradh pixmap = get_drawable_pixmap(picture->pDrawable); 158303b705cfSriastradh get_drawable_deltas(picture->pDrawable, pixmap, &dx, &dy); 158403b705cfSriastradh 158503b705cfSriastradh x += dx + picture->pDrawable->x; 158603b705cfSriastradh y += dy + picture->pDrawable->y; 158703b705cfSriastradh 158803b705cfSriastradh channel->is_affine = sna_transform_is_affine(picture->transform); 158942542f5fSchristos if (sna_transform_is_imprecise_integer_translation(picture->transform, picture->filter, precise, &dx, &dy)) { 159003b705cfSriastradh DBG(("%s: integer translation (%d, %d), removing\n", 159103b705cfSriastradh __FUNCTION__, dx, dy)); 159203b705cfSriastradh x += dx; 159303b705cfSriastradh y += dy; 159403b705cfSriastradh channel->transform = NULL; 159503b705cfSriastradh channel->filter = PictFilterNearest; 159642542f5fSchristos 159742542f5fSchristos if (channel->repeat && 159842542f5fSchristos (x >= 0 && 159942542f5fSchristos y >= 0 && 1600fe8aea9eSmrg x + w <= pixmap->drawable.width && 1601fe8aea9eSmrg y + h <= pixmap->drawable.height)) { 160242542f5fSchristos struct sna_pixmap *priv = sna_pixmap(pixmap); 160342542f5fSchristos if (priv && priv->clear) { 160442542f5fSchristos DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color)); 1605fe8aea9eSmrg return gen2_composite_solid_init(sna, channel, solid_color(picture->format, priv->clear_color)); 160642542f5fSchristos } 160742542f5fSchristos } 160803b705cfSriastradh } else 160903b705cfSriastradh channel->transform = picture->transform; 161003b705cfSriastradh 161103b705cfSriastradh if (!gen2_check_card_format(sna, picture, channel, x, y, w ,h, &fixup_alpha)) 161203b705cfSriastradh return sna_render_picture_convert(sna, picture, channel, pixmap, 161303b705cfSriastradh x, y, w, h, dst_x, dst_y, fixup_alpha); 161403b705cfSriastradh 161503b705cfSriastradh channel->pict_format = picture->format; 161603b705cfSriastradh if (too_large(pixmap->drawable.width, pixmap->drawable.height)) 161703b705cfSriastradh return sna_render_picture_extract(sna, picture, channel, 161803b705cfSriastradh x, y, w, h, dst_x, dst_y); 161903b705cfSriastradh 162003b705cfSriastradh return sna_render_pixmap_bo(sna, channel, pixmap, 162103b705cfSriastradh x, y, w, h, dst_x, dst_y); 162203b705cfSriastradh} 162303b705cfSriastradh 162403b705cfSriastradhstatic bool 162503b705cfSriastradhgen2_composite_set_target(struct sna *sna, 162603b705cfSriastradh struct sna_composite_op *op, 162703b705cfSriastradh PicturePtr dst, 162842542f5fSchristos int x, int y, int w, int h, 162942542f5fSchristos bool partial) 163003b705cfSriastradh{ 163103b705cfSriastradh BoxRec box; 163242542f5fSchristos unsigned hint; 163303b705cfSriastradh 163403b705cfSriastradh op->dst.pixmap = get_drawable_pixmap(dst->pDrawable); 163503b705cfSriastradh op->dst.format = dst->format; 163603b705cfSriastradh op->dst.width = op->dst.pixmap->drawable.width; 163703b705cfSriastradh op->dst.height = op->dst.pixmap->drawable.height; 163803b705cfSriastradh 163903b705cfSriastradh if (w && h) { 164003b705cfSriastradh box.x1 = x; 164103b705cfSriastradh box.y1 = y; 164203b705cfSriastradh box.x2 = x + w; 164303b705cfSriastradh box.y2 = y + h; 164403b705cfSriastradh } else 164503b705cfSriastradh sna_render_picture_extents(dst, &box); 164603b705cfSriastradh 1647fe8aea9eSmrg hint = PREFER_GPU | RENDER_GPU; 1648fe8aea9eSmrg if (!need_tiling(sna, op->dst.width, op->dst.height)) 1649fe8aea9eSmrg hint |= FORCE_GPU; 165042542f5fSchristos if (!partial) { 165142542f5fSchristos hint |= IGNORE_DAMAGE; 165242542f5fSchristos if (w == op->dst.width && h == op->dst.height) 165342542f5fSchristos hint |= REPLACES; 165442542f5fSchristos } 165542542f5fSchristos 165642542f5fSchristos op->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint, &box, &op->damage); 165703b705cfSriastradh if (op->dst.bo == NULL) 165803b705cfSriastradh return false; 165903b705cfSriastradh 166042542f5fSchristos if (hint & REPLACES) { 166142542f5fSchristos struct sna_pixmap *priv = sna_pixmap(op->dst.pixmap); 166242542f5fSchristos kgem_bo_pair_undo(&sna->kgem, priv->gpu_bo, priv->cpu_bo); 166303b705cfSriastradh } 166403b705cfSriastradh 166542542f5fSchristos assert((op->dst.bo->pitch & 7) == 0); 166642542f5fSchristos 166703b705cfSriastradh get_drawable_deltas(dst->pDrawable, op->dst.pixmap, 166803b705cfSriastradh &op->dst.x, &op->dst.y); 166903b705cfSriastradh 167042542f5fSchristos DBG(("%s: pixmap=%ld, format=%08x, size=%dx%d, pitch=%d, delta=(%d,%d),damage=%p\n", 167103b705cfSriastradh __FUNCTION__, 167242542f5fSchristos op->dst.pixmap->drawable.serialNumber, (int)op->dst.format, 167303b705cfSriastradh op->dst.width, op->dst.height, 167403b705cfSriastradh op->dst.bo->pitch, 167503b705cfSriastradh op->dst.x, op->dst.y, 167603b705cfSriastradh op->damage ? *op->damage : (void *)-1)); 167703b705cfSriastradh 167803b705cfSriastradh assert(op->dst.bo->proxy == NULL); 167942542f5fSchristos 168042542f5fSchristos if (((too_large(op->dst.width, op->dst.height) || 168142542f5fSchristos op->dst.bo->pitch > MAX_3D_PITCH)) && 168242542f5fSchristos !sna_render_composite_redirect(sna, op, x, y, w, h, partial)) 168342542f5fSchristos return false; 168442542f5fSchristos 168503b705cfSriastradh return true; 168603b705cfSriastradh} 168703b705cfSriastradh 168803b705cfSriastradhstatic bool 168903b705cfSriastradhis_unhandled_gradient(PicturePtr picture, bool precise) 169003b705cfSriastradh{ 169103b705cfSriastradh if (picture->pDrawable) 169203b705cfSriastradh return false; 169303b705cfSriastradh 169403b705cfSriastradh switch (picture->pSourcePict->type) { 169503b705cfSriastradh case SourcePictTypeSolidFill: 169603b705cfSriastradh case SourcePictTypeLinear: 169703b705cfSriastradh return false; 169803b705cfSriastradh default: 169903b705cfSriastradh return precise; 170003b705cfSriastradh } 170103b705cfSriastradh} 170203b705cfSriastradh 170303b705cfSriastradhstatic bool 170403b705cfSriastradhhas_alphamap(PicturePtr p) 170503b705cfSriastradh{ 170603b705cfSriastradh return p->alphaMap != NULL; 170703b705cfSriastradh} 170803b705cfSriastradh 170903b705cfSriastradhstatic bool 171003b705cfSriastradhneed_upload(PicturePtr p) 171103b705cfSriastradh{ 171203b705cfSriastradh return p->pDrawable && unattached(p->pDrawable) && untransformed(p); 171303b705cfSriastradh} 171403b705cfSriastradh 171503b705cfSriastradhstatic bool 171603b705cfSriastradhsource_is_busy(PixmapPtr pixmap) 171703b705cfSriastradh{ 171803b705cfSriastradh struct sna_pixmap *priv = sna_pixmap(pixmap); 171903b705cfSriastradh if (priv == NULL) 172003b705cfSriastradh return false; 172103b705cfSriastradh 172203b705cfSriastradh if (priv->clear) 172303b705cfSriastradh return false; 172403b705cfSriastradh 172503b705cfSriastradh if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo)) 172603b705cfSriastradh return true; 172703b705cfSriastradh 172803b705cfSriastradh if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) 172903b705cfSriastradh return true; 173003b705cfSriastradh 173103b705cfSriastradh return priv->gpu_damage && !priv->cpu_damage; 173203b705cfSriastradh} 173303b705cfSriastradh 173403b705cfSriastradhstatic bool 173503b705cfSriastradhsource_fallback(PicturePtr p, PixmapPtr pixmap, bool precise) 173603b705cfSriastradh{ 173703b705cfSriastradh if (sna_picture_is_solid(p, NULL)) 173803b705cfSriastradh return false; 173903b705cfSriastradh 174003b705cfSriastradh if (is_unhandled_gradient(p, precise) || !gen2_check_repeat(p)) 174103b705cfSriastradh return true; 174203b705cfSriastradh 174303b705cfSriastradh if (pixmap && source_is_busy(pixmap)) 174403b705cfSriastradh return false; 174503b705cfSriastradh 174603b705cfSriastradh return has_alphamap(p) || !gen2_check_filter(p) || need_upload(p); 174703b705cfSriastradh} 174803b705cfSriastradh 174903b705cfSriastradhstatic bool 175003b705cfSriastradhgen2_composite_fallback(struct sna *sna, 175103b705cfSriastradh PicturePtr src, 175203b705cfSriastradh PicturePtr mask, 175303b705cfSriastradh PicturePtr dst) 175403b705cfSriastradh{ 175503b705cfSriastradh PixmapPtr src_pixmap; 175603b705cfSriastradh PixmapPtr mask_pixmap; 175703b705cfSriastradh PixmapPtr dst_pixmap; 175803b705cfSriastradh bool src_fallback, mask_fallback; 175903b705cfSriastradh 176003b705cfSriastradh if (!gen2_check_dst_format(dst->format)) { 176103b705cfSriastradh DBG(("%s: unknown destination format: %d\n", 176203b705cfSriastradh __FUNCTION__, dst->format)); 176303b705cfSriastradh return true; 176403b705cfSriastradh } 176503b705cfSriastradh 176603b705cfSriastradh dst_pixmap = get_drawable_pixmap(dst->pDrawable); 176703b705cfSriastradh 176803b705cfSriastradh src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL; 176903b705cfSriastradh src_fallback = source_fallback(src, src_pixmap, 177003b705cfSriastradh dst->polyMode == PolyModePrecise); 177103b705cfSriastradh 177203b705cfSriastradh if (mask) { 177303b705cfSriastradh mask_pixmap = mask->pDrawable ? get_drawable_pixmap(mask->pDrawable) : NULL; 177403b705cfSriastradh mask_fallback = source_fallback(mask, mask_pixmap, 177503b705cfSriastradh dst->polyMode == PolyModePrecise); 177603b705cfSriastradh } else { 177703b705cfSriastradh mask_pixmap = NULL; 177803b705cfSriastradh mask_fallback = NULL; 177903b705cfSriastradh } 178003b705cfSriastradh 178103b705cfSriastradh /* If we are using the destination as a source and need to 178203b705cfSriastradh * readback in order to upload the source, do it all 178303b705cfSriastradh * on the cpu. 178403b705cfSriastradh */ 178503b705cfSriastradh if (src_pixmap == dst_pixmap && src_fallback) { 178603b705cfSriastradh DBG(("%s: src is dst and will fallback\n",__FUNCTION__)); 178703b705cfSriastradh return true; 178803b705cfSriastradh } 178903b705cfSriastradh if (mask_pixmap == dst_pixmap && mask_fallback) { 179003b705cfSriastradh DBG(("%s: mask is dst and will fallback\n",__FUNCTION__)); 179103b705cfSriastradh return true; 179203b705cfSriastradh } 179303b705cfSriastradh 179403b705cfSriastradh /* If anything is on the GPU, push everything out to the GPU */ 179503b705cfSriastradh if (dst_use_gpu(dst_pixmap)) { 179603b705cfSriastradh DBG(("%s: dst is already on the GPU, try to use GPU\n", 179703b705cfSriastradh __FUNCTION__)); 179803b705cfSriastradh return false; 179903b705cfSriastradh } 180003b705cfSriastradh 180103b705cfSriastradh if (src_pixmap && !src_fallback) { 180203b705cfSriastradh DBG(("%s: src is already on the GPU, try to use GPU\n", 180303b705cfSriastradh __FUNCTION__)); 180403b705cfSriastradh return false; 180503b705cfSriastradh } 180603b705cfSriastradh if (mask_pixmap && !mask_fallback) { 180703b705cfSriastradh DBG(("%s: mask is already on the GPU, try to use GPU\n", 180803b705cfSriastradh __FUNCTION__)); 180903b705cfSriastradh return false; 181003b705cfSriastradh } 181103b705cfSriastradh 181203b705cfSriastradh /* However if the dst is not on the GPU and we need to 181303b705cfSriastradh * render one of the sources using the CPU, we may 181403b705cfSriastradh * as well do the entire operation in place onthe CPU. 181503b705cfSriastradh */ 181603b705cfSriastradh if (src_fallback) { 181703b705cfSriastradh DBG(("%s: dst is on the CPU and src will fallback\n", 181803b705cfSriastradh __FUNCTION__)); 181903b705cfSriastradh return true; 182003b705cfSriastradh } 182103b705cfSriastradh 182203b705cfSriastradh if (mask && mask_fallback) { 182303b705cfSriastradh DBG(("%s: dst is on the CPU and mask will fallback\n", 182403b705cfSriastradh __FUNCTION__)); 182503b705cfSriastradh return true; 182603b705cfSriastradh } 182703b705cfSriastradh 182803b705cfSriastradh if (too_large(dst_pixmap->drawable.width, 182903b705cfSriastradh dst_pixmap->drawable.height) && 183003b705cfSriastradh dst_is_cpu(dst_pixmap)) { 183103b705cfSriastradh DBG(("%s: dst is on the CPU and too large\n", __FUNCTION__)); 183203b705cfSriastradh return true; 183303b705cfSriastradh } 183403b705cfSriastradh 183503b705cfSriastradh DBG(("%s: dst is not on the GPU and the operation should not fallback\n", 183603b705cfSriastradh __FUNCTION__)); 183703b705cfSriastradh return dst_use_cpu(dst_pixmap); 183803b705cfSriastradh} 183903b705cfSriastradh 184003b705cfSriastradhstatic int 184103b705cfSriastradhreuse_source(struct sna *sna, 184203b705cfSriastradh PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y, 184303b705cfSriastradh PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y) 184403b705cfSriastradh{ 184503b705cfSriastradh uint32_t color; 184603b705cfSriastradh 184703b705cfSriastradh if (src_x != msk_x || src_y != msk_y) 184803b705cfSriastradh return false; 184903b705cfSriastradh 185003b705cfSriastradh if (sna_picture_is_solid(mask, &color)) 185103b705cfSriastradh return gen2_composite_solid_init(sna, mc, color); 185203b705cfSriastradh 185303b705cfSriastradh if (sc->is_solid) 185403b705cfSriastradh return false; 185503b705cfSriastradh 185603b705cfSriastradh if (src == mask) { 185703b705cfSriastradh DBG(("%s: mask is source\n", __FUNCTION__)); 185803b705cfSriastradh *mc = *sc; 185903b705cfSriastradh mc->bo = kgem_bo_reference(mc->bo); 186003b705cfSriastradh return true; 186103b705cfSriastradh } 186203b705cfSriastradh 186303b705cfSriastradh if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable) 186403b705cfSriastradh return false; 186503b705cfSriastradh 186603b705cfSriastradh DBG(("%s: mask reuses source drawable\n", __FUNCTION__)); 186703b705cfSriastradh 186803b705cfSriastradh if (!sna_transform_equal(src->transform, mask->transform)) 186903b705cfSriastradh return false; 187003b705cfSriastradh 187103b705cfSriastradh if (!sna_picture_alphamap_equal(src, mask)) 187203b705cfSriastradh return false; 187303b705cfSriastradh 187403b705cfSriastradh if (!gen2_check_repeat(mask)) 187503b705cfSriastradh return false; 187603b705cfSriastradh 187703b705cfSriastradh if (!gen2_check_filter(mask)) 187803b705cfSriastradh return false; 187903b705cfSriastradh 188003b705cfSriastradh if (!gen2_check_format(sna, mask)) 188103b705cfSriastradh return false; 188203b705cfSriastradh 188303b705cfSriastradh DBG(("%s: reusing source channel for mask with a twist\n", 188403b705cfSriastradh __FUNCTION__)); 188503b705cfSriastradh 188603b705cfSriastradh *mc = *sc; 188703b705cfSriastradh mc->repeat = mask->repeat ? mask->repeatType : RepeatNone; 188803b705cfSriastradh mc->filter = mask->filter; 188903b705cfSriastradh mc->pict_format = mask->format; 189003b705cfSriastradh mc->bo = kgem_bo_reference(mc->bo); 189103b705cfSriastradh return true; 189203b705cfSriastradh} 189303b705cfSriastradh 189403b705cfSriastradhstatic bool 189503b705cfSriastradhgen2_render_composite(struct sna *sna, 189603b705cfSriastradh uint8_t op, 189703b705cfSriastradh PicturePtr src, 189803b705cfSriastradh PicturePtr mask, 189903b705cfSriastradh PicturePtr dst, 190003b705cfSriastradh int16_t src_x, int16_t src_y, 190103b705cfSriastradh int16_t mask_x, int16_t mask_y, 190203b705cfSriastradh int16_t dst_x, int16_t dst_y, 190303b705cfSriastradh int16_t width, int16_t height, 190442542f5fSchristos unsigned flags, 190503b705cfSriastradh struct sna_composite_op *tmp) 190603b705cfSriastradh{ 190703b705cfSriastradh DBG(("%s()\n", __FUNCTION__)); 190803b705cfSriastradh 190903b705cfSriastradh if (op >= ARRAY_SIZE(gen2_blend_op)) { 191003b705cfSriastradh DBG(("%s: fallback due to unhandled blend op: %d\n", 191103b705cfSriastradh __FUNCTION__, op)); 191203b705cfSriastradh return false; 191303b705cfSriastradh } 191403b705cfSriastradh 191503b705cfSriastradh if (mask == NULL && 191603b705cfSriastradh sna_blt_composite(sna, op, src, dst, 191703b705cfSriastradh src_x, src_y, 191803b705cfSriastradh dst_x, dst_y, 191903b705cfSriastradh width, height, 192042542f5fSchristos flags, tmp)) 192103b705cfSriastradh return true; 192203b705cfSriastradh 192303b705cfSriastradh if (gen2_composite_fallback(sna, src, mask, dst)) 192442542f5fSchristos goto fallback; 192503b705cfSriastradh 192603b705cfSriastradh if (need_tiling(sna, width, height)) 192703b705cfSriastradh return sna_tiling_composite(op, src, mask, dst, 192803b705cfSriastradh src_x, src_y, 192903b705cfSriastradh mask_x, mask_y, 193003b705cfSriastradh dst_x, dst_y, 193103b705cfSriastradh width, height, 193203b705cfSriastradh tmp); 193303b705cfSriastradh 193442542f5fSchristos tmp->op = op; 193542542f5fSchristos sna_render_composite_redirect_init(tmp); 193642542f5fSchristos 193703b705cfSriastradh if (!gen2_composite_set_target(sna, tmp, dst, 193842542f5fSchristos dst_x, dst_y, width, height, 193942542f5fSchristos flags & COMPOSITE_PARTIAL || op > PictOpSrc)) { 194003b705cfSriastradh DBG(("%s: unable to set render target\n", 194103b705cfSriastradh __FUNCTION__)); 194242542f5fSchristos goto fallback; 194303b705cfSriastradh } 194403b705cfSriastradh 194503b705cfSriastradh switch (gen2_composite_picture(sna, src, &tmp->src, 194603b705cfSriastradh src_x, src_y, 194703b705cfSriastradh width, height, 194803b705cfSriastradh dst_x, dst_y, 194903b705cfSriastradh dst->polyMode == PolyModePrecise)) { 195003b705cfSriastradh case -1: 195103b705cfSriastradh DBG(("%s: fallback -- unable to prepare source\n", 195203b705cfSriastradh __FUNCTION__)); 195303b705cfSriastradh goto cleanup_dst; 195403b705cfSriastradh case 0: 195503b705cfSriastradh gen2_composite_solid_init(sna, &tmp->src, 0); 195603b705cfSriastradh break; 195703b705cfSriastradh case 1: 195803b705cfSriastradh if (mask == NULL && tmp->src.bo && 195903b705cfSriastradh sna_blt_composite__convert(sna, 196003b705cfSriastradh dst_x, dst_y, width, height, 196103b705cfSriastradh tmp)) 196203b705cfSriastradh return true; 196303b705cfSriastradh break; 196403b705cfSriastradh } 196503b705cfSriastradh 196603b705cfSriastradh if (mask) { 196703b705cfSriastradh if (!reuse_source(sna, 196803b705cfSriastradh src, &tmp->src, src_x, src_y, 196903b705cfSriastradh mask, &tmp->mask, mask_x, mask_y)) { 197003b705cfSriastradh switch (gen2_composite_picture(sna, mask, &tmp->mask, 197103b705cfSriastradh mask_x, mask_y, 197203b705cfSriastradh width, height, 197303b705cfSriastradh dst_x, dst_y, 197403b705cfSriastradh dst->polyMode == PolyModePrecise)) { 197503b705cfSriastradh case -1: 197603b705cfSriastradh DBG(("%s: fallback -- unable to prepare mask\n", 197703b705cfSriastradh __FUNCTION__)); 197803b705cfSriastradh goto cleanup_src; 197903b705cfSriastradh case 0: 198003b705cfSriastradh gen2_composite_solid_init(sna, &tmp->mask, 0); 198103b705cfSriastradh case 1: 198203b705cfSriastradh break; 198303b705cfSriastradh } 198403b705cfSriastradh } 198503b705cfSriastradh 198603b705cfSriastradh if (mask->componentAlpha && PICT_FORMAT_RGB(mask->format)) { 198703b705cfSriastradh /* Check if it's component alpha that relies on a source alpha 198803b705cfSriastradh * and on the source value. We can only get one of those 198903b705cfSriastradh * into the single source value that we get to blend with. 199003b705cfSriastradh */ 199103b705cfSriastradh tmp->has_component_alpha = true; 199203b705cfSriastradh if (gen2_blend_op[op].src_alpha && 199303b705cfSriastradh (gen2_blend_op[op].src_blend != BLENDFACTOR_ZERO)) { 199403b705cfSriastradh if (op != PictOpOver) { 199503b705cfSriastradh DBG(("%s: fallback -- unsupported CA blend (src_blend=%d)\n", 199603b705cfSriastradh __FUNCTION__, 199703b705cfSriastradh gen2_blend_op[op].src_blend)); 199803b705cfSriastradh goto cleanup_src; 199903b705cfSriastradh } 200003b705cfSriastradh 200103b705cfSriastradh tmp->need_magic_ca_pass = true; 200203b705cfSriastradh tmp->op = PictOpOutReverse; 200303b705cfSriastradh } 200403b705cfSriastradh } 200503b705cfSriastradh 200603b705cfSriastradh /* convert solid to a texture (pure convenience) */ 200703b705cfSriastradh if (tmp->mask.is_solid && tmp->src.is_solid) { 200803b705cfSriastradh assert(tmp->mask.is_affine); 200903b705cfSriastradh tmp->mask.bo = sna_render_get_solid(sna, tmp->mask.u.gen2.pixel); 201003b705cfSriastradh if (!tmp->mask.bo) 201103b705cfSriastradh goto cleanup_src; 201203b705cfSriastradh } 201303b705cfSriastradh } 201403b705cfSriastradh 201503b705cfSriastradh tmp->floats_per_vertex = 2; 201603b705cfSriastradh if (!tmp->src.is_solid) 201703b705cfSriastradh tmp->floats_per_vertex += tmp->src.is_affine ? 2 : 3; 201803b705cfSriastradh if (tmp->mask.bo) 201903b705cfSriastradh tmp->floats_per_vertex += tmp->mask.is_affine ? 2 : 3; 202003b705cfSriastradh tmp->floats_per_rect = 3*tmp->floats_per_vertex; 202103b705cfSriastradh 202203b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive; 202303b705cfSriastradh if (tmp->mask.bo) { 202403b705cfSriastradh if (tmp->mask.transform == NULL) { 202503b705cfSriastradh if (tmp->src.is_solid) { 202603b705cfSriastradh assert(tmp->floats_per_rect == 12); 202703b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 202803b705cfSriastradh if (sna->cpu_features & SSE2) { 202903b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_constant_identity_mask__sse2; 203003b705cfSriastradh } else 203103b705cfSriastradh#endif 203203b705cfSriastradh { 203303b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_constant_identity_mask; 203403b705cfSriastradh } 203503b705cfSriastradh } 203603b705cfSriastradh } 203703b705cfSriastradh } else { 203803b705cfSriastradh if (tmp->src.is_solid) { 203903b705cfSriastradh assert(tmp->floats_per_rect == 6); 204003b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 204103b705cfSriastradh if (sna->cpu_features & SSE2) { 204203b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_constant__sse2; 204303b705cfSriastradh } else 204403b705cfSriastradh#endif 204503b705cfSriastradh { 204603b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_constant; 204703b705cfSriastradh } 204803b705cfSriastradh } else if (tmp->src.is_linear) { 204903b705cfSriastradh assert(tmp->floats_per_rect == 12); 205003b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 205103b705cfSriastradh if (sna->cpu_features & SSE2) { 205203b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_linear__sse2; 205303b705cfSriastradh } else 205403b705cfSriastradh#endif 205503b705cfSriastradh { 205603b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_linear; 205703b705cfSriastradh } 205803b705cfSriastradh } else if (tmp->src.transform == NULL) { 205903b705cfSriastradh assert(tmp->floats_per_rect == 12); 206003b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 206103b705cfSriastradh if (sna->cpu_features & SSE2) { 206203b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_identity__sse2; 206303b705cfSriastradh } else 206403b705cfSriastradh#endif 206503b705cfSriastradh { 206603b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_identity; 206703b705cfSriastradh } 206803b705cfSriastradh } else if (tmp->src.is_affine) { 206903b705cfSriastradh assert(tmp->floats_per_rect == 12); 207003b705cfSriastradh tmp->src.scale[0] /= tmp->src.transform->matrix[2][2]; 207103b705cfSriastradh tmp->src.scale[1] /= tmp->src.transform->matrix[2][2]; 207203b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 207303b705cfSriastradh if (sna->cpu_features & SSE2) { 207403b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_affine__sse2; 207503b705cfSriastradh } else 207603b705cfSriastradh#endif 207703b705cfSriastradh { 207803b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_affine; 207903b705cfSriastradh } 208003b705cfSriastradh } 208103b705cfSriastradh } 208203b705cfSriastradh 208303b705cfSriastradh tmp->blt = gen2_render_composite_blt; 208403b705cfSriastradh tmp->box = gen2_render_composite_box; 208503b705cfSriastradh tmp->boxes = gen2_render_composite_boxes; 208603b705cfSriastradh tmp->done = gen2_render_composite_done; 208703b705cfSriastradh 208803b705cfSriastradh if (!kgem_check_bo(&sna->kgem, 208903b705cfSriastradh tmp->dst.bo, tmp->src.bo, tmp->mask.bo, 209003b705cfSriastradh NULL)) { 209103b705cfSriastradh kgem_submit(&sna->kgem); 209203b705cfSriastradh if (!kgem_check_bo(&sna->kgem, 209303b705cfSriastradh tmp->dst.bo, tmp->src.bo, tmp->mask.bo, 209403b705cfSriastradh NULL)) { 209503b705cfSriastradh DBG(("%s: fallback, operation does not fit into GTT\n", 209603b705cfSriastradh __FUNCTION__)); 209703b705cfSriastradh goto cleanup_mask; 209803b705cfSriastradh } 209903b705cfSriastradh } 210003b705cfSriastradh 210103b705cfSriastradh gen2_emit_composite_state(sna, tmp); 210203b705cfSriastradh return true; 210303b705cfSriastradh 210403b705cfSriastradhcleanup_mask: 210542542f5fSchristos if (tmp->mask.bo) { 210603b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->mask.bo); 210742542f5fSchristos tmp->mask.bo = NULL; 210842542f5fSchristos } 210903b705cfSriastradhcleanup_src: 211042542f5fSchristos if (tmp->src.bo) { 211103b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->src.bo); 211242542f5fSchristos tmp->src.bo = NULL; 211342542f5fSchristos } 211403b705cfSriastradhcleanup_dst: 211542542f5fSchristos if (tmp->redirect.real_bo) { 211603b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->dst.bo); 211742542f5fSchristos tmp->redirect.real_bo = NULL; 211842542f5fSchristos } 211942542f5fSchristosfallback: 212042542f5fSchristos return (mask == NULL && 212142542f5fSchristos sna_blt_composite(sna, op, src, dst, 212242542f5fSchristos src_x, src_y, 212342542f5fSchristos dst_x, dst_y, 212442542f5fSchristos width, height, 212542542f5fSchristos flags | COMPOSITE_FALLBACK, tmp)); 212603b705cfSriastradh} 212703b705cfSriastradh 212803b705cfSriastradhfastcall static void 212903b705cfSriastradhgen2_emit_composite_spans_primitive_constant(struct sna *sna, 213003b705cfSriastradh const struct sna_composite_spans_op *op, 213103b705cfSriastradh const BoxRec *box, 213203b705cfSriastradh float opacity) 213303b705cfSriastradh{ 213403b705cfSriastradh float *v = (float *)sna->kgem.batch + sna->kgem.nbatch; 213503b705cfSriastradh uint32_t alpha = (uint8_t)(255 * opacity) << 24; 213603b705cfSriastradh sna->kgem.nbatch += 9; 213703b705cfSriastradh 213803b705cfSriastradh v[0] = op->base.dst.x + box->x2; 213903b705cfSriastradh v[1] = op->base.dst.y + box->y2; 214003b705cfSriastradh *((uint32_t *)v + 2) = alpha; 214103b705cfSriastradh 214203b705cfSriastradh v[3] = op->base.dst.x + box->x1; 214303b705cfSriastradh v[4] = v[1]; 214403b705cfSriastradh *((uint32_t *)v + 5) = alpha; 214503b705cfSriastradh 214603b705cfSriastradh v[6] = v[3]; 214703b705cfSriastradh v[7] = op->base.dst.y + box->y1; 214803b705cfSriastradh *((uint32_t *)v + 8) = alpha; 214903b705cfSriastradh} 215003b705cfSriastradh 215103b705cfSriastradhfastcall static void 215203b705cfSriastradhgen2_emit_composite_spans_primitive_linear(struct sna *sna, 215303b705cfSriastradh const struct sna_composite_spans_op *op, 215403b705cfSriastradh const BoxRec *box, 215503b705cfSriastradh float opacity) 215603b705cfSriastradh{ 215703b705cfSriastradh union { 215803b705cfSriastradh float f; 215903b705cfSriastradh uint32_t u; 216003b705cfSriastradh } alpha; 216103b705cfSriastradh 216203b705cfSriastradh alpha.u = (uint8_t)(255 * opacity) << 24; 216303b705cfSriastradh 216403b705cfSriastradh gen2_emit_composite_dstcoord(sna, 216503b705cfSriastradh op->base.dst.x + box->x2, 216603b705cfSriastradh op->base.dst.y + box->y2); 216703b705cfSriastradh VERTEX(alpha.f); 216803b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, box->x2, box->y2); 216903b705cfSriastradh 217003b705cfSriastradh gen2_emit_composite_dstcoord(sna, 217103b705cfSriastradh op->base.dst.x + box->x1, 217203b705cfSriastradh op->base.dst.y + box->y2); 217303b705cfSriastradh VERTEX(alpha.f); 217403b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, box->x1, box->y2); 217503b705cfSriastradh 217603b705cfSriastradh gen2_emit_composite_dstcoord(sna, 217703b705cfSriastradh op->base.dst.x + box->x1, 217803b705cfSriastradh op->base.dst.y + box->y1); 217903b705cfSriastradh VERTEX(alpha.f); 218003b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, box->x1, box->y1); 218103b705cfSriastradh} 218203b705cfSriastradh 218303b705cfSriastradhfastcall static void 218403b705cfSriastradhgen2_emit_composite_spans_primitive_identity_source(struct sna *sna, 218503b705cfSriastradh const struct sna_composite_spans_op *op, 218603b705cfSriastradh const BoxRec *box, 218703b705cfSriastradh float opacity) 218803b705cfSriastradh{ 218903b705cfSriastradh float *v = (float *)sna->kgem.batch + sna->kgem.nbatch; 219003b705cfSriastradh uint32_t alpha = (uint8_t)(255 * opacity) << 24; 219103b705cfSriastradh sna->kgem.nbatch += 15; 219203b705cfSriastradh 219303b705cfSriastradh v[0] = op->base.dst.x + box->x2; 219403b705cfSriastradh v[1] = op->base.dst.y + box->y2; 219503b705cfSriastradh *((uint32_t *)v + 2) = alpha; 219603b705cfSriastradh v[3] = (op->base.src.offset[0] + box->x2) * op->base.src.scale[0]; 219703b705cfSriastradh v[4] = (op->base.src.offset[1] + box->y2) * op->base.src.scale[1]; 219803b705cfSriastradh 219903b705cfSriastradh v[5] = op->base.dst.x + box->x1; 220003b705cfSriastradh v[6] = v[1]; 220103b705cfSriastradh *((uint32_t *)v + 7) = alpha; 220203b705cfSriastradh v[8] = (op->base.src.offset[0] + box->x1) * op->base.src.scale[0]; 220303b705cfSriastradh v[9] = v[4]; 220403b705cfSriastradh 220503b705cfSriastradh v[10] = v[5]; 220603b705cfSriastradh v[11] = op->base.dst.y + box->y1; 220703b705cfSriastradh *((uint32_t *)v + 12) = alpha; 220803b705cfSriastradh v[13] = v[8]; 220903b705cfSriastradh v[14] = (op->base.src.offset[1] + box->y1) * op->base.src.scale[1]; 221003b705cfSriastradh} 221103b705cfSriastradh 221203b705cfSriastradhfastcall static void 221303b705cfSriastradhgen2_emit_composite_spans_primitive_affine_source(struct sna *sna, 221403b705cfSriastradh const struct sna_composite_spans_op *op, 221503b705cfSriastradh const BoxRec *box, 221603b705cfSriastradh float opacity) 221703b705cfSriastradh{ 221803b705cfSriastradh PictTransform *transform = op->base.src.transform; 221903b705cfSriastradh uint32_t alpha = (uint8_t)(255 * opacity) << 24; 222003b705cfSriastradh float *v; 222103b705cfSriastradh 222203b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 222303b705cfSriastradh sna->kgem.nbatch += 15; 222403b705cfSriastradh 222503b705cfSriastradh v[0] = op->base.dst.x + box->x2; 222603b705cfSriastradh v[6] = v[1] = op->base.dst.y + box->y2; 222703b705cfSriastradh v[10] = v[5] = op->base.dst.x + box->x1; 222803b705cfSriastradh v[11] = op->base.dst.y + box->y1; 222903b705cfSriastradh *((uint32_t *)v + 2) = alpha; 223003b705cfSriastradh *((uint32_t *)v + 7) = alpha; 223103b705cfSriastradh *((uint32_t *)v + 12) = alpha; 223203b705cfSriastradh 223303b705cfSriastradh _sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x2, 223403b705cfSriastradh (int)op->base.src.offset[1] + box->y2, 223503b705cfSriastradh transform, op->base.src.scale, 223603b705cfSriastradh &v[3], &v[4]); 223703b705cfSriastradh 223803b705cfSriastradh _sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x1, 223903b705cfSriastradh (int)op->base.src.offset[1] + box->y2, 224003b705cfSriastradh transform, op->base.src.scale, 224103b705cfSriastradh &v[8], &v[9]); 224203b705cfSriastradh 224303b705cfSriastradh _sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x1, 224403b705cfSriastradh (int)op->base.src.offset[1] + box->y1, 224503b705cfSriastradh transform, op->base.src.scale, 224603b705cfSriastradh &v[13], &v[14]); 224703b705cfSriastradh} 224803b705cfSriastradh 224903b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 225003b705cfSriastradhsse2 fastcall static void 225103b705cfSriastradhgen2_emit_composite_spans_primitive_constant__sse2(struct sna *sna, 225203b705cfSriastradh const struct sna_composite_spans_op *op, 225303b705cfSriastradh const BoxRec *box, 225403b705cfSriastradh float opacity) 225503b705cfSriastradh{ 225603b705cfSriastradh float *v = (float *)sna->kgem.batch + sna->kgem.nbatch; 225703b705cfSriastradh uint32_t alpha = (uint8_t)(255 * opacity) << 24; 225803b705cfSriastradh sna->kgem.nbatch += 9; 225903b705cfSriastradh 226003b705cfSriastradh v[0] = op->base.dst.x + box->x2; 226103b705cfSriastradh v[1] = op->base.dst.y + box->y2; 226203b705cfSriastradh *((uint32_t *)v + 2) = alpha; 226303b705cfSriastradh 226403b705cfSriastradh v[3] = op->base.dst.x + box->x1; 226503b705cfSriastradh v[4] = v[1]; 226603b705cfSriastradh *((uint32_t *)v + 5) = alpha; 226703b705cfSriastradh 226803b705cfSriastradh v[6] = v[3]; 226903b705cfSriastradh v[7] = op->base.dst.y + box->y1; 227003b705cfSriastradh *((uint32_t *)v + 8) = alpha; 227103b705cfSriastradh} 227203b705cfSriastradh 227303b705cfSriastradhsse2 fastcall static void 227403b705cfSriastradhgen2_emit_composite_spans_primitive_linear__sse2(struct sna *sna, 227503b705cfSriastradh const struct sna_composite_spans_op *op, 227603b705cfSriastradh const BoxRec *box, 227703b705cfSriastradh float opacity) 227803b705cfSriastradh{ 227903b705cfSriastradh union { 228003b705cfSriastradh float f; 228103b705cfSriastradh uint32_t u; 228203b705cfSriastradh } alpha; 228303b705cfSriastradh 228403b705cfSriastradh alpha.u = (uint8_t)(255 * opacity) << 24; 228503b705cfSriastradh 228603b705cfSriastradh gen2_emit_composite_dstcoord(sna, 228703b705cfSriastradh op->base.dst.x + box->x2, 228803b705cfSriastradh op->base.dst.y + box->y2); 228903b705cfSriastradh VERTEX(alpha.f); 229003b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, box->x2, box->y2); 229103b705cfSriastradh 229203b705cfSriastradh gen2_emit_composite_dstcoord(sna, 229303b705cfSriastradh op->base.dst.x + box->x1, 229403b705cfSriastradh op->base.dst.y + box->y2); 229503b705cfSriastradh VERTEX(alpha.f); 229603b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, box->x1, box->y2); 229703b705cfSriastradh 229803b705cfSriastradh gen2_emit_composite_dstcoord(sna, 229903b705cfSriastradh op->base.dst.x + box->x1, 230003b705cfSriastradh op->base.dst.y + box->y1); 230103b705cfSriastradh VERTEX(alpha.f); 230203b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, box->x1, box->y1); 230303b705cfSriastradh} 230403b705cfSriastradh 230503b705cfSriastradhsse2 fastcall static void 230603b705cfSriastradhgen2_emit_composite_spans_primitive_identity_source__sse2(struct sna *sna, 230703b705cfSriastradh const struct sna_composite_spans_op *op, 230803b705cfSriastradh const BoxRec *box, 230903b705cfSriastradh float opacity) 231003b705cfSriastradh{ 231103b705cfSriastradh float *v = (float *)sna->kgem.batch + sna->kgem.nbatch; 231203b705cfSriastradh uint32_t alpha = (uint8_t)(255 * opacity) << 24; 231303b705cfSriastradh sna->kgem.nbatch += 15; 231403b705cfSriastradh 231503b705cfSriastradh v[0] = op->base.dst.x + box->x2; 231603b705cfSriastradh v[1] = op->base.dst.y + box->y2; 231703b705cfSriastradh *((uint32_t *)v + 2) = alpha; 231803b705cfSriastradh v[3] = (op->base.src.offset[0] + box->x2) * op->base.src.scale[0]; 231903b705cfSriastradh v[4] = (op->base.src.offset[1] + box->y2) * op->base.src.scale[1]; 232003b705cfSriastradh 232103b705cfSriastradh v[5] = op->base.dst.x + box->x1; 232203b705cfSriastradh v[6] = v[1]; 232303b705cfSriastradh *((uint32_t *)v + 7) = alpha; 232403b705cfSriastradh v[8] = (op->base.src.offset[0] + box->x1) * op->base.src.scale[0]; 232503b705cfSriastradh v[9] = v[4]; 232603b705cfSriastradh 232703b705cfSriastradh v[10] = v[5]; 232803b705cfSriastradh v[11] = op->base.dst.y + box->y1; 232903b705cfSriastradh *((uint32_t *)v + 12) = alpha; 233003b705cfSriastradh v[13] = v[8]; 233103b705cfSriastradh v[14] = (op->base.src.offset[1] + box->y1) * op->base.src.scale[1]; 233203b705cfSriastradh} 233303b705cfSriastradh 233403b705cfSriastradhsse2 fastcall static void 233503b705cfSriastradhgen2_emit_composite_spans_primitive_affine_source__sse2(struct sna *sna, 233603b705cfSriastradh const struct sna_composite_spans_op *op, 233703b705cfSriastradh const BoxRec *box, 233803b705cfSriastradh float opacity) 233903b705cfSriastradh{ 234003b705cfSriastradh PictTransform *transform = op->base.src.transform; 234103b705cfSriastradh uint32_t alpha = (uint8_t)(255 * opacity) << 24; 234203b705cfSriastradh float *v; 234303b705cfSriastradh 234403b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 234503b705cfSriastradh sna->kgem.nbatch += 15; 234603b705cfSriastradh 234703b705cfSriastradh v[0] = op->base.dst.x + box->x2; 234803b705cfSriastradh v[6] = v[1] = op->base.dst.y + box->y2; 234903b705cfSriastradh v[10] = v[5] = op->base.dst.x + box->x1; 235003b705cfSriastradh v[11] = op->base.dst.y + box->y1; 235103b705cfSriastradh *((uint32_t *)v + 2) = alpha; 235203b705cfSriastradh *((uint32_t *)v + 7) = alpha; 235303b705cfSriastradh *((uint32_t *)v + 12) = alpha; 235403b705cfSriastradh 235503b705cfSriastradh _sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x2, 235603b705cfSriastradh (int)op->base.src.offset[1] + box->y2, 235703b705cfSriastradh transform, op->base.src.scale, 235803b705cfSriastradh &v[3], &v[4]); 235903b705cfSriastradh 236003b705cfSriastradh _sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x1, 236103b705cfSriastradh (int)op->base.src.offset[1] + box->y2, 236203b705cfSriastradh transform, op->base.src.scale, 236303b705cfSriastradh &v[8], &v[9]); 236403b705cfSriastradh 236503b705cfSriastradh _sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x1, 236603b705cfSriastradh (int)op->base.src.offset[1] + box->y1, 236703b705cfSriastradh transform, op->base.src.scale, 236803b705cfSriastradh &v[13], &v[14]); 236903b705cfSriastradh} 237003b705cfSriastradh#endif 237103b705cfSriastradh 237203b705cfSriastradhstatic void 237303b705cfSriastradhgen2_emit_composite_spans_vertex(struct sna *sna, 237403b705cfSriastradh const struct sna_composite_spans_op *op, 237503b705cfSriastradh int16_t x, int16_t y, 237603b705cfSriastradh float opacity) 237703b705cfSriastradh{ 237803b705cfSriastradh gen2_emit_composite_dstcoord(sna, x + op->base.dst.x, y + op->base.dst.y); 237903b705cfSriastradh BATCH((uint8_t)(opacity * 255) << 24); 238003b705cfSriastradh assert(!op->base.src.is_solid); 238103b705cfSriastradh if (op->base.src.is_linear) 238203b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, x, y); 238303b705cfSriastradh else 238403b705cfSriastradh gen2_emit_composite_texcoord(sna, &op->base.src, x, y); 238503b705cfSriastradh} 238603b705cfSriastradh 238703b705cfSriastradhfastcall static void 238803b705cfSriastradhgen2_emit_composite_spans_primitive(struct sna *sna, 238903b705cfSriastradh const struct sna_composite_spans_op *op, 239003b705cfSriastradh const BoxRec *box, 239103b705cfSriastradh float opacity) 239203b705cfSriastradh{ 239303b705cfSriastradh gen2_emit_composite_spans_vertex(sna, op, box->x2, box->y2, opacity); 239403b705cfSriastradh gen2_emit_composite_spans_vertex(sna, op, box->x1, box->y2, opacity); 239503b705cfSriastradh gen2_emit_composite_spans_vertex(sna, op, box->x1, box->y1, opacity); 239603b705cfSriastradh} 239703b705cfSriastradh 239803b705cfSriastradhstatic void 239903b705cfSriastradhgen2_emit_spans_pipeline(struct sna *sna, 240003b705cfSriastradh const struct sna_composite_spans_op *op) 240103b705cfSriastradh{ 240203b705cfSriastradh uint32_t cblend, ablend; 240303b705cfSriastradh uint32_t unwind; 240403b705cfSriastradh 240503b705cfSriastradh cblend = 240603b705cfSriastradh TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULATE | 240703b705cfSriastradh TB0C_ARG1_SEL_DIFFUSE | TB0C_ARG1_REPLICATE_ALPHA | 240803b705cfSriastradh TB0C_OUTPUT_WRITE_CURRENT; 240903b705cfSriastradh ablend = 241003b705cfSriastradh TB0A_RESULT_SCALE_1X | TB0A_OP_MODULATE | 241103b705cfSriastradh TB0A_ARG1_SEL_DIFFUSE | 241203b705cfSriastradh TB0A_OUTPUT_WRITE_CURRENT; 241303b705cfSriastradh 241403b705cfSriastradh if (op->base.src.is_solid) { 241503b705cfSriastradh ablend |= TB0A_ARG2_SEL_SPECULAR; 241603b705cfSriastradh cblend |= TB0C_ARG2_SEL_SPECULAR; 241703b705cfSriastradh if (op->base.dst.format == PICT_a8) 241803b705cfSriastradh cblend |= TB0C_ARG2_REPLICATE_ALPHA; 241903b705cfSriastradh } else if (op->base.dst.format == PICT_a8) { 242003b705cfSriastradh ablend |= TB0A_ARG2_SEL_TEXEL0; 242103b705cfSriastradh cblend |= TB0C_ARG2_SEL_TEXEL0 | TB0C_ARG2_REPLICATE_ALPHA; 242203b705cfSriastradh } else { 242303b705cfSriastradh if (PICT_FORMAT_RGB(op->base.src.pict_format) != 0) 242403b705cfSriastradh cblend |= TB0C_ARG2_SEL_TEXEL0; 242503b705cfSriastradh else 242603b705cfSriastradh cblend |= TB0C_ARG2_SEL_ONE | TB0C_ARG2_INVERT; 242703b705cfSriastradh 242803b705cfSriastradh if (op->base.src.is_opaque) 242903b705cfSriastradh ablend |= TB0A_ARG2_SEL_ONE; 243003b705cfSriastradh else 243103b705cfSriastradh ablend |= TB0A_ARG2_SEL_TEXEL0; 243203b705cfSriastradh } 243303b705cfSriastradh 243403b705cfSriastradh unwind = sna->kgem.nbatch; 243503b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 243603b705cfSriastradh LOAD_TEXTURE_BLEND_STAGE(0) | 1); 243703b705cfSriastradh BATCH(cblend); 243803b705cfSriastradh BATCH(ablend); 243903b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1, 244003b705cfSriastradh sna->kgem.batch + unwind + 1, 244103b705cfSriastradh 2 * sizeof(uint32_t)) == 0) 244203b705cfSriastradh sna->kgem.nbatch = unwind; 244303b705cfSriastradh else 244403b705cfSriastradh sna->render_state.gen2.ls2 = unwind; 244503b705cfSriastradh} 244603b705cfSriastradh 244703b705cfSriastradhstatic void gen2_emit_composite_spans_state(struct sna *sna, 244803b705cfSriastradh const struct sna_composite_spans_op *op) 244903b705cfSriastradh{ 245003b705cfSriastradh uint32_t unwind; 245103b705cfSriastradh 245203b705cfSriastradh gen2_get_batch(sna, &op->base); 2453fe8aea9eSmrg gen2_emit_target(sna, 2454fe8aea9eSmrg op->base.dst.bo, 2455fe8aea9eSmrg op->base.dst.width, 2456fe8aea9eSmrg op->base.dst.height, 2457fe8aea9eSmrg op->base.dst.format); 245803b705cfSriastradh 245903b705cfSriastradh unwind = sna->kgem.nbatch; 246003b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 246103b705cfSriastradh I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2); 246203b705cfSriastradh BATCH(!op->base.src.is_solid << 12); 246303b705cfSriastradh BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY | S3_DIFFUSE_PRESENT); 246403b705cfSriastradh BATCH(gen2_get_blend_cntl(op->base.op, false, op->base.dst.format)); 246503b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1, 246603b705cfSriastradh sna->kgem.batch + unwind + 1, 246703b705cfSriastradh 3 * sizeof(uint32_t)) == 0) 246803b705cfSriastradh sna->kgem.nbatch = unwind; 246903b705cfSriastradh else 247003b705cfSriastradh sna->render_state.gen2.ls1 = unwind; 247103b705cfSriastradh 247203b705cfSriastradh gen2_disable_logic_op(sna); 247303b705cfSriastradh gen2_emit_spans_pipeline(sna, op); 247403b705cfSriastradh 247503b705cfSriastradh if (op->base.src.is_solid) { 247603b705cfSriastradh if (op->base.src.u.gen2.pixel != sna->render_state.gen2.specular) { 247703b705cfSriastradh BATCH(_3DSTATE_DFLT_SPECULAR_CMD); 247803b705cfSriastradh BATCH(op->base.src.u.gen2.pixel); 247903b705cfSriastradh sna->render_state.gen2.specular = op->base.src.u.gen2.pixel; 248003b705cfSriastradh } 248103b705cfSriastradh } else { 248203b705cfSriastradh uint32_t v =_3DSTATE_VERTEX_FORMAT_2_CMD | 248303b705cfSriastradh (op->base.src.is_affine ? TEXCOORDFMT_2D : TEXCOORDFMT_3D); 248403b705cfSriastradh if (sna->render_state.gen2.vft != v) { 248503b705cfSriastradh BATCH(v); 248603b705cfSriastradh sna->render_state.gen2.vft = v; 248703b705cfSriastradh } 248803b705cfSriastradh gen2_emit_texture(sna, &op->base.src, 0); 248903b705cfSriastradh } 249003b705cfSriastradh} 249103b705cfSriastradh 249203b705cfSriastradhfastcall static void 249303b705cfSriastradhgen2_render_composite_spans_box(struct sna *sna, 249403b705cfSriastradh const struct sna_composite_spans_op *op, 249503b705cfSriastradh const BoxRec *box, float opacity) 249603b705cfSriastradh{ 249703b705cfSriastradh DBG(("%s: src=+(%d, %d), opacity=%f, dst=+(%d, %d), box=(%d, %d) x (%d, %d)\n", 249803b705cfSriastradh __FUNCTION__, 249903b705cfSriastradh op->base.src.offset[0], op->base.src.offset[1], 250003b705cfSriastradh opacity, 250103b705cfSriastradh op->base.dst.x, op->base.dst.y, 250203b705cfSriastradh box->x1, box->y1, 250303b705cfSriastradh box->x2 - box->x1, 250403b705cfSriastradh box->y2 - box->y1)); 250503b705cfSriastradh 250603b705cfSriastradh if (gen2_get_rectangles(sna, &op->base, 1) == 0) { 250703b705cfSriastradh gen2_emit_composite_spans_state(sna, op); 250803b705cfSriastradh gen2_get_rectangles(sna, &op->base, 1); 250903b705cfSriastradh } 251003b705cfSriastradh 251103b705cfSriastradh op->prim_emit(sna, op, box, opacity); 251203b705cfSriastradh} 251303b705cfSriastradh 251403b705cfSriastradhstatic void 251503b705cfSriastradhgen2_render_composite_spans_boxes(struct sna *sna, 251603b705cfSriastradh const struct sna_composite_spans_op *op, 251703b705cfSriastradh const BoxRec *box, int nbox, 251803b705cfSriastradh float opacity) 251903b705cfSriastradh{ 252003b705cfSriastradh DBG(("%s: nbox=%d, src=+(%d, %d), opacity=%f, dst=+(%d, %d)\n", 252103b705cfSriastradh __FUNCTION__, nbox, 252203b705cfSriastradh op->base.src.offset[0], op->base.src.offset[1], 252303b705cfSriastradh opacity, 252403b705cfSriastradh op->base.dst.x, op->base.dst.y)); 252503b705cfSriastradh 252603b705cfSriastradh do { 252703b705cfSriastradh int nbox_this_time; 252803b705cfSriastradh 252903b705cfSriastradh nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox); 253003b705cfSriastradh if (nbox_this_time == 0) { 253103b705cfSriastradh gen2_emit_composite_spans_state(sna, op); 253203b705cfSriastradh nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox); 253303b705cfSriastradh } 253403b705cfSriastradh nbox -= nbox_this_time; 253503b705cfSriastradh 253603b705cfSriastradh do { 253703b705cfSriastradh DBG((" %s: (%d, %d) x (%d, %d)\n", __FUNCTION__, 253803b705cfSriastradh box->x1, box->y1, 253903b705cfSriastradh box->x2 - box->x1, 254003b705cfSriastradh box->y2 - box->y1)); 254103b705cfSriastradh 254203b705cfSriastradh op->prim_emit(sna, op, box++, opacity); 254303b705cfSriastradh } while (--nbox_this_time); 254403b705cfSriastradh } while (nbox); 254503b705cfSriastradh} 254603b705cfSriastradh 254703b705cfSriastradhfastcall static void 254803b705cfSriastradhgen2_render_composite_spans_done(struct sna *sna, 254903b705cfSriastradh const struct sna_composite_spans_op *op) 255003b705cfSriastradh{ 255103b705cfSriastradh DBG(("%s()\n", __FUNCTION__)); 255203b705cfSriastradh 255303b705cfSriastradh gen2_vertex_flush(sna, &op->base); 255403b705cfSriastradh 255503b705cfSriastradh if (op->base.src.bo) 255603b705cfSriastradh kgem_bo_destroy(&sna->kgem, op->base.src.bo); 255703b705cfSriastradh 255803b705cfSriastradh sna_render_composite_redirect_done(sna, &op->base); 255903b705cfSriastradh} 256003b705cfSriastradh 256103b705cfSriastradhstatic bool 256203b705cfSriastradhgen2_check_composite_spans(struct sna *sna, 256303b705cfSriastradh uint8_t op, PicturePtr src, PicturePtr dst, 256403b705cfSriastradh int16_t width, int16_t height, unsigned flags) 256503b705cfSriastradh{ 256603b705cfSriastradh if (op >= ARRAY_SIZE(gen2_blend_op)) 256703b705cfSriastradh return false; 256803b705cfSriastradh 256903b705cfSriastradh if (gen2_composite_fallback(sna, src, NULL, dst)) 257003b705cfSriastradh return false; 257103b705cfSriastradh 257203b705cfSriastradh if (need_tiling(sna, width, height)) { 257303b705cfSriastradh if (!is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) { 257403b705cfSriastradh DBG(("%s: fallback, tiled operation not on GPU\n", 257503b705cfSriastradh __FUNCTION__)); 257603b705cfSriastradh return false; 257703b705cfSriastradh } 257803b705cfSriastradh } 257903b705cfSriastradh 258003b705cfSriastradh return true; 258103b705cfSriastradh} 258203b705cfSriastradh 258303b705cfSriastradhstatic bool 258403b705cfSriastradhgen2_render_composite_spans(struct sna *sna, 258503b705cfSriastradh uint8_t op, 258603b705cfSriastradh PicturePtr src, 258703b705cfSriastradh PicturePtr dst, 258803b705cfSriastradh int16_t src_x, int16_t src_y, 258903b705cfSriastradh int16_t dst_x, int16_t dst_y, 259003b705cfSriastradh int16_t width, int16_t height, 259103b705cfSriastradh unsigned flags, 259203b705cfSriastradh struct sna_composite_spans_op *tmp) 259303b705cfSriastradh{ 259403b705cfSriastradh DBG(("%s(src=(%d, %d), dst=(%d, %d), size=(%d, %d))\n", __FUNCTION__, 259503b705cfSriastradh src_x, src_y, dst_x, dst_y, width, height)); 259603b705cfSriastradh 259703b705cfSriastradh assert(gen2_check_composite_spans(sna, op, src, dst, width, height, flags)); 259803b705cfSriastradh if (need_tiling(sna, width, height)) { 259903b705cfSriastradh DBG(("%s: tiling, operation (%dx%d) too wide for pipeline\n", 260003b705cfSriastradh __FUNCTION__, width, height)); 260103b705cfSriastradh return sna_tiling_composite_spans(op, src, dst, 260203b705cfSriastradh src_x, src_y, dst_x, dst_y, 260303b705cfSriastradh width, height, flags, tmp); 260403b705cfSriastradh } 260503b705cfSriastradh 260642542f5fSchristos tmp->base.op = op; 260742542f5fSchristos sna_render_composite_redirect_init(&tmp->base); 260803b705cfSriastradh if (!gen2_composite_set_target(sna, &tmp->base, dst, 260942542f5fSchristos dst_x, dst_y, width, height, 261042542f5fSchristos true)) { 261103b705cfSriastradh DBG(("%s: unable to set render target\n", 261203b705cfSriastradh __FUNCTION__)); 261303b705cfSriastradh return false; 261403b705cfSriastradh } 261503b705cfSriastradh 261603b705cfSriastradh switch (gen2_composite_picture(sna, src, &tmp->base.src, 261703b705cfSriastradh src_x, src_y, 261803b705cfSriastradh width, height, 261903b705cfSriastradh dst_x, dst_y, 262003b705cfSriastradh dst->polyMode == PolyModePrecise)) { 262103b705cfSriastradh case -1: 262203b705cfSriastradh goto cleanup_dst; 262303b705cfSriastradh case 0: 262403b705cfSriastradh gen2_composite_solid_init(sna, &tmp->base.src, 0); 262503b705cfSriastradh case 1: 262603b705cfSriastradh break; 262703b705cfSriastradh } 262842542f5fSchristos assert(tmp->base.src.bo || tmp->base.src.is_solid); 262903b705cfSriastradh 263003b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive; 263103b705cfSriastradh tmp->base.floats_per_vertex = 3; 263203b705cfSriastradh if (tmp->base.src.is_solid) { 263303b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 263403b705cfSriastradh if (sna->cpu_features & SSE2) { 263503b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_constant__sse2; 263603b705cfSriastradh } else 263703b705cfSriastradh#endif 263803b705cfSriastradh { 263903b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_constant; 264003b705cfSriastradh } 264103b705cfSriastradh } else if (tmp->base.src.is_linear) { 264203b705cfSriastradh tmp->base.floats_per_vertex += 2; 264303b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 264403b705cfSriastradh if (sna->cpu_features & SSE2) { 264503b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_linear__sse2; 264603b705cfSriastradh } else 264703b705cfSriastradh#endif 264803b705cfSriastradh { 264903b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_linear; 265003b705cfSriastradh } 265103b705cfSriastradh } else { 265203b705cfSriastradh assert(tmp->base.src.bo); 265303b705cfSriastradh tmp->base.floats_per_vertex += tmp->base.src.is_affine ? 2 : 3; 265403b705cfSriastradh if (tmp->base.src.transform == NULL) { 265503b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 265603b705cfSriastradh if (sna->cpu_features & SSE2) { 265703b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_identity_source__sse2; 265803b705cfSriastradh } else 265903b705cfSriastradh#endif 266003b705cfSriastradh { 266103b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_identity_source; 266203b705cfSriastradh } 266303b705cfSriastradh } else if (tmp->base.src.is_affine) { 266403b705cfSriastradh tmp->base.src.scale[0] /= tmp->base.src.transform->matrix[2][2]; 266503b705cfSriastradh tmp->base.src.scale[1] /= tmp->base.src.transform->matrix[2][2]; 266603b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 266703b705cfSriastradh if (sna->cpu_features & SSE2) { 266803b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_affine_source__sse2; 266903b705cfSriastradh } else 267003b705cfSriastradh#endif 267103b705cfSriastradh { 267203b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_affine_source; 267303b705cfSriastradh } 267403b705cfSriastradh } 267503b705cfSriastradh } 267603b705cfSriastradh tmp->base.mask.bo = NULL; 267703b705cfSriastradh tmp->base.floats_per_rect = 3*tmp->base.floats_per_vertex; 267803b705cfSriastradh 267903b705cfSriastradh tmp->box = gen2_render_composite_spans_box; 268003b705cfSriastradh tmp->boxes = gen2_render_composite_spans_boxes; 268103b705cfSriastradh tmp->done = gen2_render_composite_spans_done; 268203b705cfSriastradh 268303b705cfSriastradh if (!kgem_check_bo(&sna->kgem, 268403b705cfSriastradh tmp->base.dst.bo, tmp->base.src.bo, 268503b705cfSriastradh NULL)) { 268603b705cfSriastradh kgem_submit(&sna->kgem); 268703b705cfSriastradh if (!kgem_check_bo(&sna->kgem, 268803b705cfSriastradh tmp->base.dst.bo, tmp->base.src.bo, 268903b705cfSriastradh NULL)) 269003b705cfSriastradh goto cleanup_src; 269103b705cfSriastradh } 269203b705cfSriastradh 269303b705cfSriastradh gen2_emit_composite_spans_state(sna, tmp); 269403b705cfSriastradh return true; 269503b705cfSriastradh 269603b705cfSriastradhcleanup_src: 269703b705cfSriastradh if (tmp->base.src.bo) 269803b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->base.src.bo); 269903b705cfSriastradhcleanup_dst: 270003b705cfSriastradh if (tmp->base.redirect.real_bo) 270103b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->base.dst.bo); 270203b705cfSriastradh return false; 270303b705cfSriastradh} 270403b705cfSriastradh 270503b705cfSriastradhstatic void 270603b705cfSriastradhgen2_emit_fill_pipeline(struct sna *sna, const struct sna_composite_op *op) 270703b705cfSriastradh{ 270803b705cfSriastradh uint32_t blend, unwind; 270903b705cfSriastradh 271003b705cfSriastradh unwind = sna->kgem.nbatch; 271103b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 271203b705cfSriastradh LOAD_TEXTURE_BLEND_STAGE(0) | 1); 271303b705cfSriastradh 271403b705cfSriastradh blend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_ARG1 | 271503b705cfSriastradh TB0C_ARG1_SEL_DIFFUSE | 271603b705cfSriastradh TB0C_OUTPUT_WRITE_CURRENT; 271703b705cfSriastradh if (op->dst.format == PICT_a8) 271803b705cfSriastradh blend |= TB0C_ARG1_REPLICATE_ALPHA; 271903b705cfSriastradh BATCH(blend); 272003b705cfSriastradh 272103b705cfSriastradh BATCH(TB0A_RESULT_SCALE_1X | TB0A_OP_ARG1 | 272203b705cfSriastradh TB0A_ARG1_SEL_DIFFUSE | 272303b705cfSriastradh TB0A_OUTPUT_WRITE_CURRENT); 272403b705cfSriastradh 272503b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1, 272603b705cfSriastradh sna->kgem.batch + unwind + 1, 272703b705cfSriastradh 2 * sizeof(uint32_t)) == 0) 272803b705cfSriastradh sna->kgem.nbatch = unwind; 272903b705cfSriastradh else 273003b705cfSriastradh sna->render_state.gen2.ls2 = unwind; 273103b705cfSriastradh} 273203b705cfSriastradh 273303b705cfSriastradhstatic void gen2_emit_fill_composite_state(struct sna *sna, 273403b705cfSriastradh const struct sna_composite_op *op, 273503b705cfSriastradh uint32_t pixel) 273603b705cfSriastradh{ 273703b705cfSriastradh uint32_t ls1; 273803b705cfSriastradh 273903b705cfSriastradh gen2_get_batch(sna, op); 2740fe8aea9eSmrg gen2_emit_target(sna, 2741fe8aea9eSmrg op->dst.bo, 2742fe8aea9eSmrg op->dst.width, 2743fe8aea9eSmrg op->dst.height, 2744fe8aea9eSmrg op->dst.format); 274503b705cfSriastradh 274603b705cfSriastradh ls1 = sna->kgem.nbatch; 274703b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 274803b705cfSriastradh I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2); 274903b705cfSriastradh BATCH(0); 275003b705cfSriastradh BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY); 275103b705cfSriastradh BATCH(gen2_get_blend_cntl(op->op, false, op->dst.format)); 275203b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1, 275303b705cfSriastradh sna->kgem.batch + ls1 + 1, 275403b705cfSriastradh 3 * sizeof(uint32_t)) == 0) 275503b705cfSriastradh sna->kgem.nbatch = ls1; 275603b705cfSriastradh else 275703b705cfSriastradh sna->render_state.gen2.ls1 = ls1; 275803b705cfSriastradh 275903b705cfSriastradh gen2_emit_fill_pipeline(sna, op); 276003b705cfSriastradh 276103b705cfSriastradh if (pixel != sna->render_state.gen2.diffuse) { 276203b705cfSriastradh BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); 276303b705cfSriastradh BATCH(pixel); 276403b705cfSriastradh sna->render_state.gen2.diffuse = pixel; 276503b705cfSriastradh } 276603b705cfSriastradh} 276703b705cfSriastradh 276803b705cfSriastradhstatic bool 276903b705cfSriastradhgen2_render_fill_boxes_try_blt(struct sna *sna, 277003b705cfSriastradh CARD8 op, PictFormat format, 277103b705cfSriastradh const xRenderColor *color, 277242542f5fSchristos const DrawableRec *dst, struct kgem_bo *dst_bo, 277303b705cfSriastradh const BoxRec *box, int n) 277403b705cfSriastradh{ 277503b705cfSriastradh uint8_t alu; 277603b705cfSriastradh uint32_t pixel; 277703b705cfSriastradh 277803b705cfSriastradh if (op > PictOpSrc) 277903b705cfSriastradh return false; 278003b705cfSriastradh 278103b705cfSriastradh if (op == PictOpClear) { 278203b705cfSriastradh alu = GXclear; 278303b705cfSriastradh pixel = 0; 278403b705cfSriastradh } else if (!sna_get_pixel_from_rgba(&pixel, 278503b705cfSriastradh color->red, 278603b705cfSriastradh color->green, 278703b705cfSriastradh color->blue, 278803b705cfSriastradh color->alpha, 278903b705cfSriastradh format)) 279003b705cfSriastradh return false; 279103b705cfSriastradh else 279203b705cfSriastradh alu = GXcopy; 279303b705cfSriastradh 279403b705cfSriastradh return sna_blt_fill_boxes(sna, alu, 279542542f5fSchristos dst_bo, dst->bitsPerPixel, 279603b705cfSriastradh pixel, box, n); 279703b705cfSriastradh} 279803b705cfSriastradh 279903b705cfSriastradhstatic bool 280003b705cfSriastradhgen2_render_fill_boxes(struct sna *sna, 280103b705cfSriastradh CARD8 op, 280203b705cfSriastradh PictFormat format, 280303b705cfSriastradh const xRenderColor *color, 280442542f5fSchristos const DrawableRec *dst, struct kgem_bo *dst_bo, 280503b705cfSriastradh const BoxRec *box, int n) 280603b705cfSriastradh{ 280703b705cfSriastradh struct sna_composite_op tmp; 280803b705cfSriastradh uint32_t pixel; 280903b705cfSriastradh 281003b705cfSriastradh if (op >= ARRAY_SIZE(gen2_blend_op)) { 281103b705cfSriastradh DBG(("%s: fallback due to unhandled blend op: %d\n", 281203b705cfSriastradh __FUNCTION__, op)); 281303b705cfSriastradh return false; 281403b705cfSriastradh } 281503b705cfSriastradh 281603b705cfSriastradh#if NO_FILL_BOXES 281703b705cfSriastradh return gen2_render_fill_boxes_try_blt(sna, op, format, color, 281803b705cfSriastradh dst, dst_bo, 281903b705cfSriastradh box, n); 282003b705cfSriastradh#endif 282103b705cfSriastradh if (gen2_render_fill_boxes_try_blt(sna, op, format, color, 282203b705cfSriastradh dst, dst_bo, 282303b705cfSriastradh box, n)) 282403b705cfSriastradh return true; 282503b705cfSriastradh 282603b705cfSriastradh 282703b705cfSriastradh DBG(("%s (op=%d, format=%x, color=(%04x,%04x,%04x, %04x))\n", 282803b705cfSriastradh __FUNCTION__, op, (int)format, 282903b705cfSriastradh color->red, color->green, color->blue, color->alpha)); 283003b705cfSriastradh 283142542f5fSchristos if (too_large(dst->width, dst->height) || 283203b705cfSriastradh dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH || 283303b705cfSriastradh !gen2_check_dst_format(format)) { 283403b705cfSriastradh DBG(("%s: try blt, too large or incompatible destination\n", 283503b705cfSriastradh __FUNCTION__)); 283603b705cfSriastradh if (!gen2_check_dst_format(format)) 283703b705cfSriastradh return false; 283803b705cfSriastradh 283903b705cfSriastradh assert(dst_bo->pitch >= 8); 284003b705cfSriastradh return sna_tiling_fill_boxes(sna, op, format, color, 284103b705cfSriastradh dst, dst_bo, box, n); 284203b705cfSriastradh } 284303b705cfSriastradh 284403b705cfSriastradh if (op == PictOpClear) 284503b705cfSriastradh pixel = 0; 284603b705cfSriastradh else if (!sna_get_pixel_from_rgba(&pixel, 284703b705cfSriastradh color->red, 284803b705cfSriastradh color->green, 284903b705cfSriastradh color->blue, 285003b705cfSriastradh color->alpha, 285103b705cfSriastradh PICT_a8r8g8b8)) 285203b705cfSriastradh return false; 285303b705cfSriastradh 285403b705cfSriastradh DBG(("%s: using shader for op=%d, format=%x, pixel=%x\n", 285503b705cfSriastradh __FUNCTION__, op, (int)format, pixel)); 285603b705cfSriastradh 285703b705cfSriastradh memset(&tmp, 0, sizeof(tmp)); 285803b705cfSriastradh tmp.op = op; 285942542f5fSchristos tmp.dst.pixmap = (PixmapPtr)dst; 286042542f5fSchristos tmp.dst.width = dst->width; 286142542f5fSchristos tmp.dst.height = dst->height; 286203b705cfSriastradh tmp.dst.format = format; 286303b705cfSriastradh tmp.dst.bo = dst_bo; 286403b705cfSriastradh tmp.floats_per_vertex = 2; 286503b705cfSriastradh tmp.floats_per_rect = 6; 286603b705cfSriastradh 286703b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) { 286803b705cfSriastradh kgem_submit(&sna->kgem); 286942542f5fSchristos if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) 287042542f5fSchristos return false; 287103b705cfSriastradh } 287203b705cfSriastradh 287303b705cfSriastradh gen2_emit_fill_composite_state(sna, &tmp, pixel); 287403b705cfSriastradh 287503b705cfSriastradh do { 287603b705cfSriastradh int n_this_time = gen2_get_rectangles(sna, &tmp, n); 287703b705cfSriastradh if (n_this_time == 0) { 287803b705cfSriastradh gen2_emit_fill_composite_state(sna, &tmp, pixel); 287903b705cfSriastradh n_this_time = gen2_get_rectangles(sna, &tmp, n); 288003b705cfSriastradh } 288103b705cfSriastradh n -= n_this_time; 288203b705cfSriastradh 288303b705cfSriastradh do { 288403b705cfSriastradh DBG((" (%d, %d), (%d, %d): %x\n", 288503b705cfSriastradh box->x1, box->y1, box->x2, box->y2, pixel)); 288603b705cfSriastradh VERTEX(box->x2); 288703b705cfSriastradh VERTEX(box->y2); 288803b705cfSriastradh VERTEX(box->x1); 288903b705cfSriastradh VERTEX(box->y2); 289003b705cfSriastradh VERTEX(box->x1); 289103b705cfSriastradh VERTEX(box->y1); 289203b705cfSriastradh box++; 289303b705cfSriastradh } while (--n_this_time); 289403b705cfSriastradh } while (n); 289503b705cfSriastradh 289603b705cfSriastradh gen2_vertex_flush(sna, &tmp); 289703b705cfSriastradh return true; 289803b705cfSriastradh} 289903b705cfSriastradh 290003b705cfSriastradhstatic void gen2_emit_fill_state(struct sna *sna, 290103b705cfSriastradh const struct sna_composite_op *op) 290203b705cfSriastradh{ 290303b705cfSriastradh uint32_t ls1; 290403b705cfSriastradh 290503b705cfSriastradh gen2_get_batch(sna, op); 2906fe8aea9eSmrg gen2_emit_target(sna, 2907fe8aea9eSmrg op->dst.bo, 2908fe8aea9eSmrg op->dst.width, 2909fe8aea9eSmrg op->dst.height, 2910fe8aea9eSmrg op->dst.format); 291103b705cfSriastradh 291203b705cfSriastradh ls1 = sna->kgem.nbatch; 291303b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 291403b705cfSriastradh I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2); 291503b705cfSriastradh BATCH(0); 291603b705cfSriastradh BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY); 291703b705cfSriastradh BATCH(S8_ENABLE_COLOR_BUFFER_WRITE); 291803b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1, 291903b705cfSriastradh sna->kgem.batch + ls1 + 1, 292003b705cfSriastradh 3 * sizeof(uint32_t)) == 0) 292103b705cfSriastradh sna->kgem.nbatch = ls1; 292203b705cfSriastradh else 292303b705cfSriastradh sna->render_state.gen2.ls1 = ls1; 292403b705cfSriastradh 292503b705cfSriastradh gen2_enable_logic_op(sna, op->op); 292603b705cfSriastradh gen2_emit_fill_pipeline(sna, op); 292703b705cfSriastradh 292803b705cfSriastradh if (op->src.u.gen2.pixel != sna->render_state.gen2.diffuse) { 292903b705cfSriastradh BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); 293003b705cfSriastradh BATCH(op->src.u.gen2.pixel); 293103b705cfSriastradh sna->render_state.gen2.diffuse = op->src.u.gen2.pixel; 293203b705cfSriastradh } 293303b705cfSriastradh} 293403b705cfSriastradh 293503b705cfSriastradhstatic void 293603b705cfSriastradhgen2_render_fill_op_blt(struct sna *sna, 293703b705cfSriastradh const struct sna_fill_op *op, 293803b705cfSriastradh int16_t x, int16_t y, int16_t w, int16_t h) 293903b705cfSriastradh{ 294003b705cfSriastradh if (!gen2_get_rectangles(sna, &op->base, 1)) { 294103b705cfSriastradh gen2_emit_fill_state(sna, &op->base); 294203b705cfSriastradh gen2_get_rectangles(sna, &op->base, 1); 294303b705cfSriastradh } 294403b705cfSriastradh 294503b705cfSriastradh VERTEX(x+w); 294603b705cfSriastradh VERTEX(y+h); 294703b705cfSriastradh VERTEX(x); 294803b705cfSriastradh VERTEX(y+h); 294903b705cfSriastradh VERTEX(x); 295003b705cfSriastradh VERTEX(y); 295103b705cfSriastradh} 295203b705cfSriastradh 295303b705cfSriastradhfastcall static void 295403b705cfSriastradhgen2_render_fill_op_box(struct sna *sna, 295503b705cfSriastradh const struct sna_fill_op *op, 295603b705cfSriastradh const BoxRec *box) 295703b705cfSriastradh{ 295803b705cfSriastradh if (!gen2_get_rectangles(sna, &op->base, 1)) { 295903b705cfSriastradh gen2_emit_fill_state(sna, &op->base); 296003b705cfSriastradh gen2_get_rectangles(sna, &op->base, 1); 296103b705cfSriastradh } 296203b705cfSriastradh 296303b705cfSriastradh VERTEX(box->x2); 296403b705cfSriastradh VERTEX(box->y2); 296503b705cfSriastradh VERTEX(box->x1); 296603b705cfSriastradh VERTEX(box->y2); 296703b705cfSriastradh VERTEX(box->x1); 296803b705cfSriastradh VERTEX(box->y1); 296903b705cfSriastradh} 297003b705cfSriastradh 297103b705cfSriastradhfastcall static void 297203b705cfSriastradhgen2_render_fill_op_boxes(struct sna *sna, 297303b705cfSriastradh const struct sna_fill_op *op, 297403b705cfSriastradh const BoxRec *box, 297503b705cfSriastradh int nbox) 297603b705cfSriastradh{ 297703b705cfSriastradh DBG(("%s: (%d, %d),(%d, %d)... x %d\n", __FUNCTION__, 297803b705cfSriastradh box->x1, box->y1, box->x2, box->y2, nbox)); 297903b705cfSriastradh 298003b705cfSriastradh do { 298103b705cfSriastradh int nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox); 298203b705cfSriastradh if (nbox_this_time == 0) { 298303b705cfSriastradh gen2_emit_fill_state(sna, &op->base); 298403b705cfSriastradh nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox); 298503b705cfSriastradh } 298603b705cfSriastradh nbox -= nbox_this_time; 298703b705cfSriastradh 298803b705cfSriastradh do { 298903b705cfSriastradh VERTEX(box->x2); 299003b705cfSriastradh VERTEX(box->y2); 299103b705cfSriastradh VERTEX(box->x1); 299203b705cfSriastradh VERTEX(box->y2); 299303b705cfSriastradh VERTEX(box->x1); 299403b705cfSriastradh VERTEX(box->y1); 299503b705cfSriastradh box++; 299603b705cfSriastradh } while (--nbox_this_time); 299703b705cfSriastradh } while (nbox); 299803b705cfSriastradh} 299903b705cfSriastradh 300003b705cfSriastradhstatic void 300103b705cfSriastradhgen2_render_fill_op_done(struct sna *sna, const struct sna_fill_op *op) 300203b705cfSriastradh{ 300303b705cfSriastradh gen2_vertex_flush(sna, &op->base); 300403b705cfSriastradh} 300503b705cfSriastradh 300603b705cfSriastradhstatic bool 300703b705cfSriastradhgen2_render_fill(struct sna *sna, uint8_t alu, 300803b705cfSriastradh PixmapPtr dst, struct kgem_bo *dst_bo, 300942542f5fSchristos uint32_t color, unsigned flags, 301003b705cfSriastradh struct sna_fill_op *tmp) 301103b705cfSriastradh{ 301203b705cfSriastradh#if NO_FILL 301303b705cfSriastradh return sna_blt_fill(sna, alu, 301403b705cfSriastradh dst_bo, dst->drawable.bitsPerPixel, 301503b705cfSriastradh color, 301603b705cfSriastradh tmp); 301703b705cfSriastradh#endif 301803b705cfSriastradh 301903b705cfSriastradh /* Prefer to use the BLT if already engaged */ 302003b705cfSriastradh if (sna_blt_fill(sna, alu, 302103b705cfSriastradh dst_bo, dst->drawable.bitsPerPixel, 302203b705cfSriastradh color, 302303b705cfSriastradh tmp)) 302403b705cfSriastradh return true; 302503b705cfSriastradh 302603b705cfSriastradh /* Must use the BLT if we can't RENDER... */ 302703b705cfSriastradh if (too_large(dst->drawable.width, dst->drawable.height) || 302803b705cfSriastradh dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH) 302903b705cfSriastradh return false; 303003b705cfSriastradh 303103b705cfSriastradh tmp->base.op = alu; 303203b705cfSriastradh tmp->base.dst.pixmap = dst; 303303b705cfSriastradh tmp->base.dst.width = dst->drawable.width; 303403b705cfSriastradh tmp->base.dst.height = dst->drawable.height; 303503b705cfSriastradh tmp->base.dst.format = sna_format_for_depth(dst->drawable.depth); 303603b705cfSriastradh tmp->base.dst.bo = dst_bo; 303703b705cfSriastradh tmp->base.dst.x = tmp->base.dst.y = 0; 303803b705cfSriastradh tmp->base.floats_per_vertex = 2; 303903b705cfSriastradh tmp->base.floats_per_rect = 6; 304003b705cfSriastradh 304103b705cfSriastradh tmp->base.src.u.gen2.pixel = 304203b705cfSriastradh sna_rgba_for_color(color, dst->drawable.depth); 304303b705cfSriastradh 304403b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) { 304503b705cfSriastradh kgem_submit(&sna->kgem); 304603b705cfSriastradh return sna_blt_fill(sna, alu, 304703b705cfSriastradh dst_bo, dst->drawable.bitsPerPixel, 304803b705cfSriastradh color, 304903b705cfSriastradh tmp); 305003b705cfSriastradh } 305103b705cfSriastradh 305203b705cfSriastradh tmp->blt = gen2_render_fill_op_blt; 305303b705cfSriastradh tmp->box = gen2_render_fill_op_box; 305403b705cfSriastradh tmp->boxes = gen2_render_fill_op_boxes; 305542542f5fSchristos tmp->points = NULL; 305603b705cfSriastradh tmp->done = gen2_render_fill_op_done; 305703b705cfSriastradh 305803b705cfSriastradh gen2_emit_fill_state(sna, &tmp->base); 305903b705cfSriastradh return true; 306003b705cfSriastradh} 306103b705cfSriastradh 306203b705cfSriastradhstatic bool 306303b705cfSriastradhgen2_render_fill_one_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo, 306403b705cfSriastradh uint32_t color, 306503b705cfSriastradh int16_t x1, int16_t y1, int16_t x2, int16_t y2, 306603b705cfSriastradh uint8_t alu) 306703b705cfSriastradh{ 306803b705cfSriastradh BoxRec box; 306903b705cfSriastradh 307003b705cfSriastradh box.x1 = x1; 307103b705cfSriastradh box.y1 = y1; 307203b705cfSriastradh box.x2 = x2; 307303b705cfSriastradh box.y2 = y2; 307403b705cfSriastradh 307503b705cfSriastradh return sna_blt_fill_boxes(sna, alu, 307603b705cfSriastradh bo, dst->drawable.bitsPerPixel, 307703b705cfSriastradh color, &box, 1); 307803b705cfSriastradh} 307903b705cfSriastradh 308003b705cfSriastradhstatic bool 308103b705cfSriastradhgen2_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo, 308203b705cfSriastradh uint32_t color, 308303b705cfSriastradh int16_t x1, int16_t y1, 308403b705cfSriastradh int16_t x2, int16_t y2, 308503b705cfSriastradh uint8_t alu) 308603b705cfSriastradh{ 308703b705cfSriastradh struct sna_composite_op tmp; 308803b705cfSriastradh 308903b705cfSriastradh#if NO_FILL_ONE 309003b705cfSriastradh return gen2_render_fill_one_try_blt(sna, dst, bo, color, 309103b705cfSriastradh x1, y1, x2, y2, alu); 309203b705cfSriastradh#endif 309303b705cfSriastradh 309403b705cfSriastradh /* Prefer to use the BLT if already engaged */ 309503b705cfSriastradh if (gen2_render_fill_one_try_blt(sna, dst, bo, color, 309603b705cfSriastradh x1, y1, x2, y2, alu)) 309703b705cfSriastradh return true; 309803b705cfSriastradh 309903b705cfSriastradh /* Must use the BLT if we can't RENDER... */ 310003b705cfSriastradh if (too_large(dst->drawable.width, dst->drawable.height) || 310103b705cfSriastradh bo->pitch < 8 || bo->pitch > MAX_3D_PITCH) 310203b705cfSriastradh return false; 310303b705cfSriastradh 310403b705cfSriastradh if (!kgem_check_bo(&sna->kgem, bo, NULL)) { 310503b705cfSriastradh kgem_submit(&sna->kgem); 310642542f5fSchristos 310703b705cfSriastradh if (gen2_render_fill_one_try_blt(sna, dst, bo, color, 310803b705cfSriastradh x1, y1, x2, y2, alu)) 310903b705cfSriastradh return true; 311042542f5fSchristos 311142542f5fSchristos if (!kgem_check_bo(&sna->kgem, bo, NULL)) 311242542f5fSchristos return false; 311303b705cfSriastradh } 311403b705cfSriastradh 311503b705cfSriastradh tmp.op = alu; 311603b705cfSriastradh tmp.dst.pixmap = dst; 311703b705cfSriastradh tmp.dst.width = dst->drawable.width; 311803b705cfSriastradh tmp.dst.height = dst->drawable.height; 311903b705cfSriastradh tmp.dst.format = sna_format_for_depth(dst->drawable.depth); 312003b705cfSriastradh tmp.dst.bo = bo; 312103b705cfSriastradh tmp.floats_per_vertex = 2; 312203b705cfSriastradh tmp.floats_per_rect = 6; 312303b705cfSriastradh tmp.need_magic_ca_pass = false; 312403b705cfSriastradh 312503b705cfSriastradh tmp.src.u.gen2.pixel = 312603b705cfSriastradh sna_rgba_for_color(color, dst->drawable.depth); 312703b705cfSriastradh 312803b705cfSriastradh gen2_emit_fill_state(sna, &tmp); 312903b705cfSriastradh gen2_get_rectangles(sna, &tmp, 1); 313003b705cfSriastradh DBG(("%s: (%d, %d), (%d, %d): %x\n", __FUNCTION__, 313103b705cfSriastradh x1, y1, x2, y2, tmp.src.u.gen2.pixel)); 313203b705cfSriastradh VERTEX(x2); 313303b705cfSriastradh VERTEX(y2); 313403b705cfSriastradh VERTEX(x1); 313503b705cfSriastradh VERTEX(y2); 313603b705cfSriastradh VERTEX(x1); 313703b705cfSriastradh VERTEX(y1); 313803b705cfSriastradh gen2_vertex_flush(sna, &tmp); 313903b705cfSriastradh 314003b705cfSriastradh return true; 314103b705cfSriastradh} 314203b705cfSriastradh 3143fe8aea9eSmrgstatic void 3144fe8aea9eSmrggen2_emit_video_state(struct sna *sna, 3145fe8aea9eSmrg struct sna_video *video, 3146fe8aea9eSmrg struct sna_video_frame *frame, 3147fe8aea9eSmrg PixmapPtr pixmap, 3148fe8aea9eSmrg struct kgem_bo *dst_bo, 3149fe8aea9eSmrg int width, int height, 3150fe8aea9eSmrg bool bilinear) 3151fe8aea9eSmrg{ 3152fe8aea9eSmrg uint32_t ms1, v, unwind; 3153fe8aea9eSmrg 3154fe8aea9eSmrg gen2_emit_target(sna, dst_bo, width, height, 3155fe8aea9eSmrg sna_format_for_depth(pixmap->drawable.depth)); 3156fe8aea9eSmrg 3157fe8aea9eSmrg unwind = sna->kgem.nbatch; 3158fe8aea9eSmrg BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 3159fe8aea9eSmrg I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2); 3160fe8aea9eSmrg BATCH(1 << 12); 3161fe8aea9eSmrg BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY); 3162fe8aea9eSmrg BATCH(S8_ENABLE_COLOR_BUFFER_WRITE); 3163fe8aea9eSmrg if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1, 3164fe8aea9eSmrg sna->kgem.batch + unwind + 1, 3165fe8aea9eSmrg 3 * sizeof(uint32_t)) == 0) 3166fe8aea9eSmrg sna->kgem.nbatch = unwind; 3167fe8aea9eSmrg else 3168fe8aea9eSmrg sna->render_state.gen2.ls1 = unwind; 3169fe8aea9eSmrg 3170fe8aea9eSmrg gen2_disable_logic_op(sna); 3171fe8aea9eSmrg 3172fe8aea9eSmrg unwind = sna->kgem.nbatch; 3173fe8aea9eSmrg BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 3174fe8aea9eSmrg LOAD_TEXTURE_BLEND_STAGE(0) | 1); 3175fe8aea9eSmrg BATCH(TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OUTPUT_WRITE_CURRENT | 3176fe8aea9eSmrg TB0C_OP_ARG1 | TB0C_ARG1_SEL_TEXEL0); 3177fe8aea9eSmrg BATCH(TB0A_RESULT_SCALE_1X | TB0A_OUTPUT_WRITE_CURRENT | 3178fe8aea9eSmrg TB0A_OP_ARG1 | TB0A_ARG1_SEL_ONE); 3179fe8aea9eSmrg if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1, 3180fe8aea9eSmrg sna->kgem.batch + unwind + 1, 3181fe8aea9eSmrg 2 * sizeof(uint32_t)) == 0) 3182fe8aea9eSmrg sna->kgem.nbatch = unwind; 3183fe8aea9eSmrg else 3184fe8aea9eSmrg sna->render_state.gen2.ls2 = unwind; 3185fe8aea9eSmrg 3186fe8aea9eSmrg BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(0) | 4); 3187fe8aea9eSmrg BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch, 3188fe8aea9eSmrg frame->bo, 3189fe8aea9eSmrg I915_GEM_DOMAIN_SAMPLER << 16, 3190fe8aea9eSmrg 0)); 3191fe8aea9eSmrg ms1 = MAPSURF_422 | TM0S1_COLORSPACE_CONVERSION; 3192fe8aea9eSmrg switch (frame->id) { 3193fe8aea9eSmrg case FOURCC_YUY2: 3194fe8aea9eSmrg ms1 |= MT_422_YCRCB_NORMAL; 3195fe8aea9eSmrg break; 3196fe8aea9eSmrg case FOURCC_UYVY: 3197fe8aea9eSmrg ms1 |= MT_422_YCRCB_SWAPY; 3198fe8aea9eSmrg break; 3199fe8aea9eSmrg } 3200fe8aea9eSmrg BATCH(((frame->height - 1) << TM0S1_HEIGHT_SHIFT) | 3201fe8aea9eSmrg ((frame->width - 1) << TM0S1_WIDTH_SHIFT) | 3202fe8aea9eSmrg ms1 | 3203fe8aea9eSmrg gen2_sampler_tiling_bits(frame->bo->tiling)); 3204fe8aea9eSmrg BATCH((frame->pitch[0] / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D); 3205fe8aea9eSmrg if (bilinear) 3206fe8aea9eSmrg BATCH(FILTER_LINEAR << TM0S3_MAG_FILTER_SHIFT | 3207fe8aea9eSmrg FILTER_LINEAR << TM0S3_MIN_FILTER_SHIFT | 3208fe8aea9eSmrg MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT); 3209fe8aea9eSmrg else 3210fe8aea9eSmrg BATCH(FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT | 3211fe8aea9eSmrg FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT | 3212fe8aea9eSmrg MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT); 3213fe8aea9eSmrg BATCH(0); /* default color */ 3214fe8aea9eSmrg 3215fe8aea9eSmrg BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(0) | 3216fe8aea9eSmrg ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | TEXCOORDTYPE_CARTESIAN | 3217fe8aea9eSmrg ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) | 3218fe8aea9eSmrg ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP)); 3219fe8aea9eSmrg 3220fe8aea9eSmrg v = _3DSTATE_VERTEX_FORMAT_2_CMD | TEXCOORDFMT_2D; 3221fe8aea9eSmrg if (sna->render_state.gen2.vft != v) { 3222fe8aea9eSmrg BATCH(v); 3223fe8aea9eSmrg sna->render_state.gen2.vft = v; 3224fe8aea9eSmrg } 3225fe8aea9eSmrg} 3226fe8aea9eSmrg 3227fe8aea9eSmrgstatic void 3228fe8aea9eSmrggen2_video_get_batch(struct sna *sna, struct kgem_bo *bo) 3229fe8aea9eSmrg{ 3230fe8aea9eSmrg kgem_set_mode(&sna->kgem, KGEM_RENDER, bo); 3231fe8aea9eSmrg 3232fe8aea9eSmrg if (!kgem_check_batch(&sna->kgem, 120) || 3233fe8aea9eSmrg !kgem_check_reloc(&sna->kgem, 4) || 3234fe8aea9eSmrg !kgem_check_exec(&sna->kgem, 2)) { 3235fe8aea9eSmrg _kgem_submit(&sna->kgem); 3236fe8aea9eSmrg _kgem_set_mode(&sna->kgem, KGEM_RENDER); 3237fe8aea9eSmrg } 3238fe8aea9eSmrg 3239fe8aea9eSmrg if (sna->render_state.gen2.need_invariant) 3240fe8aea9eSmrg gen2_emit_invariant(sna); 3241fe8aea9eSmrg} 3242fe8aea9eSmrg 3243fe8aea9eSmrgstatic int 3244fe8aea9eSmrggen2_get_inline_rectangles(struct sna *sna, int want, int floats_per_vertex) 3245fe8aea9eSmrg{ 3246fe8aea9eSmrg int size = floats_per_vertex * 3; 3247fe8aea9eSmrg int rem = batch_space(sna) - 1; 3248fe8aea9eSmrg 3249fe8aea9eSmrg if (rem > MAX_INLINE) 3250fe8aea9eSmrg rem = MAX_INLINE; 3251fe8aea9eSmrg 3252fe8aea9eSmrg if (size * want > rem) 3253fe8aea9eSmrg want = rem / size; 3254fe8aea9eSmrg 3255fe8aea9eSmrg return want; 3256fe8aea9eSmrg} 3257fe8aea9eSmrg 3258fe8aea9eSmrgstatic bool 3259fe8aea9eSmrggen2_render_video(struct sna *sna, 3260fe8aea9eSmrg struct sna_video *video, 3261fe8aea9eSmrg struct sna_video_frame *frame, 3262fe8aea9eSmrg RegionPtr dstRegion, 3263fe8aea9eSmrg PixmapPtr pixmap) 3264fe8aea9eSmrg{ 3265fe8aea9eSmrg struct sna_pixmap *priv = sna_pixmap(pixmap); 3266fe8aea9eSmrg const BoxRec *pbox = region_rects(dstRegion); 3267fe8aea9eSmrg int nbox = region_num_rects(dstRegion); 3268fe8aea9eSmrg int dst_width = dstRegion->extents.x2 - dstRegion->extents.x1; 3269fe8aea9eSmrg int dst_height = dstRegion->extents.y2 - dstRegion->extents.y1; 3270fe8aea9eSmrg int src_width = frame->src.x2 - frame->src.x1; 3271fe8aea9eSmrg int src_height = frame->src.y2 - frame->src.y1; 3272fe8aea9eSmrg float src_offset_x, src_offset_y; 3273fe8aea9eSmrg float src_scale_x, src_scale_y; 3274fe8aea9eSmrg int pix_xoff, pix_yoff; 3275fe8aea9eSmrg struct kgem_bo *dst_bo; 3276fe8aea9eSmrg bool bilinear; 3277fe8aea9eSmrg int copy = 0; 3278fe8aea9eSmrg 3279fe8aea9eSmrg DBG(("%s: src:%dx%d (frame:%dx%d) -> dst:%dx%d\n", __FUNCTION__, 3280fe8aea9eSmrg src_width, src_height, frame->width, frame->height, dst_width, dst_height)); 3281fe8aea9eSmrg 3282fe8aea9eSmrg assert(priv->gpu_bo); 3283fe8aea9eSmrg dst_bo = priv->gpu_bo; 3284fe8aea9eSmrg 3285fe8aea9eSmrg bilinear = src_width != dst_width || src_height != dst_height; 3286fe8aea9eSmrg 3287fe8aea9eSmrg src_scale_x = (float)src_width / dst_width / frame->width; 3288fe8aea9eSmrg src_offset_x = (float)frame->src.x1 / frame->width - dstRegion->extents.x1 * src_scale_x; 3289fe8aea9eSmrg 3290fe8aea9eSmrg src_scale_y = (float)src_height / dst_height / frame->height; 3291fe8aea9eSmrg src_offset_y = (float)frame->src.y1 / frame->height - dstRegion->extents.y1 * src_scale_y; 3292fe8aea9eSmrg DBG(("%s: src offset (%f, %f), scale (%f, %f)\n", 3293fe8aea9eSmrg __FUNCTION__, src_offset_x, src_offset_y, src_scale_x, src_scale_y)); 3294fe8aea9eSmrg 3295fe8aea9eSmrg if (too_large(pixmap->drawable.width, pixmap->drawable.height) || 3296fe8aea9eSmrg dst_bo->pitch > MAX_3D_PITCH) { 3297fe8aea9eSmrg int bpp = pixmap->drawable.bitsPerPixel; 3298fe8aea9eSmrg 3299fe8aea9eSmrg if (too_large(dst_width, dst_height)) 3300fe8aea9eSmrg return false; 3301fe8aea9eSmrg 3302fe8aea9eSmrg dst_bo = kgem_create_2d(&sna->kgem, 3303fe8aea9eSmrg dst_width, dst_height, bpp, 3304fe8aea9eSmrg kgem_choose_tiling(&sna->kgem, 3305fe8aea9eSmrg I915_TILING_X, 3306fe8aea9eSmrg dst_width, dst_height, bpp), 3307fe8aea9eSmrg 0); 3308fe8aea9eSmrg if (!dst_bo) 3309fe8aea9eSmrg return false; 3310fe8aea9eSmrg 3311fe8aea9eSmrg pix_xoff = -dstRegion->extents.x1; 3312fe8aea9eSmrg pix_yoff = -dstRegion->extents.y1; 3313fe8aea9eSmrg copy = 1; 3314fe8aea9eSmrg } else { 3315fe8aea9eSmrg /* Set up the offset for translating from the given region 3316fe8aea9eSmrg * (in screen coordinates) to the backing pixmap. 3317fe8aea9eSmrg */ 3318fe8aea9eSmrg#ifdef COMPOSITE 3319fe8aea9eSmrg pix_xoff = -pixmap->screen_x + pixmap->drawable.x; 3320fe8aea9eSmrg pix_yoff = -pixmap->screen_y + pixmap->drawable.y; 3321fe8aea9eSmrg#else 3322fe8aea9eSmrg pix_xoff = 0; 3323fe8aea9eSmrg pix_yoff = 0; 3324fe8aea9eSmrg#endif 3325fe8aea9eSmrg 3326fe8aea9eSmrg dst_width = pixmap->drawable.width; 3327fe8aea9eSmrg dst_height = pixmap->drawable.height; 3328fe8aea9eSmrg } 3329fe8aea9eSmrg 3330fe8aea9eSmrg gen2_video_get_batch(sna, dst_bo); 3331fe8aea9eSmrg gen2_emit_video_state(sna, video, frame, pixmap, 3332fe8aea9eSmrg dst_bo, dst_width, dst_height, bilinear); 3333fe8aea9eSmrg do { 3334fe8aea9eSmrg int nbox_this_time = gen2_get_inline_rectangles(sna, nbox, 4); 3335fe8aea9eSmrg if (nbox_this_time == 0) { 3336fe8aea9eSmrg gen2_video_get_batch(sna, dst_bo); 3337fe8aea9eSmrg gen2_emit_video_state(sna, video, frame, pixmap, 3338fe8aea9eSmrg dst_bo, dst_width, dst_height, bilinear); 3339fe8aea9eSmrg nbox_this_time = gen2_get_inline_rectangles(sna, nbox, 4); 3340fe8aea9eSmrg assert(nbox_this_time); 3341fe8aea9eSmrg } 3342fe8aea9eSmrg nbox -= nbox_this_time; 3343fe8aea9eSmrg 3344fe8aea9eSmrg BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST | 3345fe8aea9eSmrg ((12 * nbox_this_time) - 1)); 3346fe8aea9eSmrg do { 3347fe8aea9eSmrg int box_x1 = pbox->x1; 3348fe8aea9eSmrg int box_y1 = pbox->y1; 3349fe8aea9eSmrg int box_x2 = pbox->x2; 3350fe8aea9eSmrg int box_y2 = pbox->y2; 3351fe8aea9eSmrg 3352fe8aea9eSmrg pbox++; 3353fe8aea9eSmrg 3354fe8aea9eSmrg DBG(("%s: dst (%d, %d), (%d, %d) + (%d, %d); src (%f, %f), (%f, %f)\n", 3355fe8aea9eSmrg __FUNCTION__, box_x1, box_y1, box_x2, box_y2, pix_xoff, pix_yoff, 3356fe8aea9eSmrg box_x1 * src_scale_x + src_offset_x, 3357fe8aea9eSmrg box_y1 * src_scale_y + src_offset_y, 3358fe8aea9eSmrg box_x2 * src_scale_x + src_offset_x, 3359fe8aea9eSmrg box_y2 * src_scale_y + src_offset_y)); 3360fe8aea9eSmrg 3361fe8aea9eSmrg /* bottom right */ 3362fe8aea9eSmrg BATCH_F(box_x2 + pix_xoff); 3363fe8aea9eSmrg BATCH_F(box_y2 + pix_yoff); 3364fe8aea9eSmrg BATCH_F(box_x2 * src_scale_x + src_offset_x); 3365fe8aea9eSmrg BATCH_F(box_y2 * src_scale_y + src_offset_y); 3366fe8aea9eSmrg 3367fe8aea9eSmrg /* bottom left */ 3368fe8aea9eSmrg BATCH_F(box_x1 + pix_xoff); 3369fe8aea9eSmrg BATCH_F(box_y2 + pix_yoff); 3370fe8aea9eSmrg BATCH_F(box_x1 * src_scale_x + src_offset_x); 3371fe8aea9eSmrg BATCH_F(box_y2 * src_scale_y + src_offset_y); 3372fe8aea9eSmrg 3373fe8aea9eSmrg /* top left */ 3374fe8aea9eSmrg BATCH_F(box_x1 + pix_xoff); 3375fe8aea9eSmrg BATCH_F(box_y1 + pix_yoff); 3376fe8aea9eSmrg BATCH_F(box_x1 * src_scale_x + src_offset_x); 3377fe8aea9eSmrg BATCH_F(box_y1 * src_scale_y + src_offset_y); 3378fe8aea9eSmrg } while (--nbox_this_time); 3379fe8aea9eSmrg } while (nbox); 3380fe8aea9eSmrg 3381fe8aea9eSmrg if (copy) { 3382fe8aea9eSmrg#ifdef COMPOSITE 3383fe8aea9eSmrg pix_xoff = -pixmap->screen_x + pixmap->drawable.x; 3384fe8aea9eSmrg pix_yoff = -pixmap->screen_y + pixmap->drawable.y; 3385fe8aea9eSmrg#else 3386fe8aea9eSmrg pix_xoff = 0; 3387fe8aea9eSmrg pix_yoff = 0; 3388fe8aea9eSmrg#endif 3389fe8aea9eSmrg sna_blt_copy_boxes(sna, GXcopy, 3390fe8aea9eSmrg dst_bo, -dstRegion->extents.x1, -dstRegion->extents.y1, 3391fe8aea9eSmrg priv->gpu_bo, pix_xoff, pix_yoff, 3392fe8aea9eSmrg pixmap->drawable.bitsPerPixel, 3393fe8aea9eSmrg region_rects(dstRegion), 3394fe8aea9eSmrg region_num_rects(dstRegion)); 3395fe8aea9eSmrg 3396fe8aea9eSmrg kgem_bo_destroy(&sna->kgem, dst_bo); 3397fe8aea9eSmrg } 3398fe8aea9eSmrg 3399fe8aea9eSmrg if (!DAMAGE_IS_ALL(priv->gpu_damage)) { 3400fe8aea9eSmrg if ((pix_xoff | pix_yoff) == 0) { 3401fe8aea9eSmrg sna_damage_add(&priv->gpu_damage, dstRegion); 3402fe8aea9eSmrg } else { 3403fe8aea9eSmrg sna_damage_add_boxes(&priv->gpu_damage, 3404fe8aea9eSmrg region_rects(dstRegion), 3405fe8aea9eSmrg region_num_rects(dstRegion), 3406fe8aea9eSmrg pix_xoff, pix_yoff); 3407fe8aea9eSmrg } 3408fe8aea9eSmrg } 3409fe8aea9eSmrg 3410fe8aea9eSmrg return true; 3411fe8aea9eSmrg} 3412fe8aea9eSmrg 341303b705cfSriastradhstatic void 341403b705cfSriastradhgen2_render_copy_setup_source(struct sna_composite_channel *channel, 341542542f5fSchristos const DrawableRec *draw, 341603b705cfSriastradh struct kgem_bo *bo) 341703b705cfSriastradh{ 341842542f5fSchristos assert(draw->width && draw->height); 341903b705cfSriastradh 342003b705cfSriastradh channel->filter = PictFilterNearest; 342103b705cfSriastradh channel->repeat = RepeatNone; 342242542f5fSchristos channel->width = draw->width; 342342542f5fSchristos channel->height = draw->height; 342442542f5fSchristos channel->scale[0] = 1.f/draw->width; 342542542f5fSchristos channel->scale[1] = 1.f/draw->height; 342603b705cfSriastradh channel->offset[0] = 0; 342703b705cfSriastradh channel->offset[1] = 0; 342842542f5fSchristos channel->pict_format = sna_format_for_depth(draw->depth); 342903b705cfSriastradh channel->bo = bo; 343003b705cfSriastradh channel->is_affine = 1; 343103b705cfSriastradh 343203b705cfSriastradh DBG(("%s: source=%d, (%dx%d), format=%08x\n", 343303b705cfSriastradh __FUNCTION__, bo->handle, 343403b705cfSriastradh channel->width, channel->height, 343503b705cfSriastradh channel->pict_format)); 343603b705cfSriastradh} 343703b705cfSriastradh 343803b705cfSriastradhstatic void 343903b705cfSriastradhgen2_emit_copy_pipeline(struct sna *sna, const struct sna_composite_op *op) 344003b705cfSriastradh{ 344103b705cfSriastradh uint32_t blend, unwind; 344203b705cfSriastradh 344303b705cfSriastradh unwind = sna->kgem.nbatch; 344403b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 344503b705cfSriastradh LOAD_TEXTURE_BLEND_STAGE(0) | 1); 344603b705cfSriastradh 344703b705cfSriastradh blend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_ARG1 | 344803b705cfSriastradh TB0C_OUTPUT_WRITE_CURRENT; 344903b705cfSriastradh if (op->dst.format == PICT_a8) 345003b705cfSriastradh blend |= TB0C_ARG1_REPLICATE_ALPHA | TB0C_ARG1_SEL_TEXEL0; 345103b705cfSriastradh else if (PICT_FORMAT_RGB(op->src.pict_format) != 0) 345203b705cfSriastradh blend |= TB0C_ARG1_SEL_TEXEL0; 345303b705cfSriastradh else 345403b705cfSriastradh blend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT; /* 0.0 */ 345503b705cfSriastradh BATCH(blend); 345603b705cfSriastradh 345703b705cfSriastradh blend = TB0A_RESULT_SCALE_1X | TB0A_OP_ARG1 | 345803b705cfSriastradh TB0A_OUTPUT_WRITE_CURRENT; 345903b705cfSriastradh if (PICT_FORMAT_A(op->src.pict_format) == 0) 346003b705cfSriastradh blend |= TB0A_ARG1_SEL_ONE; 346103b705cfSriastradh else 346203b705cfSriastradh blend |= TB0A_ARG1_SEL_TEXEL0; 346303b705cfSriastradh BATCH(blend); 346403b705cfSriastradh 346503b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1, 346603b705cfSriastradh sna->kgem.batch + unwind + 1, 346703b705cfSriastradh 2 * sizeof(uint32_t)) == 0) 346803b705cfSriastradh sna->kgem.nbatch = unwind; 346903b705cfSriastradh else 347003b705cfSriastradh sna->render_state.gen2.ls2 = unwind; 347103b705cfSriastradh} 347203b705cfSriastradh 347303b705cfSriastradhstatic void gen2_emit_copy_state(struct sna *sna, const struct sna_composite_op *op) 347403b705cfSriastradh{ 347503b705cfSriastradh uint32_t ls1, v; 347603b705cfSriastradh 347703b705cfSriastradh gen2_get_batch(sna, op); 347803b705cfSriastradh 347903b705cfSriastradh if (kgem_bo_is_dirty(op->src.bo)) { 348003b705cfSriastradh if (op->src.bo == op->dst.bo) 348103b705cfSriastradh BATCH(MI_FLUSH | MI_INVALIDATE_MAP_CACHE); 348203b705cfSriastradh else 348303b705cfSriastradh BATCH(_3DSTATE_MODES_5_CMD | 348403b705cfSriastradh PIPELINE_FLUSH_RENDER_CACHE | 348503b705cfSriastradh PIPELINE_FLUSH_TEXTURE_CACHE); 348603b705cfSriastradh kgem_clear_dirty(&sna->kgem); 348703b705cfSriastradh } 3488fe8aea9eSmrg gen2_emit_target(sna, 3489fe8aea9eSmrg op->dst.bo, 3490fe8aea9eSmrg op->dst.width, 3491fe8aea9eSmrg op->dst.height, 3492fe8aea9eSmrg op->dst.format); 349303b705cfSriastradh 349403b705cfSriastradh ls1 = sna->kgem.nbatch; 349503b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 349603b705cfSriastradh I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2); 349703b705cfSriastradh BATCH(1<<12); 349803b705cfSriastradh BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY); 349903b705cfSriastradh BATCH(S8_ENABLE_COLOR_BUFFER_WRITE); 350003b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1, 350103b705cfSriastradh sna->kgem.batch + ls1 + 1, 350203b705cfSriastradh 3 * sizeof(uint32_t)) == 0) 350303b705cfSriastradh sna->kgem.nbatch = ls1; 350403b705cfSriastradh else 350503b705cfSriastradh sna->render_state.gen2.ls1 = ls1; 350603b705cfSriastradh 350703b705cfSriastradh gen2_enable_logic_op(sna, op->op); 350803b705cfSriastradh gen2_emit_copy_pipeline(sna, op); 350903b705cfSriastradh 351003b705cfSriastradh v = _3DSTATE_VERTEX_FORMAT_2_CMD | TEXCOORDFMT_2D; 351103b705cfSriastradh if (sna->render_state.gen2.vft != v) { 351203b705cfSriastradh BATCH(v); 351303b705cfSriastradh sna->render_state.gen2.vft = v; 351403b705cfSriastradh } 351503b705cfSriastradh 351603b705cfSriastradh gen2_emit_texture(sna, &op->src, 0); 351703b705cfSriastradh} 351803b705cfSriastradh 351903b705cfSriastradhstatic bool 352003b705cfSriastradhgen2_render_copy_boxes(struct sna *sna, uint8_t alu, 352142542f5fSchristos const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, 352242542f5fSchristos const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, 352303b705cfSriastradh const BoxRec *box, int n, unsigned flags) 352403b705cfSriastradh{ 352503b705cfSriastradh struct sna_composite_op tmp; 352603b705cfSriastradh 352703b705cfSriastradh#if NO_COPY_BOXES 352803b705cfSriastradh if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) 352903b705cfSriastradh return false; 353003b705cfSriastradh 353103b705cfSriastradh return sna_blt_copy_boxes(sna, alu, 353203b705cfSriastradh src_bo, src_dx, src_dy, 353303b705cfSriastradh dst_bo, dst_dx, dst_dy, 353403b705cfSriastradh dst->drawable.bitsPerPixel, 353503b705cfSriastradh box, n); 353603b705cfSriastradh#endif 353703b705cfSriastradh 353803b705cfSriastradh DBG(("%s (%d, %d)->(%d, %d) x %d\n", 353903b705cfSriastradh __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n)); 354003b705cfSriastradh 354142542f5fSchristos if (sna_blt_compare_depth(src, dst) && 354203b705cfSriastradh sna_blt_copy_boxes(sna, alu, 354303b705cfSriastradh src_bo, src_dx, src_dy, 354403b705cfSriastradh dst_bo, dst_dx, dst_dy, 354542542f5fSchristos dst->bitsPerPixel, 354603b705cfSriastradh box, n)) 354703b705cfSriastradh return true; 354803b705cfSriastradh 354903b705cfSriastradh if (src_bo == dst_bo || /* XXX handle overlap using 3D ? */ 355042542f5fSchristos too_large(src->width, src->height) || 355103b705cfSriastradh src_bo->pitch > MAX_3D_PITCH || dst_bo->pitch < 8) { 355203b705cfSriastradhfallback: 355303b705cfSriastradh return sna_blt_copy_boxes_fallback(sna, alu, 355403b705cfSriastradh src, src_bo, src_dx, src_dy, 355503b705cfSriastradh dst, dst_bo, dst_dx, dst_dy, 355603b705cfSriastradh box, n); 355703b705cfSriastradh } 355803b705cfSriastradh 355903b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) { 356003b705cfSriastradh kgem_submit(&sna->kgem); 356103b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) 356203b705cfSriastradh goto fallback; 356303b705cfSriastradh } 356403b705cfSriastradh 356503b705cfSriastradh assert(dst_bo->pitch >= 8); 356603b705cfSriastradh 356703b705cfSriastradh memset(&tmp, 0, sizeof(tmp)); 356803b705cfSriastradh tmp.op = alu; 356903b705cfSriastradh 357042542f5fSchristos tmp.dst.pixmap = (PixmapPtr)dst; 357142542f5fSchristos tmp.dst.width = dst->width; 357242542f5fSchristos tmp.dst.height = dst->height; 357342542f5fSchristos tmp.dst.format = sna_format_for_depth(dst->depth); 357403b705cfSriastradh tmp.dst.bo = dst_bo; 357503b705cfSriastradh tmp.dst.x = tmp.dst.y = 0; 357603b705cfSriastradh tmp.damage = NULL; 357703b705cfSriastradh 357803b705cfSriastradh DBG(("%s: target=%d, format=%08x, size=%dx%d\n", 357903b705cfSriastradh __FUNCTION__, dst_bo->handle, 358003b705cfSriastradh (unsigned)tmp.dst.format, 358103b705cfSriastradh tmp.dst.width, 358203b705cfSriastradh tmp.dst.height)); 358303b705cfSriastradh 358403b705cfSriastradh sna_render_composite_redirect_init(&tmp); 358503b705cfSriastradh if (too_large(tmp.dst.width, tmp.dst.height) || 358603b705cfSriastradh dst_bo->pitch > MAX_3D_PITCH) { 358703b705cfSriastradh BoxRec extents = box[0]; 358803b705cfSriastradh int i; 358903b705cfSriastradh 359003b705cfSriastradh for (i = 1; i < n; i++) { 359103b705cfSriastradh if (box[i].x1 < extents.x1) 359203b705cfSriastradh extents.x1 = box[i].x1; 359303b705cfSriastradh if (box[i].y1 < extents.y1) 359403b705cfSriastradh extents.y1 = box[i].y1; 359503b705cfSriastradh 359603b705cfSriastradh if (box[i].x2 > extents.x2) 359703b705cfSriastradh extents.x2 = box[i].x2; 359803b705cfSriastradh if (box[i].y2 > extents.y2) 359903b705cfSriastradh extents.y2 = box[i].y2; 360003b705cfSriastradh } 360103b705cfSriastradh if (!sna_render_composite_redirect(sna, &tmp, 360203b705cfSriastradh extents.x1 + dst_dx, 360303b705cfSriastradh extents.y1 + dst_dy, 360403b705cfSriastradh extents.x2 - extents.x1, 360503b705cfSriastradh extents.y2 - extents.y1, 360603b705cfSriastradh alu != GXcopy || n > 1)) 360703b705cfSriastradh goto fallback_tiled; 360803b705cfSriastradh } 360903b705cfSriastradh 361003b705cfSriastradh tmp.floats_per_vertex = 4; 361103b705cfSriastradh tmp.floats_per_rect = 12; 361203b705cfSriastradh 361303b705cfSriastradh dst_dx += tmp.dst.x; 361403b705cfSriastradh dst_dy += tmp.dst.y; 361503b705cfSriastradh tmp.dst.x = tmp.dst.y = 0; 361603b705cfSriastradh 361703b705cfSriastradh gen2_render_copy_setup_source(&tmp.src, src, src_bo); 361803b705cfSriastradh gen2_emit_copy_state(sna, &tmp); 361903b705cfSriastradh do { 362003b705cfSriastradh int n_this_time; 362103b705cfSriastradh 362203b705cfSriastradh n_this_time = gen2_get_rectangles(sna, &tmp, n); 362303b705cfSriastradh if (n_this_time == 0) { 362403b705cfSriastradh gen2_emit_copy_state(sna, &tmp); 362503b705cfSriastradh n_this_time = gen2_get_rectangles(sna, &tmp, n); 362603b705cfSriastradh } 362703b705cfSriastradh n -= n_this_time; 362803b705cfSriastradh 362903b705cfSriastradh do { 363003b705cfSriastradh DBG((" (%d, %d) -> (%d, %d) + (%d, %d)\n", 363103b705cfSriastradh box->x1 + src_dx, box->y1 + src_dy, 363203b705cfSriastradh box->x1 + dst_dx, box->y1 + dst_dy, 363303b705cfSriastradh box->x2 - box->x1, box->y2 - box->y1)); 363403b705cfSriastradh VERTEX(box->x2 + dst_dx); 363503b705cfSriastradh VERTEX(box->y2 + dst_dy); 363603b705cfSriastradh VERTEX((box->x2 + src_dx) * tmp.src.scale[0]); 363703b705cfSriastradh VERTEX((box->y2 + src_dy) * tmp.src.scale[1]); 363803b705cfSriastradh 363903b705cfSriastradh VERTEX(box->x1 + dst_dx); 364003b705cfSriastradh VERTEX(box->y2 + dst_dy); 364103b705cfSriastradh VERTEX((box->x1 + src_dx) * tmp.src.scale[0]); 364203b705cfSriastradh VERTEX((box->y2 + src_dy) * tmp.src.scale[1]); 364303b705cfSriastradh 364403b705cfSriastradh VERTEX(box->x1 + dst_dx); 364503b705cfSriastradh VERTEX(box->y1 + dst_dy); 364603b705cfSriastradh VERTEX((box->x1 + src_dx) * tmp.src.scale[0]); 364703b705cfSriastradh VERTEX((box->y1 + src_dy) * tmp.src.scale[1]); 364803b705cfSriastradh 364903b705cfSriastradh box++; 365003b705cfSriastradh } while (--n_this_time); 365103b705cfSriastradh } while (n); 365203b705cfSriastradh 365303b705cfSriastradh gen2_vertex_flush(sna, &tmp); 365403b705cfSriastradh sna_render_composite_redirect_done(sna, &tmp); 365503b705cfSriastradh return true; 365603b705cfSriastradh 365703b705cfSriastradhfallback_tiled: 365803b705cfSriastradh return sna_tiling_copy_boxes(sna, alu, 365903b705cfSriastradh src, src_bo, src_dx, src_dy, 366003b705cfSriastradh dst, dst_bo, dst_dx, dst_dy, 366103b705cfSriastradh box, n); 366203b705cfSriastradh} 366303b705cfSriastradh 366403b705cfSriastradhstatic void 366503b705cfSriastradhgen2_render_copy_blt(struct sna *sna, 366603b705cfSriastradh const struct sna_copy_op *op, 366703b705cfSriastradh int16_t sx, int16_t sy, 366803b705cfSriastradh int16_t w, int16_t h, 366903b705cfSriastradh int16_t dx, int16_t dy) 367003b705cfSriastradh{ 367103b705cfSriastradh if (!gen2_get_rectangles(sna, &op->base, 1)) { 367203b705cfSriastradh gen2_emit_copy_state(sna, &op->base); 367303b705cfSriastradh gen2_get_rectangles(sna, &op->base, 1); 367403b705cfSriastradh } 367503b705cfSriastradh 367603b705cfSriastradh VERTEX(dx+w); 367703b705cfSriastradh VERTEX(dy+h); 367803b705cfSriastradh VERTEX((sx+w)*op->base.src.scale[0]); 367903b705cfSriastradh VERTEX((sy+h)*op->base.src.scale[1]); 368003b705cfSriastradh 368103b705cfSriastradh VERTEX(dx); 368203b705cfSriastradh VERTEX(dy+h); 368303b705cfSriastradh VERTEX(sx*op->base.src.scale[0]); 368403b705cfSriastradh VERTEX((sy+h)*op->base.src.scale[1]); 368503b705cfSriastradh 368603b705cfSriastradh VERTEX(dx); 368703b705cfSriastradh VERTEX(dy); 368803b705cfSriastradh VERTEX(sx*op->base.src.scale[0]); 368903b705cfSriastradh VERTEX(sy*op->base.src.scale[1]); 369003b705cfSriastradh} 369103b705cfSriastradh 369203b705cfSriastradhstatic void 369303b705cfSriastradhgen2_render_copy_done(struct sna *sna, const struct sna_copy_op *op) 369403b705cfSriastradh{ 369503b705cfSriastradh gen2_vertex_flush(sna, &op->base); 369603b705cfSriastradh} 369703b705cfSriastradh 369803b705cfSriastradhstatic bool 369903b705cfSriastradhgen2_render_copy(struct sna *sna, uint8_t alu, 370003b705cfSriastradh PixmapPtr src, struct kgem_bo *src_bo, 370103b705cfSriastradh PixmapPtr dst, struct kgem_bo *dst_bo, 370203b705cfSriastradh struct sna_copy_op *tmp) 370303b705cfSriastradh{ 370403b705cfSriastradh#if NO_COPY 370503b705cfSriastradh if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) 370603b705cfSriastradh return false; 370703b705cfSriastradh 370803b705cfSriastradh return sna_blt_copy(sna, alu, 370903b705cfSriastradh src_bo, dst_bo, 371003b705cfSriastradh dst->drawable.bitsPerPixel, 371103b705cfSriastradh tmp); 371203b705cfSriastradh#endif 371303b705cfSriastradh 371403b705cfSriastradh /* Prefer to use the BLT */ 371503b705cfSriastradh if (sna_blt_compare_depth(&src->drawable, &dst->drawable) && 371603b705cfSriastradh sna_blt_copy(sna, alu, 371703b705cfSriastradh src_bo, dst_bo, 371803b705cfSriastradh dst->drawable.bitsPerPixel, 371903b705cfSriastradh tmp)) 372003b705cfSriastradh return true; 372103b705cfSriastradh 372203b705cfSriastradh /* Must use the BLT if we can't RENDER... */ 372303b705cfSriastradh if (too_large(src->drawable.width, src->drawable.height) || 372403b705cfSriastradh too_large(dst->drawable.width, dst->drawable.height) || 372503b705cfSriastradh src_bo->pitch > MAX_3D_PITCH || 372603b705cfSriastradh dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH) { 372703b705cfSriastradhfallback: 372803b705cfSriastradh if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) 372903b705cfSriastradh return false; 373003b705cfSriastradh 373103b705cfSriastradh return sna_blt_copy(sna, alu, src_bo, dst_bo, 373203b705cfSriastradh dst->drawable.bitsPerPixel, 373303b705cfSriastradh tmp); 373403b705cfSriastradh } 373503b705cfSriastradh 373603b705cfSriastradh tmp->base.op = alu; 373703b705cfSriastradh 373803b705cfSriastradh tmp->base.dst.pixmap = dst; 373903b705cfSriastradh tmp->base.dst.width = dst->drawable.width; 374003b705cfSriastradh tmp->base.dst.height = dst->drawable.height; 374103b705cfSriastradh tmp->base.dst.format = sna_format_for_depth(dst->drawable.depth); 374203b705cfSriastradh tmp->base.dst.bo = dst_bo; 374303b705cfSriastradh 374442542f5fSchristos gen2_render_copy_setup_source(&tmp->base.src, &src->drawable, src_bo); 374503b705cfSriastradh tmp->base.mask.bo = NULL; 374603b705cfSriastradh 374703b705cfSriastradh tmp->base.floats_per_vertex = 4; 374803b705cfSriastradh tmp->base.floats_per_rect = 12; 374903b705cfSriastradh 375003b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) { 375103b705cfSriastradh kgem_submit(&sna->kgem); 375203b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) 375303b705cfSriastradh goto fallback; 375403b705cfSriastradh } 375503b705cfSriastradh 375603b705cfSriastradh tmp->blt = gen2_render_copy_blt; 375703b705cfSriastradh tmp->done = gen2_render_copy_done; 375803b705cfSriastradh 375903b705cfSriastradh gen2_emit_composite_state(sna, &tmp->base); 376003b705cfSriastradh return true; 376103b705cfSriastradh} 376203b705cfSriastradh 376303b705cfSriastradhstatic void 376403b705cfSriastradhgen2_render_reset(struct sna *sna) 376503b705cfSriastradh{ 376603b705cfSriastradh sna->render_state.gen2.need_invariant = true; 376703b705cfSriastradh sna->render_state.gen2.logic_op_enabled = 0; 376803b705cfSriastradh sna->render_state.gen2.target = 0; 376903b705cfSriastradh 377003b705cfSriastradh sna->render_state.gen2.ls1 = 0; 377103b705cfSriastradh sna->render_state.gen2.ls2 = 0; 377203b705cfSriastradh sna->render_state.gen2.vft = 0; 377303b705cfSriastradh 377403b705cfSriastradh sna->render_state.gen2.diffuse = 0x0c0ffee0; 377503b705cfSriastradh sna->render_state.gen2.specular = 0x0c0ffee0; 377603b705cfSriastradh} 377703b705cfSriastradh 377803b705cfSriastradhstatic void 377903b705cfSriastradhgen2_render_flush(struct sna *sna) 378003b705cfSriastradh{ 378103b705cfSriastradh assert(sna->render.vertex_index == 0); 378203b705cfSriastradh assert(sna->render.vertex_offset == 0); 378303b705cfSriastradh} 378403b705cfSriastradh 378503b705cfSriastradhstatic void 378603b705cfSriastradhgen2_render_context_switch(struct kgem *kgem, 378703b705cfSriastradh int new_mode) 378803b705cfSriastradh{ 378903b705cfSriastradh struct sna *sna = container_of(kgem, struct sna, kgem); 379003b705cfSriastradh 379103b705cfSriastradh if (!kgem->nbatch) 379203b705cfSriastradh return; 379303b705cfSriastradh 379403b705cfSriastradh /* Reload BLT registers following a lost context */ 379503b705cfSriastradh sna->blt_state.fill_bo = 0; 379603b705cfSriastradh 379703b705cfSriastradh if (kgem_ring_is_idle(kgem, kgem->ring)) { 379803b705cfSriastradh DBG(("%s: GPU idle, flushing\n", __FUNCTION__)); 379903b705cfSriastradh _kgem_submit(kgem); 380003b705cfSriastradh } 380103b705cfSriastradh} 380203b705cfSriastradh 380303b705cfSriastradhconst char *gen2_render_init(struct sna *sna, const char *backend) 380403b705cfSriastradh{ 380503b705cfSriastradh struct sna_render *render = &sna->render; 380603b705cfSriastradh 380703b705cfSriastradh sna->kgem.context_switch = gen2_render_context_switch; 380803b705cfSriastradh 380903b705cfSriastradh /* Use the BLT (and overlay) for everything except when forced to 381003b705cfSriastradh * use the texture combiners. 381103b705cfSriastradh */ 381203b705cfSriastradh#if !NO_COMPOSITE 381303b705cfSriastradh render->composite = gen2_render_composite; 381403b705cfSriastradh render->prefer_gpu |= PREFER_GPU_RENDER; 381503b705cfSriastradh#endif 381603b705cfSriastradh#if !NO_COMPOSITE_SPANS 381703b705cfSriastradh render->check_composite_spans = gen2_check_composite_spans; 381803b705cfSriastradh render->composite_spans = gen2_render_composite_spans; 381903b705cfSriastradh render->prefer_gpu |= PREFER_GPU_SPANS; 382003b705cfSriastradh#endif 382103b705cfSriastradh render->fill_boxes = gen2_render_fill_boxes; 382203b705cfSriastradh render->fill = gen2_render_fill; 382303b705cfSriastradh render->fill_one = gen2_render_fill_one; 382403b705cfSriastradh render->copy = gen2_render_copy; 382503b705cfSriastradh render->copy_boxes = gen2_render_copy_boxes; 382603b705cfSriastradh 3827fe8aea9eSmrg render->video = gen2_render_video; 382803b705cfSriastradh 382903b705cfSriastradh render->reset = gen2_render_reset; 383003b705cfSriastradh render->flush = gen2_render_flush; 383103b705cfSriastradh 383203b705cfSriastradh render->max_3d_size = MAX_3D_SIZE; 383303b705cfSriastradh render->max_3d_pitch = MAX_3D_PITCH; 383403b705cfSriastradh return "Almador (gen2)"; 383503b705cfSriastradh} 3836