gen2_render.c revision 42542f5f
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" 3803b705cfSriastradh 3903b705cfSriastradh#include "gen2_render.h" 4003b705cfSriastradh 4103b705cfSriastradh#define NO_COMPOSITE 0 4203b705cfSriastradh#define NO_COMPOSITE_SPANS 0 4303b705cfSriastradh#define NO_COPY 0 4403b705cfSriastradh#define NO_COPY_BOXES 0 4503b705cfSriastradh#define NO_FILL 0 4603b705cfSriastradh#define NO_FILL_ONE 0 4703b705cfSriastradh#define NO_FILL_BOXES 0 4803b705cfSriastradh 4903b705cfSriastradh#define MAX_3D_SIZE 2048 5003b705cfSriastradh#define MAX_3D_PITCH 8192 5103b705cfSriastradh 5203b705cfSriastradh#define BATCH(v) batch_emit(sna, v) 5303b705cfSriastradh#define BATCH_F(v) batch_emit_float(sna, v) 5403b705cfSriastradh#define VERTEX(v) batch_emit_float(sna, v) 5503b705cfSriastradh 5603b705cfSriastradhstatic const struct blendinfo { 5703b705cfSriastradh bool dst_alpha; 5803b705cfSriastradh bool src_alpha; 5903b705cfSriastradh uint32_t src_blend; 6003b705cfSriastradh uint32_t dst_blend; 6103b705cfSriastradh} gen2_blend_op[] = { 6203b705cfSriastradh /* Clear */ 6303b705cfSriastradh {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ZERO}, 6403b705cfSriastradh /* Src */ 6503b705cfSriastradh {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ZERO}, 6603b705cfSriastradh /* Dst */ 6703b705cfSriastradh {0, 0, BLENDFACTOR_ZERO, BLENDFACTOR_ONE}, 6803b705cfSriastradh /* Over */ 6903b705cfSriastradh {0, 1, BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA}, 7003b705cfSriastradh /* OverReverse */ 7103b705cfSriastradh {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ONE}, 7203b705cfSriastradh /* In */ 7303b705cfSriastradh {1, 0, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_ZERO}, 7403b705cfSriastradh /* InReverse */ 7503b705cfSriastradh {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_SRC_ALPHA}, 7603b705cfSriastradh /* Out */ 7703b705cfSriastradh {1, 0, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_ZERO}, 7803b705cfSriastradh /* OutReverse */ 7903b705cfSriastradh {0, 1, BLENDFACTOR_ZERO, BLENDFACTOR_INV_SRC_ALPHA}, 8003b705cfSriastradh /* Atop */ 8103b705cfSriastradh {1, 1, BLENDFACTOR_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA}, 8203b705cfSriastradh /* AtopReverse */ 8303b705cfSriastradh {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_SRC_ALPHA}, 8403b705cfSriastradh /* Xor */ 8503b705cfSriastradh {1, 1, BLENDFACTOR_INV_DST_ALPHA, BLENDFACTOR_INV_SRC_ALPHA}, 8603b705cfSriastradh /* Add */ 8703b705cfSriastradh {0, 0, BLENDFACTOR_ONE, BLENDFACTOR_ONE}, 8803b705cfSriastradh}; 8903b705cfSriastradh 9003b705cfSriastradhstatic const struct formatinfo { 9103b705cfSriastradh unsigned int fmt; 9203b705cfSriastradh uint32_t card_fmt; 9303b705cfSriastradh} i8xx_tex_formats[] = { 9403b705cfSriastradh {PICT_a8, MAPSURF_8BIT | MT_8BIT_A8}, 9503b705cfSriastradh {PICT_a8r8g8b8, MAPSURF_32BIT | MT_32BIT_ARGB8888}, 9603b705cfSriastradh {PICT_a8b8g8r8, MAPSURF_32BIT | MT_32BIT_ABGR8888}, 9703b705cfSriastradh {PICT_r5g6b5, MAPSURF_16BIT | MT_16BIT_RGB565}, 9803b705cfSriastradh {PICT_a1r5g5b5, MAPSURF_16BIT | MT_16BIT_ARGB1555}, 9903b705cfSriastradh {PICT_a4r4g4b4, MAPSURF_16BIT | MT_16BIT_ARGB4444}, 10003b705cfSriastradh}, i85x_tex_formats[] = { 10103b705cfSriastradh {PICT_x8r8g8b8, MAPSURF_32BIT | MT_32BIT_XRGB8888}, 10203b705cfSriastradh {PICT_x8b8g8r8, MAPSURF_32BIT | MT_32BIT_XBGR8888}, 10303b705cfSriastradh}; 10403b705cfSriastradh 10503b705cfSriastradhstatic inline bool 10603b705cfSriastradhtoo_large(int width, int height) 10703b705cfSriastradh{ 10803b705cfSriastradh return width > MAX_3D_SIZE || height > MAX_3D_SIZE; 10903b705cfSriastradh} 11003b705cfSriastradh 11103b705cfSriastradhstatic inline uint32_t 11203b705cfSriastradhgen2_buf_tiling(uint32_t tiling) 11303b705cfSriastradh{ 11403b705cfSriastradh uint32_t v = 0; 11503b705cfSriastradh switch (tiling) { 11603b705cfSriastradh default: assert(0); 11703b705cfSriastradh case I915_TILING_Y: v |= BUF_3D_TILE_WALK_Y; 11803b705cfSriastradh case I915_TILING_X: v |= BUF_3D_TILED_SURFACE; 11903b705cfSriastradh case I915_TILING_NONE: break; 12003b705cfSriastradh } 12103b705cfSriastradh return v; 12203b705cfSriastradh} 12303b705cfSriastradh 12403b705cfSriastradhstatic uint32_t 12503b705cfSriastradhgen2_get_dst_format(uint32_t format) 12603b705cfSriastradh{ 12703b705cfSriastradh#define BIAS DSTORG_HORT_BIAS(0x8) | DSTORG_VERT_BIAS(0x8) 12803b705cfSriastradh switch (format) { 12903b705cfSriastradh default: 13003b705cfSriastradh assert(0); 13103b705cfSriastradh case PICT_a8r8g8b8: 13203b705cfSriastradh case PICT_x8r8g8b8: 13303b705cfSriastradh return COLR_BUF_ARGB8888 | BIAS; 13403b705cfSriastradh case PICT_r5g6b5: 13503b705cfSriastradh return COLR_BUF_RGB565 | BIAS; 13603b705cfSriastradh case PICT_a1r5g5b5: 13703b705cfSriastradh case PICT_x1r5g5b5: 13803b705cfSriastradh return COLR_BUF_ARGB1555 | BIAS; 13903b705cfSriastradh case PICT_a8: 14003b705cfSriastradh return COLR_BUF_8BIT | BIAS; 14103b705cfSriastradh case PICT_a4r4g4b4: 14203b705cfSriastradh case PICT_x4r4g4b4: 14303b705cfSriastradh return COLR_BUF_ARGB4444 | BIAS; 14403b705cfSriastradh } 14503b705cfSriastradh#undef BIAS 14603b705cfSriastradh} 14703b705cfSriastradh 14803b705cfSriastradhstatic bool 14903b705cfSriastradhgen2_check_dst_format(uint32_t format) 15003b705cfSriastradh{ 15103b705cfSriastradh switch (format) { 15203b705cfSriastradh case PICT_a8r8g8b8: 15303b705cfSriastradh case PICT_x8r8g8b8: 15403b705cfSriastradh case PICT_r5g6b5: 15503b705cfSriastradh case PICT_a1r5g5b5: 15603b705cfSriastradh case PICT_x1r5g5b5: 15703b705cfSriastradh case PICT_a8: 15803b705cfSriastradh case PICT_a4r4g4b4: 15903b705cfSriastradh case PICT_x4r4g4b4: 16003b705cfSriastradh return true; 16103b705cfSriastradh default: 16203b705cfSriastradh return false; 16303b705cfSriastradh } 16403b705cfSriastradh} 16503b705cfSriastradh 16603b705cfSriastradhstatic uint32_t 16703b705cfSriastradhgen2_get_card_format(struct sna *sna, uint32_t format) 16803b705cfSriastradh{ 16903b705cfSriastradh unsigned int i; 17003b705cfSriastradh 17103b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i8xx_tex_formats); i++) 17203b705cfSriastradh if (i8xx_tex_formats[i].fmt == format) 17303b705cfSriastradh return i8xx_tex_formats[i].card_fmt; 17403b705cfSriastradh 17503b705cfSriastradh if (sna->kgem.gen < 021) { 17603b705cfSriastradh /* Whilst these are not directly supported on 830/845, 17703b705cfSriastradh * we only enable them when we can implicitly convert 17803b705cfSriastradh * them to a supported variant through the texture 17903b705cfSriastradh * combiners. 18003b705cfSriastradh */ 18103b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i85x_tex_formats); i++) 18203b705cfSriastradh if (i85x_tex_formats[i].fmt == format) 18303b705cfSriastradh return i8xx_tex_formats[1+i].card_fmt; 18403b705cfSriastradh } else { 18503b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i85x_tex_formats); i++) 18603b705cfSriastradh if (i85x_tex_formats[i].fmt == format) 18703b705cfSriastradh return i85x_tex_formats[i].card_fmt; 18803b705cfSriastradh } 18903b705cfSriastradh 19003b705cfSriastradh assert(0); 19103b705cfSriastradh return 0; 19203b705cfSriastradh} 19303b705cfSriastradh 19403b705cfSriastradhstatic uint32_t 19503b705cfSriastradhgen2_check_format(struct sna *sna, PicturePtr p) 19603b705cfSriastradh{ 19703b705cfSriastradh unsigned int i; 19803b705cfSriastradh 19903b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i8xx_tex_formats); i++) 20003b705cfSriastradh if (i8xx_tex_formats[i].fmt == p->format) 20103b705cfSriastradh return true; 20203b705cfSriastradh 20303b705cfSriastradh if (sna->kgem.gen > 021) { 20403b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i85x_tex_formats); i++) 20503b705cfSriastradh if (i85x_tex_formats[i].fmt == p->format) 20603b705cfSriastradh return true; 20703b705cfSriastradh } 20803b705cfSriastradh 20903b705cfSriastradh return false; 21003b705cfSriastradh} 21103b705cfSriastradh 21203b705cfSriastradhstatic uint32_t 21303b705cfSriastradhgen2_sampler_tiling_bits(uint32_t tiling) 21403b705cfSriastradh{ 21503b705cfSriastradh uint32_t bits = 0; 21603b705cfSriastradh switch (tiling) { 21703b705cfSriastradh default: 21803b705cfSriastradh assert(0); 21903b705cfSriastradh case I915_TILING_Y: 22003b705cfSriastradh bits |= TM0S1_TILE_WALK; 22103b705cfSriastradh case I915_TILING_X: 22203b705cfSriastradh bits |= TM0S1_TILED_SURFACE; 22303b705cfSriastradh case I915_TILING_NONE: 22403b705cfSriastradh break; 22503b705cfSriastradh } 22603b705cfSriastradh return bits; 22703b705cfSriastradh} 22803b705cfSriastradh 22903b705cfSriastradhstatic bool 23003b705cfSriastradhgen2_check_filter(PicturePtr picture) 23103b705cfSriastradh{ 23203b705cfSriastradh switch (picture->filter) { 23303b705cfSriastradh case PictFilterNearest: 23403b705cfSriastradh case PictFilterBilinear: 23503b705cfSriastradh return true; 23603b705cfSriastradh default: 23703b705cfSriastradh return false; 23803b705cfSriastradh } 23903b705cfSriastradh} 24003b705cfSriastradh 24103b705cfSriastradhstatic bool 24203b705cfSriastradhgen2_check_repeat(PicturePtr picture) 24303b705cfSriastradh{ 24403b705cfSriastradh if (!picture->repeat) 24503b705cfSriastradh return true; 24603b705cfSriastradh 24703b705cfSriastradh switch (picture->repeatType) { 24803b705cfSriastradh case RepeatNone: 24903b705cfSriastradh case RepeatNormal: 25003b705cfSriastradh case RepeatPad: 25103b705cfSriastradh case RepeatReflect: 25203b705cfSriastradh return true; 25303b705cfSriastradh default: 25403b705cfSriastradh return false; 25503b705cfSriastradh } 25603b705cfSriastradh} 25703b705cfSriastradh 25803b705cfSriastradhstatic void 25903b705cfSriastradhgen2_emit_texture(struct sna *sna, 26003b705cfSriastradh const struct sna_composite_channel *channel, 26103b705cfSriastradh int unit) 26203b705cfSriastradh{ 26303b705cfSriastradh uint32_t wrap_mode_u, wrap_mode_v; 26403b705cfSriastradh uint32_t texcoordtype; 26503b705cfSriastradh uint32_t filter; 26603b705cfSriastradh 26742542f5fSchristos assert(channel->bo); 26842542f5fSchristos 26903b705cfSriastradh if (channel->is_affine) 27003b705cfSriastradh texcoordtype = TEXCOORDTYPE_CARTESIAN; 27103b705cfSriastradh else 27203b705cfSriastradh texcoordtype = TEXCOORDTYPE_HOMOGENEOUS; 27303b705cfSriastradh 27403b705cfSriastradh switch (channel->repeat) { 27503b705cfSriastradh default: 27603b705cfSriastradh assert(0); 27703b705cfSriastradh case RepeatNone: 27803b705cfSriastradh wrap_mode_u = TEXCOORDMODE_CLAMP_BORDER; 27903b705cfSriastradh break; 28003b705cfSriastradh case RepeatNormal: 28103b705cfSriastradh wrap_mode_u = TEXCOORDMODE_WRAP; 28203b705cfSriastradh break; 28303b705cfSriastradh case RepeatPad: 28403b705cfSriastradh wrap_mode_u = TEXCOORDMODE_CLAMP; 28503b705cfSriastradh break; 28603b705cfSriastradh case RepeatReflect: 28703b705cfSriastradh wrap_mode_u = TEXCOORDMODE_MIRROR; 28803b705cfSriastradh break; 28903b705cfSriastradh } 29003b705cfSriastradh if (channel->is_linear) 29103b705cfSriastradh wrap_mode_v = TEXCOORDMODE_WRAP; 29203b705cfSriastradh else 29303b705cfSriastradh wrap_mode_v = wrap_mode_u; 29403b705cfSriastradh 29503b705cfSriastradh switch (channel->filter) { 29603b705cfSriastradh default: 29703b705cfSriastradh assert(0); 29803b705cfSriastradh case PictFilterNearest: 29903b705cfSriastradh filter = (FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT | 30003b705cfSriastradh FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT | 30103b705cfSriastradh MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT); 30203b705cfSriastradh break; 30303b705cfSriastradh case PictFilterBilinear: 30403b705cfSriastradh filter = (FILTER_LINEAR << TM0S3_MAG_FILTER_SHIFT | 30503b705cfSriastradh FILTER_LINEAR << TM0S3_MIN_FILTER_SHIFT | 30603b705cfSriastradh MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT); 30703b705cfSriastradh break; 30803b705cfSriastradh } 30903b705cfSriastradh 31003b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4); 31103b705cfSriastradh BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch, 31203b705cfSriastradh channel->bo, 31303b705cfSriastradh I915_GEM_DOMAIN_SAMPLER << 16, 31403b705cfSriastradh 0)); 31503b705cfSriastradh BATCH(((channel->height - 1) << TM0S1_HEIGHT_SHIFT) | 31603b705cfSriastradh ((channel->width - 1) << TM0S1_WIDTH_SHIFT) | 31703b705cfSriastradh gen2_get_card_format(sna, channel->pict_format) | 31803b705cfSriastradh gen2_sampler_tiling_bits(channel->bo->tiling)); 31903b705cfSriastradh BATCH((channel->bo->pitch / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D); 32003b705cfSriastradh BATCH(filter); 32103b705cfSriastradh BATCH(0); /* default color */ 32203b705cfSriastradh 32303b705cfSriastradh BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) | 32403b705cfSriastradh ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL | texcoordtype | 32503b705cfSriastradh ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(wrap_mode_v) | 32603b705cfSriastradh ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode_u)); 32703b705cfSriastradh} 32803b705cfSriastradh 32903b705cfSriastradhstatic void 33003b705cfSriastradhgen2_get_blend_factors(const struct sna_composite_op *op, 33103b705cfSriastradh int blend, 33203b705cfSriastradh uint32_t *c_out, 33303b705cfSriastradh uint32_t *a_out) 33403b705cfSriastradh{ 33503b705cfSriastradh uint32_t cblend, ablend; 33603b705cfSriastradh 33703b705cfSriastradh /* If component alpha is active in the mask and the blend operation 33803b705cfSriastradh * uses the source alpha, then we know we don't need the source 33903b705cfSriastradh * value (otherwise we would have hit a fallback earlier), so we 34003b705cfSriastradh * provide the source alpha (src.A * mask.X) as output color. 34103b705cfSriastradh * Conversely, if CA is set and we don't need the source alpha, then 34203b705cfSriastradh * we produce the source value (src.X * mask.X) and the source alpha 34303b705cfSriastradh * is unused.. Otherwise, we provide the non-CA source value 34403b705cfSriastradh * (src.X * mask.A). 34503b705cfSriastradh * 34603b705cfSriastradh * The PICT_FORMAT_RGB(pict) == 0 fixups are not needed on 855+'s a8 34703b705cfSriastradh * pictures, but we need to implement it for 830/845 and there's no 34803b705cfSriastradh * harm done in leaving it in. 34903b705cfSriastradh */ 35003b705cfSriastradh cblend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OUTPUT_WRITE_CURRENT; 35103b705cfSriastradh ablend = TB0A_RESULT_SCALE_1X | TB0A_OUTPUT_WRITE_CURRENT; 35203b705cfSriastradh 35303b705cfSriastradh /* Get the source picture's channels into TBx_ARG1 */ 35403b705cfSriastradh if ((op->has_component_alpha && gen2_blend_op[blend].src_alpha) || 35503b705cfSriastradh op->dst.format == PICT_a8) { 35603b705cfSriastradh /* Producing source alpha value, so the first set of channels 35703b705cfSriastradh * is src.A instead of src.X. We also do this if the destination 35803b705cfSriastradh * is a8, in which case src.G is what's written, and the other 35903b705cfSriastradh * channels are ignored. 36003b705cfSriastradh */ 36142542f5fSchristos if (op->src.is_opaque) { 36242542f5fSchristos ablend |= TB0C_ARG1_SEL_ONE; 36342542f5fSchristos cblend |= TB0C_ARG1_SEL_ONE; 36442542f5fSchristos } else if (op->src.is_solid) { 36542542f5fSchristos ablend |= TB0C_ARG1_SEL_DIFFUSE; 36603b705cfSriastradh cblend |= TB0C_ARG1_SEL_DIFFUSE | TB0C_ARG1_REPLICATE_ALPHA; 36703b705cfSriastradh } else { 36842542f5fSchristos ablend |= TB0C_ARG1_SEL_TEXEL0; 36903b705cfSriastradh cblend |= TB0C_ARG1_SEL_TEXEL0 | TB0C_ARG1_REPLICATE_ALPHA; 37003b705cfSriastradh } 37103b705cfSriastradh } else { 37203b705cfSriastradh if (op->src.is_solid) 37303b705cfSriastradh cblend |= TB0C_ARG1_SEL_DIFFUSE; 37403b705cfSriastradh else if (PICT_FORMAT_RGB(op->src.pict_format) != 0) 37503b705cfSriastradh cblend |= TB0C_ARG1_SEL_TEXEL0; 37603b705cfSriastradh else 37703b705cfSriastradh cblend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT; /* 0.0 */ 37842542f5fSchristos 37942542f5fSchristos if (op->src.is_opaque) 38003b705cfSriastradh ablend |= TB0A_ARG1_SEL_ONE; 38142542f5fSchristos else if (op->src.is_solid) 38242542f5fSchristos ablend |= TB0A_ARG1_SEL_DIFFUSE; 38303b705cfSriastradh else 38403b705cfSriastradh ablend |= TB0A_ARG1_SEL_TEXEL0; 38503b705cfSriastradh } 38603b705cfSriastradh 38703b705cfSriastradh if (op->mask.bo) { 38803b705cfSriastradh if (op->src.is_solid) { 38903b705cfSriastradh cblend |= TB0C_ARG2_SEL_TEXEL0; 39003b705cfSriastradh ablend |= TB0A_ARG2_SEL_TEXEL0; 39103b705cfSriastradh } else { 39203b705cfSriastradh cblend |= TB0C_ARG2_SEL_TEXEL1; 39303b705cfSriastradh ablend |= TB0A_ARG2_SEL_TEXEL1; 39403b705cfSriastradh } 39503b705cfSriastradh 39603b705cfSriastradh if (op->dst.format == PICT_a8 || !op->has_component_alpha) 39703b705cfSriastradh cblend |= TB0C_ARG2_REPLICATE_ALPHA; 39803b705cfSriastradh 39903b705cfSriastradh cblend |= TB0C_OP_MODULATE; 40003b705cfSriastradh ablend |= TB0A_OP_MODULATE; 40103b705cfSriastradh } else if (op->mask.is_solid) { 40203b705cfSriastradh cblend |= TB0C_ARG2_SEL_DIFFUSE; 40303b705cfSriastradh ablend |= TB0A_ARG2_SEL_DIFFUSE; 40403b705cfSriastradh 40503b705cfSriastradh if (op->dst.format == PICT_a8 || !op->has_component_alpha) 40603b705cfSriastradh cblend |= TB0C_ARG2_REPLICATE_ALPHA; 40703b705cfSriastradh 40803b705cfSriastradh cblend |= TB0C_OP_MODULATE; 40903b705cfSriastradh ablend |= TB0A_OP_MODULATE; 41003b705cfSriastradh } else { 41103b705cfSriastradh cblend |= TB0C_OP_ARG1; 41203b705cfSriastradh ablend |= TB0A_OP_ARG1; 41303b705cfSriastradh } 41403b705cfSriastradh 41503b705cfSriastradh *c_out = cblend; 41603b705cfSriastradh *a_out = ablend; 41703b705cfSriastradh} 41803b705cfSriastradh 41903b705cfSriastradhstatic uint32_t gen2_get_blend_cntl(int op, 42003b705cfSriastradh bool has_component_alpha, 42103b705cfSriastradh uint32_t dst_format) 42203b705cfSriastradh{ 42303b705cfSriastradh uint32_t sblend, dblend; 42403b705cfSriastradh 42503b705cfSriastradh if (op <= PictOpSrc) 42603b705cfSriastradh return S8_ENABLE_COLOR_BUFFER_WRITE; 42703b705cfSriastradh 42803b705cfSriastradh sblend = gen2_blend_op[op].src_blend; 42903b705cfSriastradh dblend = gen2_blend_op[op].dst_blend; 43003b705cfSriastradh 43142542f5fSchristos if (gen2_blend_op[op].dst_alpha) { 43242542f5fSchristos /* If there's no dst alpha channel, adjust the blend op so that 43342542f5fSchristos * we'll treat it as always 1. 43442542f5fSchristos */ 43542542f5fSchristos if (PICT_FORMAT_A(dst_format) == 0) { 43642542f5fSchristos if (sblend == BLENDFACTOR_DST_ALPHA) 43742542f5fSchristos sblend = BLENDFACTOR_ONE; 43842542f5fSchristos else if (sblend == BLENDFACTOR_INV_DST_ALPHA) 43942542f5fSchristos sblend = BLENDFACTOR_ZERO; 44042542f5fSchristos } 44142542f5fSchristos 44242542f5fSchristos /* gen2 engine reads 8bit color buffer into green channel 44342542f5fSchristos * in cases like color buffer blending etc., and also writes 44442542f5fSchristos * back green channel. So with dst_alpha blend we should use 44542542f5fSchristos * color factor. 44642542f5fSchristos */ 44742542f5fSchristos if (dst_format == PICT_a8) { 44842542f5fSchristos if (sblend == BLENDFACTOR_DST_ALPHA) 44942542f5fSchristos sblend = BLENDFACTOR_DST_COLR; 45042542f5fSchristos else if (sblend == BLENDFACTOR_INV_DST_ALPHA) 45142542f5fSchristos sblend = BLENDFACTOR_INV_DST_COLR; 45242542f5fSchristos } 45303b705cfSriastradh } 45403b705cfSriastradh 45503b705cfSriastradh /* If the source alpha is being used, then we should only be in a case 45603b705cfSriastradh * where the source blend factor is 0, and the source blend value is 45703b705cfSriastradh * the mask channels multiplied by the source picture's alpha. 45803b705cfSriastradh */ 45903b705cfSriastradh if (has_component_alpha && gen2_blend_op[op].src_alpha) { 46003b705cfSriastradh if (dblend == BLENDFACTOR_SRC_ALPHA) 46103b705cfSriastradh dblend = BLENDFACTOR_SRC_COLR; 46203b705cfSriastradh else if (dblend == BLENDFACTOR_INV_SRC_ALPHA) 46303b705cfSriastradh dblend = BLENDFACTOR_INV_SRC_COLR; 46403b705cfSriastradh } 46503b705cfSriastradh 46603b705cfSriastradh return (sblend << S8_SRC_BLEND_FACTOR_SHIFT | 46703b705cfSriastradh dblend << S8_DST_BLEND_FACTOR_SHIFT | 46803b705cfSriastradh S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | 46903b705cfSriastradh S8_ENABLE_COLOR_BUFFER_WRITE); 47003b705cfSriastradh} 47103b705cfSriastradh 47203b705cfSriastradhstatic void gen2_emit_invariant(struct sna *sna) 47303b705cfSriastradh{ 47403b705cfSriastradh int i; 47503b705cfSriastradh 47603b705cfSriastradh for (i = 0; i < 4; i++) { 47703b705cfSriastradh BATCH(_3DSTATE_MAP_CUBE | MAP_UNIT(i)); 47803b705cfSriastradh BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | MAP_UNIT(i) | 47903b705cfSriastradh DISABLE_TEX_STREAM_BUMP | 48003b705cfSriastradh ENABLE_TEX_STREAM_COORD_SET | TEX_STREAM_COORD_SET(i) | 48103b705cfSriastradh ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(i)); 48203b705cfSriastradh BATCH(_3DSTATE_MAP_COORD_TRANSFORM); 48303b705cfSriastradh BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(i)); 48403b705cfSriastradh } 48503b705cfSriastradh 48603b705cfSriastradh BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD); 48703b705cfSriastradh BATCH(TEXBIND_SET3(TEXCOORDSRC_VTXSET_3) | 48803b705cfSriastradh TEXBIND_SET2(TEXCOORDSRC_VTXSET_2) | 48903b705cfSriastradh TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) | 49003b705cfSriastradh TEXBIND_SET0(TEXCOORDSRC_VTXSET_0)); 49103b705cfSriastradh 49203b705cfSriastradh BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); 49303b705cfSriastradh 49403b705cfSriastradh BATCH(_3DSTATE_VERTEX_TRANSFORM); 49503b705cfSriastradh BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE); 49603b705cfSriastradh 49703b705cfSriastradh BATCH(_3DSTATE_W_STATE_CMD); 49803b705cfSriastradh BATCH(MAGIC_W_STATE_DWORD1); 49903b705cfSriastradh BATCH_F(1.0); 50003b705cfSriastradh 50103b705cfSriastradh BATCH(_3DSTATE_INDPT_ALPHA_BLEND_CMD | 50203b705cfSriastradh DISABLE_INDPT_ALPHA_BLEND | 50303b705cfSriastradh ENABLE_ALPHA_BLENDFUNC | ABLENDFUNC_ADD); 50403b705cfSriastradh 50503b705cfSriastradh BATCH(_3DSTATE_CONST_BLEND_COLOR_CMD); 50603b705cfSriastradh BATCH(0); 50703b705cfSriastradh 50803b705cfSriastradh BATCH(_3DSTATE_MODES_1_CMD | 50903b705cfSriastradh ENABLE_COLR_BLND_FUNC | BLENDFUNC_ADD | 51003b705cfSriastradh ENABLE_SRC_BLND_FACTOR | SRC_BLND_FACT(BLENDFACTOR_ONE) | 51103b705cfSriastradh ENABLE_DST_BLND_FACTOR | DST_BLND_FACT(BLENDFACTOR_ZERO)); 51203b705cfSriastradh 51303b705cfSriastradh BATCH(_3DSTATE_ENABLES_1_CMD | 51403b705cfSriastradh DISABLE_LOGIC_OP | 51503b705cfSriastradh DISABLE_STENCIL_TEST | 51603b705cfSriastradh DISABLE_DEPTH_BIAS | 51703b705cfSriastradh DISABLE_SPEC_ADD | 51803b705cfSriastradh DISABLE_FOG | 51903b705cfSriastradh DISABLE_ALPHA_TEST | 52003b705cfSriastradh DISABLE_DEPTH_TEST | 52103b705cfSriastradh ENABLE_COLOR_BLEND); 52203b705cfSriastradh 52303b705cfSriastradh BATCH(_3DSTATE_ENABLES_2_CMD | 52403b705cfSriastradh DISABLE_STENCIL_WRITE | 52503b705cfSriastradh DISABLE_DITHER | 52603b705cfSriastradh DISABLE_DEPTH_WRITE | 52703b705cfSriastradh ENABLE_COLOR_MASK | 52803b705cfSriastradh ENABLE_COLOR_WRITE | 52903b705cfSriastradh ENABLE_TEX_CACHE); 53003b705cfSriastradh 53103b705cfSriastradh BATCH(_3DSTATE_STIPPLE); 53203b705cfSriastradh BATCH(0); 53303b705cfSriastradh 53403b705cfSriastradh BATCH(_3DSTATE_MAP_BLEND_OP_CMD(0) | 53503b705cfSriastradh TEXPIPE_COLOR | 53603b705cfSriastradh ENABLE_TEXOUTPUT_WRT_SEL | 53703b705cfSriastradh TEXOP_OUTPUT_CURRENT | 53803b705cfSriastradh DISABLE_TEX_CNTRL_STAGE | 53903b705cfSriastradh TEXOP_SCALE_1X | 54003b705cfSriastradh TEXOP_MODIFY_PARMS | TEXOP_LAST_STAGE | 54103b705cfSriastradh TEXBLENDOP_ARG1); 54203b705cfSriastradh BATCH(_3DSTATE_MAP_BLEND_OP_CMD(0) | 54303b705cfSriastradh TEXPIPE_ALPHA | 54403b705cfSriastradh ENABLE_TEXOUTPUT_WRT_SEL | 54503b705cfSriastradh TEXOP_OUTPUT_CURRENT | 54603b705cfSriastradh TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | 54703b705cfSriastradh TEXBLENDOP_ARG1); 54803b705cfSriastradh BATCH(_3DSTATE_MAP_BLEND_ARG_CMD(0) | 54903b705cfSriastradh TEXPIPE_COLOR | 55003b705cfSriastradh TEXBLEND_ARG1 | 55103b705cfSriastradh TEXBLENDARG_MODIFY_PARMS | 55203b705cfSriastradh TEXBLENDARG_DIFFUSE); 55303b705cfSriastradh BATCH(_3DSTATE_MAP_BLEND_ARG_CMD(0) | 55403b705cfSriastradh TEXPIPE_ALPHA | 55503b705cfSriastradh TEXBLEND_ARG1 | 55603b705cfSriastradh TEXBLENDARG_MODIFY_PARMS | 55703b705cfSriastradh TEXBLENDARG_DIFFUSE); 55803b705cfSriastradh 55903b705cfSriastradh#define INVARIANT_SIZE 35 56003b705cfSriastradh 56103b705cfSriastradh sna->render_state.gen2.need_invariant = false; 56203b705cfSriastradh} 56303b705cfSriastradh 56403b705cfSriastradhstatic void 56503b705cfSriastradhgen2_get_batch(struct sna *sna, const struct sna_composite_op *op) 56603b705cfSriastradh{ 56703b705cfSriastradh kgem_set_mode(&sna->kgem, KGEM_RENDER, op->dst.bo); 56803b705cfSriastradh 56903b705cfSriastradh if (!kgem_check_batch(&sna->kgem, INVARIANT_SIZE+40)) { 57003b705cfSriastradh DBG(("%s: flushing batch: size %d > %d\n", 57103b705cfSriastradh __FUNCTION__, INVARIANT_SIZE+40, 57203b705cfSriastradh sna->kgem.surface-sna->kgem.nbatch)); 57303b705cfSriastradh kgem_submit(&sna->kgem); 57403b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 57503b705cfSriastradh } 57603b705cfSriastradh 57703b705cfSriastradh if (!kgem_check_reloc(&sna->kgem, 3)) { 57803b705cfSriastradh DBG(("%s: flushing batch: reloc %d >= %d\n", 57903b705cfSriastradh __FUNCTION__, 58003b705cfSriastradh sna->kgem.nreloc + 3, 58103b705cfSriastradh (int)KGEM_RELOC_SIZE(&sna->kgem))); 58203b705cfSriastradh kgem_submit(&sna->kgem); 58303b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 58403b705cfSriastradh } 58503b705cfSriastradh 58603b705cfSriastradh if (!kgem_check_exec(&sna->kgem, 3)) { 58703b705cfSriastradh DBG(("%s: flushing batch: exec %d >= %d\n", 58803b705cfSriastradh __FUNCTION__, 58903b705cfSriastradh sna->kgem.nexec + 1, 59003b705cfSriastradh (int)KGEM_EXEC_SIZE(&sna->kgem))); 59103b705cfSriastradh kgem_submit(&sna->kgem); 59203b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 59303b705cfSriastradh } 59403b705cfSriastradh 59503b705cfSriastradh if (sna->render_state.gen2.need_invariant) 59603b705cfSriastradh gen2_emit_invariant(sna); 59703b705cfSriastradh} 59803b705cfSriastradh 59903b705cfSriastradhstatic void gen2_emit_target(struct sna *sna, const struct sna_composite_op *op) 60003b705cfSriastradh{ 60103b705cfSriastradh assert(!too_large(op->dst.width, op->dst.height)); 60203b705cfSriastradh assert(op->dst.bo->pitch >= 8 && op->dst.bo->pitch <= MAX_3D_PITCH); 60303b705cfSriastradh assert(sna->render.vertex_offset == 0); 60403b705cfSriastradh 60542542f5fSchristos assert(op->dst.bo->unique_id); 60603b705cfSriastradh if (sna->render_state.gen2.target == op->dst.bo->unique_id) { 60703b705cfSriastradh kgem_bo_mark_dirty(op->dst.bo); 60803b705cfSriastradh return; 60903b705cfSriastradh } 61003b705cfSriastradh 61103b705cfSriastradh BATCH(_3DSTATE_BUF_INFO_CMD); 61203b705cfSriastradh BATCH(BUF_3D_ID_COLOR_BACK | 61303b705cfSriastradh gen2_buf_tiling(op->dst.bo->tiling) | 61403b705cfSriastradh BUF_3D_PITCH(op->dst.bo->pitch)); 61503b705cfSriastradh BATCH(kgem_add_reloc(&sna->kgem, sna->kgem.nbatch, 61603b705cfSriastradh op->dst.bo, 61703b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 61803b705cfSriastradh I915_GEM_DOMAIN_RENDER, 61903b705cfSriastradh 0)); 62003b705cfSriastradh 62103b705cfSriastradh BATCH(_3DSTATE_DST_BUF_VARS_CMD); 62203b705cfSriastradh BATCH(gen2_get_dst_format(op->dst.format)); 62303b705cfSriastradh 62403b705cfSriastradh BATCH(_3DSTATE_DRAW_RECT_CMD); 62503b705cfSriastradh BATCH(0); 62603b705cfSriastradh BATCH(0); /* ymin, xmin */ 62703b705cfSriastradh BATCH(DRAW_YMAX(op->dst.height - 1) | 62803b705cfSriastradh DRAW_XMAX(op->dst.width - 1)); 62903b705cfSriastradh BATCH(0); /* yorig, xorig */ 63003b705cfSriastradh 63103b705cfSriastradh sna->render_state.gen2.target = op->dst.bo->unique_id; 63203b705cfSriastradh} 63303b705cfSriastradh 63403b705cfSriastradhstatic void gen2_disable_logic_op(struct sna *sna) 63503b705cfSriastradh{ 63603b705cfSriastradh if (!sna->render_state.gen2.logic_op_enabled) 63703b705cfSriastradh return; 63803b705cfSriastradh 63903b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 64003b705cfSriastradh 64103b705cfSriastradh BATCH(_3DSTATE_ENABLES_1_CMD | 64203b705cfSriastradh DISABLE_LOGIC_OP | ENABLE_COLOR_BLEND); 64303b705cfSriastradh 64403b705cfSriastradh sna->render_state.gen2.logic_op_enabled = 0; 64503b705cfSriastradh} 64603b705cfSriastradh 64703b705cfSriastradhstatic void gen2_enable_logic_op(struct sna *sna, int op) 64803b705cfSriastradh{ 64903b705cfSriastradh static const uint8_t logic_op[] = { 65003b705cfSriastradh LOGICOP_CLEAR, /* GXclear */ 65103b705cfSriastradh LOGICOP_AND, /* GXand */ 65203b705cfSriastradh LOGICOP_AND_RVRSE, /* GXandReverse */ 65303b705cfSriastradh LOGICOP_COPY, /* GXcopy */ 65403b705cfSriastradh LOGICOP_AND_INV, /* GXandInverted */ 65503b705cfSriastradh LOGICOP_NOOP, /* GXnoop */ 65603b705cfSriastradh LOGICOP_XOR, /* GXxor */ 65703b705cfSriastradh LOGICOP_OR, /* GXor */ 65803b705cfSriastradh LOGICOP_NOR, /* GXnor */ 65903b705cfSriastradh LOGICOP_EQUIV, /* GXequiv */ 66003b705cfSriastradh LOGICOP_INV, /* GXinvert */ 66103b705cfSriastradh LOGICOP_OR_RVRSE, /* GXorReverse */ 66203b705cfSriastradh LOGICOP_COPY_INV, /* GXcopyInverted */ 66303b705cfSriastradh LOGICOP_OR_INV, /* GXorInverted */ 66403b705cfSriastradh LOGICOP_NAND, /* GXnand */ 66503b705cfSriastradh LOGICOP_SET /* GXset */ 66603b705cfSriastradh }; 66703b705cfSriastradh 66803b705cfSriastradh if (sna->render_state.gen2.logic_op_enabled != op+1) { 66903b705cfSriastradh if (!sna->render_state.gen2.logic_op_enabled) { 67003b705cfSriastradh if (op == GXclear || op == GXcopy) 67103b705cfSriastradh return; 67203b705cfSriastradh 67303b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 67403b705cfSriastradh 67503b705cfSriastradh BATCH(_3DSTATE_ENABLES_1_CMD | 67603b705cfSriastradh ENABLE_LOGIC_OP | DISABLE_COLOR_BLEND); 67703b705cfSriastradh } 67803b705cfSriastradh 67903b705cfSriastradh BATCH(_3DSTATE_MODES_4_CMD | 68003b705cfSriastradh ENABLE_LOGIC_OP_FUNC | LOGIC_OP_FUNC(logic_op[op])); 68103b705cfSriastradh sna->render_state.gen2.logic_op_enabled = op+1; 68203b705cfSriastradh } 68303b705cfSriastradh} 68403b705cfSriastradh 68503b705cfSriastradhstatic void gen2_emit_composite_state(struct sna *sna, 68603b705cfSriastradh const struct sna_composite_op *op) 68703b705cfSriastradh{ 68803b705cfSriastradh uint32_t texcoordfmt, v, unwind; 68903b705cfSriastradh uint32_t cblend, ablend; 69003b705cfSriastradh int tex; 69103b705cfSriastradh 69203b705cfSriastradh gen2_get_batch(sna, op); 69303b705cfSriastradh 69403b705cfSriastradh if (kgem_bo_is_dirty(op->src.bo) || kgem_bo_is_dirty(op->mask.bo)) { 69503b705cfSriastradh if (op->src.bo == op->dst.bo || op->mask.bo == op->dst.bo) 69603b705cfSriastradh BATCH(MI_FLUSH | MI_INVALIDATE_MAP_CACHE); 69703b705cfSriastradh else 69803b705cfSriastradh BATCH(_3DSTATE_MODES_5_CMD | 69903b705cfSriastradh PIPELINE_FLUSH_RENDER_CACHE | 70003b705cfSriastradh PIPELINE_FLUSH_TEXTURE_CACHE); 70103b705cfSriastradh kgem_clear_dirty(&sna->kgem); 70203b705cfSriastradh } 70303b705cfSriastradh 70403b705cfSriastradh gen2_emit_target(sna, op); 70503b705cfSriastradh 70603b705cfSriastradh unwind = sna->kgem.nbatch; 70703b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 70803b705cfSriastradh I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2); 70903b705cfSriastradh BATCH((!op->src.is_solid + (op->mask.bo != NULL)) << 12); 71003b705cfSriastradh BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY); 71103b705cfSriastradh BATCH(gen2_get_blend_cntl(op->op, 71203b705cfSriastradh op->has_component_alpha, 71303b705cfSriastradh op->dst.format)); 71403b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1, 71503b705cfSriastradh sna->kgem.batch + unwind + 1, 71603b705cfSriastradh 3 * sizeof(uint32_t)) == 0) 71703b705cfSriastradh sna->kgem.nbatch = unwind; 71803b705cfSriastradh else 71903b705cfSriastradh sna->render_state.gen2.ls1 = unwind; 72003b705cfSriastradh 72103b705cfSriastradh gen2_disable_logic_op(sna); 72203b705cfSriastradh 72303b705cfSriastradh gen2_get_blend_factors(op, op->op, &cblend, &ablend); 72403b705cfSriastradh unwind = sna->kgem.nbatch; 72503b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 72603b705cfSriastradh LOAD_TEXTURE_BLEND_STAGE(0) | 1); 72703b705cfSriastradh BATCH(cblend); 72803b705cfSriastradh BATCH(ablend); 72903b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1, 73003b705cfSriastradh sna->kgem.batch + unwind + 1, 73103b705cfSriastradh 2 * sizeof(uint32_t)) == 0) 73203b705cfSriastradh sna->kgem.nbatch = unwind; 73303b705cfSriastradh else 73403b705cfSriastradh sna->render_state.gen2.ls2 = unwind; 73503b705cfSriastradh 73603b705cfSriastradh tex = texcoordfmt = 0; 73703b705cfSriastradh if (!op->src.is_solid) { 73803b705cfSriastradh if (op->src.is_affine) 73903b705cfSriastradh texcoordfmt |= TEXCOORDFMT_2D << (2*tex); 74003b705cfSriastradh else 74103b705cfSriastradh texcoordfmt |= TEXCOORDFMT_3D << (2*tex); 74203b705cfSriastradh gen2_emit_texture(sna, &op->src, tex++); 74303b705cfSriastradh } else { 74403b705cfSriastradh if (op->src.u.gen2.pixel != sna->render_state.gen2.diffuse) { 74503b705cfSriastradh BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); 74603b705cfSriastradh BATCH(op->src.u.gen2.pixel); 74703b705cfSriastradh sna->render_state.gen2.diffuse = op->src.u.gen2.pixel; 74803b705cfSriastradh } 74903b705cfSriastradh } 75003b705cfSriastradh if (op->mask.bo) { 75103b705cfSriastradh if (op->mask.is_affine) 75203b705cfSriastradh texcoordfmt |= TEXCOORDFMT_2D << (2*tex); 75303b705cfSriastradh else 75403b705cfSriastradh texcoordfmt |= TEXCOORDFMT_3D << (2*tex); 75503b705cfSriastradh gen2_emit_texture(sna, &op->mask, tex++); 75603b705cfSriastradh } else if (op->mask.is_solid) { 75703b705cfSriastradh if (op->mask.u.gen2.pixel != sna->render_state.gen2.diffuse) { 75803b705cfSriastradh BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); 75903b705cfSriastradh BATCH(op->mask.u.gen2.pixel); 76003b705cfSriastradh sna->render_state.gen2.diffuse = op->mask.u.gen2.pixel; 76103b705cfSriastradh } 76203b705cfSriastradh } 76303b705cfSriastradh 76403b705cfSriastradh v = _3DSTATE_VERTEX_FORMAT_2_CMD | texcoordfmt; 76503b705cfSriastradh if (sna->render_state.gen2.vft != v) { 76603b705cfSriastradh BATCH(v); 76703b705cfSriastradh sna->render_state.gen2.vft = v; 76803b705cfSriastradh } 76903b705cfSriastradh} 77003b705cfSriastradh 77103b705cfSriastradhstatic inline void 77203b705cfSriastradhgen2_emit_composite_dstcoord(struct sna *sna, int dstX, int dstY) 77303b705cfSriastradh{ 77403b705cfSriastradh VERTEX(dstX); 77503b705cfSriastradh VERTEX(dstY); 77603b705cfSriastradh} 77703b705cfSriastradh 77803b705cfSriastradhinline static void 77903b705cfSriastradhgen2_emit_composite_linear(struct sna *sna, 78003b705cfSriastradh const struct sna_composite_channel *channel, 78103b705cfSriastradh int16_t x, int16_t y) 78203b705cfSriastradh{ 78303b705cfSriastradh float v; 78403b705cfSriastradh 78503b705cfSriastradh v = (x * channel->u.linear.dx + 78603b705cfSriastradh y * channel->u.linear.dy + 78703b705cfSriastradh channel->u.linear.offset); 78803b705cfSriastradh DBG(("%s: (%d, %d) -> %f\n", __FUNCTION__, x, y, v)); 78903b705cfSriastradh VERTEX(v); 79003b705cfSriastradh VERTEX(v); 79103b705cfSriastradh} 79203b705cfSriastradh 79303b705cfSriastradhstatic void 79403b705cfSriastradhgen2_emit_composite_texcoord(struct sna *sna, 79503b705cfSriastradh const struct sna_composite_channel *channel, 79603b705cfSriastradh int16_t x, int16_t y) 79703b705cfSriastradh{ 79803b705cfSriastradh float s = 0, t = 0, w = 1; 79903b705cfSriastradh 80003b705cfSriastradh x += channel->offset[0]; 80103b705cfSriastradh y += channel->offset[1]; 80203b705cfSriastradh 80303b705cfSriastradh if (channel->is_affine) { 80403b705cfSriastradh sna_get_transformed_coordinates(x, y, 80503b705cfSriastradh channel->transform, 80603b705cfSriastradh &s, &t); 80703b705cfSriastradh VERTEX(s * channel->scale[0]); 80803b705cfSriastradh VERTEX(t * channel->scale[1]); 80903b705cfSriastradh } else { 81003b705cfSriastradh sna_get_transformed_coordinates_3d(x, y, 81103b705cfSriastradh channel->transform, 81203b705cfSriastradh &s, &t, &w); 81303b705cfSriastradh VERTEX(s * channel->scale[0]); 81403b705cfSriastradh VERTEX(t * channel->scale[1]); 81503b705cfSriastradh VERTEX(w); 81603b705cfSriastradh } 81703b705cfSriastradh} 81803b705cfSriastradh 81903b705cfSriastradhstatic void 82003b705cfSriastradhgen2_emit_composite_vertex(struct sna *sna, 82103b705cfSriastradh const struct sna_composite_op *op, 82203b705cfSriastradh int16_t srcX, int16_t srcY, 82303b705cfSriastradh int16_t mskX, int16_t mskY, 82403b705cfSriastradh int16_t dstX, int16_t dstY) 82503b705cfSriastradh{ 82603b705cfSriastradh gen2_emit_composite_dstcoord(sna, dstX, dstY); 82703b705cfSriastradh if (op->src.is_linear) 82803b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, srcX, srcY); 82903b705cfSriastradh else if (!op->src.is_solid) 83003b705cfSriastradh gen2_emit_composite_texcoord(sna, &op->src, srcX, srcY); 83103b705cfSriastradh 83203b705cfSriastradh if (op->mask.is_linear) 83303b705cfSriastradh gen2_emit_composite_linear(sna, &op->mask, mskX, mskY); 83403b705cfSriastradh else if (op->mask.bo) 83503b705cfSriastradh gen2_emit_composite_texcoord(sna, &op->mask, mskX, mskY); 83603b705cfSriastradh} 83703b705cfSriastradh 83803b705cfSriastradhfastcall static void 83903b705cfSriastradhgen2_emit_composite_primitive(struct sna *sna, 84003b705cfSriastradh const struct sna_composite_op *op, 84103b705cfSriastradh const struct sna_composite_rectangles *r) 84203b705cfSriastradh{ 84303b705cfSriastradh gen2_emit_composite_vertex(sna, op, 84403b705cfSriastradh r->src.x + r->width, 84503b705cfSriastradh r->src.y + r->height, 84603b705cfSriastradh r->mask.x + r->width, 84703b705cfSriastradh r->mask.y + r->height, 84803b705cfSriastradh op->dst.x + r->dst.x + r->width, 84903b705cfSriastradh op->dst.y + r->dst.y + r->height); 85003b705cfSriastradh gen2_emit_composite_vertex(sna, op, 85103b705cfSriastradh r->src.x, 85203b705cfSriastradh r->src.y + r->height, 85303b705cfSriastradh r->mask.x, 85403b705cfSriastradh r->mask.y + r->height, 85503b705cfSriastradh op->dst.x + r->dst.x, 85603b705cfSriastradh op->dst.y + r->dst.y + r->height); 85703b705cfSriastradh gen2_emit_composite_vertex(sna, op, 85803b705cfSriastradh r->src.x, 85903b705cfSriastradh r->src.y, 86003b705cfSriastradh r->mask.x, 86103b705cfSriastradh r->mask.y, 86203b705cfSriastradh op->dst.x + r->dst.x, 86303b705cfSriastradh op->dst.y + r->dst.y); 86403b705cfSriastradh} 86503b705cfSriastradh 86603b705cfSriastradhfastcall static void 86703b705cfSriastradhgen2_emit_composite_primitive_constant(struct sna *sna, 86803b705cfSriastradh const struct sna_composite_op *op, 86903b705cfSriastradh const struct sna_composite_rectangles *r) 87003b705cfSriastradh{ 87103b705cfSriastradh int16_t dst_x = r->dst.x + op->dst.x; 87203b705cfSriastradh int16_t dst_y = r->dst.y + op->dst.y; 87303b705cfSriastradh 87403b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x + r->width, dst_y + r->height); 87503b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y + r->height); 87603b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y); 87703b705cfSriastradh} 87803b705cfSriastradh 87903b705cfSriastradhfastcall static void 88003b705cfSriastradhgen2_emit_composite_primitive_linear(struct sna *sna, 88103b705cfSriastradh const struct sna_composite_op *op, 88203b705cfSriastradh const struct sna_composite_rectangles *r) 88303b705cfSriastradh{ 88403b705cfSriastradh int16_t dst_x = r->dst.x + op->dst.x; 88503b705cfSriastradh int16_t dst_y = r->dst.y + op->dst.y; 88603b705cfSriastradh 88703b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x + r->width, dst_y + r->height); 88803b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, 88903b705cfSriastradh r->src.x + r->width, r->src.y + r->height); 89003b705cfSriastradh 89103b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y + r->height); 89203b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, 89303b705cfSriastradh r->src.x, r->src.y + r->height); 89403b705cfSriastradh 89503b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y); 89603b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, 89703b705cfSriastradh r->src.x, r->src.y); 89803b705cfSriastradh} 89903b705cfSriastradh 90003b705cfSriastradhfastcall static void 90103b705cfSriastradhgen2_emit_composite_primitive_identity(struct sna *sna, 90203b705cfSriastradh const struct sna_composite_op *op, 90303b705cfSriastradh const struct sna_composite_rectangles *r) 90403b705cfSriastradh{ 90503b705cfSriastradh float w = r->width; 90603b705cfSriastradh float h = r->height; 90703b705cfSriastradh float *v; 90803b705cfSriastradh 90903b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 91003b705cfSriastradh sna->kgem.nbatch += 12; 91103b705cfSriastradh 91203b705cfSriastradh v[8] = v[4] = r->dst.x + op->dst.x; 91303b705cfSriastradh v[0] = v[4] + w; 91403b705cfSriastradh 91503b705cfSriastradh v[9] = r->dst.y + op->dst.y; 91603b705cfSriastradh v[5] = v[1] = v[9] + h; 91703b705cfSriastradh 91803b705cfSriastradh v[10] = v[6] = (r->src.x + op->src.offset[0]) * op->src.scale[0]; 91903b705cfSriastradh v[2] = v[6] + w * op->src.scale[0]; 92003b705cfSriastradh 92103b705cfSriastradh v[11] = (r->src.y + op->src.offset[1]) * op->src.scale[1]; 92203b705cfSriastradh v[7] = v[3] = v[11] + h * op->src.scale[1]; 92303b705cfSriastradh} 92403b705cfSriastradh 92503b705cfSriastradhfastcall static void 92603b705cfSriastradhgen2_emit_composite_primitive_affine(struct sna *sna, 92703b705cfSriastradh const struct sna_composite_op *op, 92803b705cfSriastradh const struct sna_composite_rectangles *r) 92903b705cfSriastradh{ 93003b705cfSriastradh PictTransform *transform = op->src.transform; 93103b705cfSriastradh int src_x = r->src.x + (int)op->src.offset[0]; 93203b705cfSriastradh int src_y = r->src.y + (int)op->src.offset[1]; 93303b705cfSriastradh float *v; 93403b705cfSriastradh 93503b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 93603b705cfSriastradh sna->kgem.nbatch += 12; 93703b705cfSriastradh 93803b705cfSriastradh v[8] = v[4] = r->dst.x + op->dst.x; 93903b705cfSriastradh v[0] = v[4] + r->width; 94003b705cfSriastradh 94103b705cfSriastradh v[9] = r->dst.y + op->dst.y; 94203b705cfSriastradh v[5] = v[1] = v[9] + r->height; 94303b705cfSriastradh 94403b705cfSriastradh _sna_get_transformed_scaled(src_x + r->width, src_y + r->height, 94503b705cfSriastradh transform, op->src.scale, 94603b705cfSriastradh &v[2], &v[3]); 94703b705cfSriastradh 94803b705cfSriastradh _sna_get_transformed_scaled(src_x, src_y + r->height, 94903b705cfSriastradh transform, op->src.scale, 95003b705cfSriastradh &v[6], &v[7]); 95103b705cfSriastradh 95203b705cfSriastradh _sna_get_transformed_scaled(src_x, src_y, 95303b705cfSriastradh transform, op->src.scale, 95403b705cfSriastradh &v[10], &v[11]); 95503b705cfSriastradh} 95603b705cfSriastradh 95703b705cfSriastradhfastcall static void 95803b705cfSriastradhgen2_emit_composite_primitive_constant_identity_mask(struct sna *sna, 95903b705cfSriastradh const struct sna_composite_op *op, 96003b705cfSriastradh const struct sna_composite_rectangles *r) 96103b705cfSriastradh{ 96203b705cfSriastradh float w = r->width; 96303b705cfSriastradh float h = r->height; 96403b705cfSriastradh float *v; 96503b705cfSriastradh 96603b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 96703b705cfSriastradh sna->kgem.nbatch += 12; 96803b705cfSriastradh 96903b705cfSriastradh v[8] = v[4] = r->dst.x + op->dst.x; 97003b705cfSriastradh v[0] = v[4] + w; 97103b705cfSriastradh 97203b705cfSriastradh v[9] = r->dst.y + op->dst.y; 97303b705cfSriastradh v[5] = v[1] = v[9] + h; 97403b705cfSriastradh 97503b705cfSriastradh v[10] = v[6] = (r->mask.x + op->mask.offset[0]) * op->mask.scale[0]; 97603b705cfSriastradh v[2] = v[6] + w * op->mask.scale[0]; 97703b705cfSriastradh 97803b705cfSriastradh v[11] = (r->mask.y + op->mask.offset[1]) * op->mask.scale[1]; 97903b705cfSriastradh v[7] = v[3] = v[11] + h * op->mask.scale[1]; 98003b705cfSriastradh} 98103b705cfSriastradh 98203b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 98303b705cfSriastradhsse2 fastcall static void 98403b705cfSriastradhgen2_emit_composite_primitive_constant__sse2(struct sna *sna, 98503b705cfSriastradh const struct sna_composite_op *op, 98603b705cfSriastradh const struct sna_composite_rectangles *r) 98703b705cfSriastradh{ 98803b705cfSriastradh int16_t dst_x = r->dst.x + op->dst.x; 98903b705cfSriastradh int16_t dst_y = r->dst.y + op->dst.y; 99003b705cfSriastradh 99103b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x + r->width, dst_y + r->height); 99203b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y + r->height); 99303b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y); 99403b705cfSriastradh} 99503b705cfSriastradh 99603b705cfSriastradhsse2 fastcall static void 99703b705cfSriastradhgen2_emit_composite_primitive_linear__sse2(struct sna *sna, 99803b705cfSriastradh const struct sna_composite_op *op, 99903b705cfSriastradh const struct sna_composite_rectangles *r) 100003b705cfSriastradh{ 100103b705cfSriastradh int16_t dst_x = r->dst.x + op->dst.x; 100203b705cfSriastradh int16_t dst_y = r->dst.y + op->dst.y; 100303b705cfSriastradh 100403b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x + r->width, dst_y + r->height); 100503b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, 100603b705cfSriastradh r->src.x + r->width, r->src.y + r->height); 100703b705cfSriastradh 100803b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y + r->height); 100903b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, 101003b705cfSriastradh r->src.x, r->src.y + r->height); 101103b705cfSriastradh 101203b705cfSriastradh gen2_emit_composite_dstcoord(sna, dst_x, dst_y); 101303b705cfSriastradh gen2_emit_composite_linear(sna, &op->src, 101403b705cfSriastradh r->src.x, r->src.y); 101503b705cfSriastradh} 101603b705cfSriastradh 101703b705cfSriastradhsse2 fastcall static void 101803b705cfSriastradhgen2_emit_composite_primitive_identity__sse2(struct sna *sna, 101903b705cfSriastradh const struct sna_composite_op *op, 102003b705cfSriastradh const struct sna_composite_rectangles *r) 102103b705cfSriastradh{ 102203b705cfSriastradh float w = r->width; 102303b705cfSriastradh float h = r->height; 102403b705cfSriastradh float *v; 102503b705cfSriastradh 102603b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 102703b705cfSriastradh sna->kgem.nbatch += 12; 102803b705cfSriastradh 102903b705cfSriastradh v[8] = v[4] = r->dst.x + op->dst.x; 103003b705cfSriastradh v[0] = v[4] + w; 103103b705cfSriastradh 103203b705cfSriastradh v[9] = r->dst.y + op->dst.y; 103303b705cfSriastradh v[5] = v[1] = v[9] + h; 103403b705cfSriastradh 103503b705cfSriastradh v[10] = v[6] = (r->src.x + op->src.offset[0]) * op->src.scale[0]; 103603b705cfSriastradh v[2] = v[6] + w * op->src.scale[0]; 103703b705cfSriastradh 103803b705cfSriastradh v[11] = (r->src.y + op->src.offset[1]) * op->src.scale[1]; 103903b705cfSriastradh v[7] = v[3] = v[11] + h * op->src.scale[1]; 104003b705cfSriastradh} 104103b705cfSriastradh 104203b705cfSriastradhsse2 fastcall static void 104303b705cfSriastradhgen2_emit_composite_primitive_affine__sse2(struct sna *sna, 104403b705cfSriastradh const struct sna_composite_op *op, 104503b705cfSriastradh const struct sna_composite_rectangles *r) 104603b705cfSriastradh{ 104703b705cfSriastradh PictTransform *transform = op->src.transform; 104803b705cfSriastradh int src_x = r->src.x + (int)op->src.offset[0]; 104903b705cfSriastradh int src_y = r->src.y + (int)op->src.offset[1]; 105003b705cfSriastradh float *v; 105103b705cfSriastradh 105203b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 105303b705cfSriastradh sna->kgem.nbatch += 12; 105403b705cfSriastradh 105503b705cfSriastradh v[8] = v[4] = r->dst.x + op->dst.x; 105603b705cfSriastradh v[0] = v[4] + r->width; 105703b705cfSriastradh 105803b705cfSriastradh v[9] = r->dst.y + op->dst.y; 105903b705cfSriastradh v[5] = v[1] = v[9] + r->height; 106003b705cfSriastradh 106103b705cfSriastradh _sna_get_transformed_scaled(src_x + r->width, src_y + r->height, 106203b705cfSriastradh transform, op->src.scale, 106303b705cfSriastradh &v[2], &v[3]); 106403b705cfSriastradh 106503b705cfSriastradh _sna_get_transformed_scaled(src_x, src_y + r->height, 106603b705cfSriastradh transform, op->src.scale, 106703b705cfSriastradh &v[6], &v[7]); 106803b705cfSriastradh 106903b705cfSriastradh _sna_get_transformed_scaled(src_x, src_y, 107003b705cfSriastradh transform, op->src.scale, 107103b705cfSriastradh &v[10], &v[11]); 107203b705cfSriastradh} 107303b705cfSriastradh 107403b705cfSriastradhsse2 fastcall static void 107503b705cfSriastradhgen2_emit_composite_primitive_constant_identity_mask__sse2(struct sna *sna, 107603b705cfSriastradh const struct sna_composite_op *op, 107703b705cfSriastradh const struct sna_composite_rectangles *r) 107803b705cfSriastradh{ 107903b705cfSriastradh float w = r->width; 108003b705cfSriastradh float h = r->height; 108103b705cfSriastradh float *v; 108203b705cfSriastradh 108303b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 108403b705cfSriastradh sna->kgem.nbatch += 12; 108503b705cfSriastradh 108603b705cfSriastradh v[8] = v[4] = r->dst.x + op->dst.x; 108703b705cfSriastradh v[0] = v[4] + w; 108803b705cfSriastradh 108903b705cfSriastradh v[9] = r->dst.y + op->dst.y; 109003b705cfSriastradh v[5] = v[1] = v[9] + h; 109103b705cfSriastradh 109203b705cfSriastradh v[10] = v[6] = (r->mask.x + op->mask.offset[0]) * op->mask.scale[0]; 109303b705cfSriastradh v[2] = v[6] + w * op->mask.scale[0]; 109403b705cfSriastradh 109503b705cfSriastradh v[11] = (r->mask.y + op->mask.offset[1]) * op->mask.scale[1]; 109603b705cfSriastradh v[7] = v[3] = v[11] + h * op->mask.scale[1]; 109703b705cfSriastradh} 109803b705cfSriastradh#endif 109903b705cfSriastradh 110003b705cfSriastradhstatic void gen2_magic_ca_pass(struct sna *sna, 110103b705cfSriastradh const struct sna_composite_op *op) 110203b705cfSriastradh{ 110303b705cfSriastradh uint32_t ablend, cblend, *src, *dst; 110403b705cfSriastradh int n; 110503b705cfSriastradh 110603b705cfSriastradh if (!op->need_magic_ca_pass) 110703b705cfSriastradh return; 110803b705cfSriastradh 110903b705cfSriastradh DBG(("%s: batch=%x, vertex=%x\n", __FUNCTION__, 111003b705cfSriastradh sna->kgem.nbatch, sna->render.vertex_offset)); 111103b705cfSriastradh 111203b705cfSriastradh assert(op->mask.bo); 111303b705cfSriastradh assert(op->has_component_alpha); 111403b705cfSriastradh 111503b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(8) | 0); 111603b705cfSriastradh BATCH(BLENDFACTOR_ONE << S8_SRC_BLEND_FACTOR_SHIFT | 111703b705cfSriastradh BLENDFACTOR_ONE << S8_DST_BLEND_FACTOR_SHIFT | 111803b705cfSriastradh S8_ENABLE_COLOR_BLEND | S8_BLENDFUNC_ADD | 111903b705cfSriastradh S8_ENABLE_COLOR_BUFFER_WRITE); 112003b705cfSriastradh sna->render_state.gen2.ls1 = 0; 112103b705cfSriastradh 112203b705cfSriastradh gen2_get_blend_factors(op, PictOpAdd, &cblend, &ablend); 112303b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 112403b705cfSriastradh LOAD_TEXTURE_BLEND_STAGE(0) | 1); 112503b705cfSriastradh BATCH(cblend); 112603b705cfSriastradh BATCH(ablend); 112703b705cfSriastradh sna->render_state.gen2.ls2 = 0; 112803b705cfSriastradh 112903b705cfSriastradh src = sna->kgem.batch + sna->render.vertex_offset; 113003b705cfSriastradh dst = sna->kgem.batch + sna->kgem.nbatch; 113103b705cfSriastradh n = 1 + sna->render.vertex_index; 113203b705cfSriastradh sna->kgem.nbatch += n; 113303b705cfSriastradh assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem)); 113403b705cfSriastradh while (n--) 113503b705cfSriastradh *dst++ = *src++; 113603b705cfSriastradh} 113703b705cfSriastradh 113803b705cfSriastradhstatic void gen2_vertex_flush(struct sna *sna, 113903b705cfSriastradh const struct sna_composite_op *op) 114003b705cfSriastradh{ 114103b705cfSriastradh if (sna->render.vertex_index == 0) 114203b705cfSriastradh return; 114303b705cfSriastradh 114403b705cfSriastradh sna->kgem.batch[sna->render.vertex_offset] |= 114503b705cfSriastradh sna->render.vertex_index - 1; 114603b705cfSriastradh 114703b705cfSriastradh gen2_magic_ca_pass(sna, op); 114803b705cfSriastradh 114903b705cfSriastradh sna->render.vertex_offset = 0; 115003b705cfSriastradh sna->render.vertex_index = 0; 115103b705cfSriastradh} 115203b705cfSriastradh 115303b705cfSriastradhinline static int gen2_get_rectangles(struct sna *sna, 115403b705cfSriastradh const struct sna_composite_op *op, 115503b705cfSriastradh int want) 115603b705cfSriastradh{ 115703b705cfSriastradh int rem = batch_space(sna), size, need; 115803b705cfSriastradh 115903b705cfSriastradh DBG(("%s: want=%d, floats_per_vertex=%d, rem=%d\n", 116003b705cfSriastradh __FUNCTION__, want, op->floats_per_vertex, rem)); 116103b705cfSriastradh 116203b705cfSriastradh assert(op->floats_per_vertex); 116303b705cfSriastradh assert(op->floats_per_rect == 3 * op->floats_per_vertex); 116403b705cfSriastradh 116503b705cfSriastradh need = 1; 116603b705cfSriastradh size = op->floats_per_rect; 116703b705cfSriastradh if (op->need_magic_ca_pass) 116803b705cfSriastradh need += 6 + size*sna->render.vertex_index, size *= 2; 116903b705cfSriastradh 117003b705cfSriastradh DBG(("%s: want=%d, need=%d,size=%d, rem=%d\n", 117103b705cfSriastradh __FUNCTION__, want, need, size, rem)); 117203b705cfSriastradh if (rem < need + size) { 117303b705cfSriastradh gen2_vertex_flush(sna, op); 117403b705cfSriastradh kgem_submit(&sna->kgem); 117503b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_RENDER); 117603b705cfSriastradh return 0; 117703b705cfSriastradh } 117803b705cfSriastradh 117903b705cfSriastradh rem -= need; 118003b705cfSriastradh if (sna->render.vertex_offset == 0) { 118103b705cfSriastradh if ((sna->kgem.batch[sna->kgem.nbatch-1] & ~0xffff) == 118203b705cfSriastradh (PRIM3D_INLINE | PRIM3D_RECTLIST)) { 118303b705cfSriastradh uint32_t *b = &sna->kgem.batch[sna->kgem.nbatch-1]; 118403b705cfSriastradh assert(*b & 0xffff); 118503b705cfSriastradh sna->render.vertex_index = 1 + (*b & 0xffff); 118603b705cfSriastradh *b = PRIM3D_INLINE | PRIM3D_RECTLIST; 118703b705cfSriastradh sna->render.vertex_offset = sna->kgem.nbatch - 1; 118803b705cfSriastradh assert(!op->need_magic_ca_pass); 118903b705cfSriastradh } else { 119003b705cfSriastradh sna->render.vertex_offset = sna->kgem.nbatch; 119103b705cfSriastradh BATCH(PRIM3D_INLINE | PRIM3D_RECTLIST); 119203b705cfSriastradh } 119303b705cfSriastradh } 119403b705cfSriastradh 119503b705cfSriastradh if (want > 1 && want * size > rem) 119603b705cfSriastradh want = rem / size; 119703b705cfSriastradh 119803b705cfSriastradh assert(want); 119903b705cfSriastradh sna->render.vertex_index += want*op->floats_per_rect; 120003b705cfSriastradh return want; 120103b705cfSriastradh} 120203b705cfSriastradh 120303b705cfSriastradhfastcall static void 120403b705cfSriastradhgen2_render_composite_blt(struct sna *sna, 120503b705cfSriastradh const struct sna_composite_op *op, 120603b705cfSriastradh const struct sna_composite_rectangles *r) 120703b705cfSriastradh{ 120803b705cfSriastradh if (!gen2_get_rectangles(sna, op, 1)) { 120903b705cfSriastradh gen2_emit_composite_state(sna, op); 121003b705cfSriastradh gen2_get_rectangles(sna, op, 1); 121103b705cfSriastradh } 121203b705cfSriastradh 121303b705cfSriastradh op->prim_emit(sna, op, r); 121403b705cfSriastradh} 121503b705cfSriastradh 121603b705cfSriastradhfastcall static void 121703b705cfSriastradhgen2_render_composite_box(struct sna *sna, 121803b705cfSriastradh const struct sna_composite_op *op, 121903b705cfSriastradh const BoxRec *box) 122003b705cfSriastradh{ 122103b705cfSriastradh struct sna_composite_rectangles r; 122203b705cfSriastradh 122303b705cfSriastradh if (!gen2_get_rectangles(sna, op, 1)) { 122403b705cfSriastradh gen2_emit_composite_state(sna, op); 122503b705cfSriastradh gen2_get_rectangles(sna, op, 1); 122603b705cfSriastradh } 122703b705cfSriastradh 122803b705cfSriastradh DBG((" %s: (%d, %d) x (%d, %d)\n", __FUNCTION__, 122903b705cfSriastradh box->x1, box->y1, 123003b705cfSriastradh box->x2 - box->x1, 123103b705cfSriastradh box->y2 - box->y1)); 123203b705cfSriastradh 123303b705cfSriastradh r.dst.x = box->x1; r.dst.y = box->y1; 123403b705cfSriastradh r.width = box->x2 - box->x1; 123503b705cfSriastradh r.height = box->y2 - box->y1; 123603b705cfSriastradh r.src = r.mask = r.dst; 123703b705cfSriastradh 123803b705cfSriastradh op->prim_emit(sna, op, &r); 123903b705cfSriastradh} 124003b705cfSriastradh 124103b705cfSriastradhstatic void 124203b705cfSriastradhgen2_render_composite_boxes(struct sna *sna, 124303b705cfSriastradh const struct sna_composite_op *op, 124403b705cfSriastradh const BoxRec *box, int nbox) 124503b705cfSriastradh{ 124603b705cfSriastradh do { 124703b705cfSriastradh int nbox_this_time; 124803b705cfSriastradh 124903b705cfSriastradh nbox_this_time = gen2_get_rectangles(sna, op, nbox); 125003b705cfSriastradh if (nbox_this_time == 0) { 125103b705cfSriastradh gen2_emit_composite_state(sna, op); 125203b705cfSriastradh nbox_this_time = gen2_get_rectangles(sna, op, nbox); 125303b705cfSriastradh } 125403b705cfSriastradh nbox -= nbox_this_time; 125503b705cfSriastradh 125603b705cfSriastradh do { 125703b705cfSriastradh struct sna_composite_rectangles r; 125803b705cfSriastradh 125903b705cfSriastradh DBG((" %s: (%d, %d) x (%d, %d)\n", __FUNCTION__, 126003b705cfSriastradh box->x1, box->y1, 126103b705cfSriastradh box->x2 - box->x1, 126203b705cfSriastradh box->y2 - box->y1)); 126303b705cfSriastradh 126403b705cfSriastradh r.dst.x = box->x1; r.dst.y = box->y1; 126503b705cfSriastradh r.width = box->x2 - box->x1; 126603b705cfSriastradh r.height = box->y2 - box->y1; 126703b705cfSriastradh r.src = r.mask = r.dst; 126803b705cfSriastradh 126903b705cfSriastradh op->prim_emit(sna, op, &r); 127003b705cfSriastradh box++; 127103b705cfSriastradh } while (--nbox_this_time); 127203b705cfSriastradh } while (nbox); 127303b705cfSriastradh} 127403b705cfSriastradh 127503b705cfSriastradhstatic void gen2_render_composite_done(struct sna *sna, 127603b705cfSriastradh const struct sna_composite_op *op) 127703b705cfSriastradh{ 127803b705cfSriastradh gen2_vertex_flush(sna, op); 127903b705cfSriastradh 128003b705cfSriastradh if (op->mask.bo) 128103b705cfSriastradh kgem_bo_destroy(&sna->kgem, op->mask.bo); 128203b705cfSriastradh if (op->src.bo) 128303b705cfSriastradh kgem_bo_destroy(&sna->kgem, op->src.bo); 128403b705cfSriastradh sna_render_composite_redirect_done(sna, op); 128503b705cfSriastradh} 128603b705cfSriastradh 128703b705cfSriastradhstatic bool 128803b705cfSriastradhgen2_composite_solid_init(struct sna *sna, 128903b705cfSriastradh struct sna_composite_channel *channel, 129003b705cfSriastradh uint32_t color) 129103b705cfSriastradh{ 129203b705cfSriastradh channel->filter = PictFilterNearest; 129303b705cfSriastradh channel->repeat = RepeatNormal; 129403b705cfSriastradh channel->is_solid = true; 129503b705cfSriastradh channel->is_affine = true; 129603b705cfSriastradh channel->width = 1; 129703b705cfSriastradh channel->height = 1; 129803b705cfSriastradh channel->pict_format = PICT_a8r8g8b8; 129903b705cfSriastradh 130003b705cfSriastradh channel->bo = NULL; 130103b705cfSriastradh channel->u.gen2.pixel = color; 130203b705cfSriastradh 130303b705cfSriastradh channel->scale[0] = channel->scale[1] = 1; 130403b705cfSriastradh channel->offset[0] = channel->offset[1] = 0; 130503b705cfSriastradh return true; 130603b705cfSriastradh} 130703b705cfSriastradh 130803b705cfSriastradh#define xFixedToDouble(f) pixman_fixed_to_double(f) 130903b705cfSriastradh 131003b705cfSriastradhstatic bool 131103b705cfSriastradhgen2_composite_linear_init(struct sna *sna, 131203b705cfSriastradh PicturePtr picture, 131303b705cfSriastradh struct sna_composite_channel *channel, 131403b705cfSriastradh int x, int y, 131503b705cfSriastradh int w, int h, 131603b705cfSriastradh int dst_x, int dst_y) 131703b705cfSriastradh{ 131803b705cfSriastradh PictLinearGradient *linear = 131903b705cfSriastradh (PictLinearGradient *)picture->pSourcePict; 132003b705cfSriastradh pixman_fixed_t tx, ty; 132103b705cfSriastradh float x0, y0, sf; 132203b705cfSriastradh float dx, dy; 132303b705cfSriastradh 132403b705cfSriastradh DBG(("%s: p1=(%f, %f), p2=(%f, %f)\n", 132503b705cfSriastradh __FUNCTION__, 132603b705cfSriastradh xFixedToDouble(linear->p1.x), xFixedToDouble(linear->p1.y), 132703b705cfSriastradh xFixedToDouble(linear->p2.x), xFixedToDouble(linear->p2.y))); 132803b705cfSriastradh 132903b705cfSriastradh if (linear->p2.x == linear->p1.x && linear->p2.y == linear->p1.y) 133003b705cfSriastradh return 0; 133103b705cfSriastradh 133203b705cfSriastradh if (!sna_transform_is_affine(picture->transform)) { 133303b705cfSriastradh DBG(("%s: fallback due to projective transform\n", 133403b705cfSriastradh __FUNCTION__)); 133503b705cfSriastradh return sna_render_picture_fixup(sna, picture, channel, 133603b705cfSriastradh x, y, w, h, dst_x, dst_y); 133703b705cfSriastradh } 133803b705cfSriastradh 133903b705cfSriastradh channel->bo = sna_render_get_gradient(sna, (PictGradient *)linear); 134003b705cfSriastradh if (!channel->bo) 134103b705cfSriastradh return 0; 134203b705cfSriastradh 134303b705cfSriastradh channel->filter = PictFilterNearest; 134403b705cfSriastradh channel->repeat = picture->repeat ? picture->repeatType : RepeatNone; 134503b705cfSriastradh channel->is_linear = true; 134603b705cfSriastradh channel->width = channel->bo->pitch / 4; 134703b705cfSriastradh channel->height = 1; 134803b705cfSriastradh channel->pict_format = PICT_a8r8g8b8; 134903b705cfSriastradh 135003b705cfSriastradh channel->scale[0] = channel->scale[1] = 1; 135103b705cfSriastradh channel->offset[0] = channel->offset[1] = 0; 135203b705cfSriastradh 135303b705cfSriastradh if (sna_transform_is_translation(picture->transform, &tx, &ty)) { 135403b705cfSriastradh dx = xFixedToDouble(linear->p2.x - linear->p1.x); 135503b705cfSriastradh dy = xFixedToDouble(linear->p2.y - linear->p1.y); 135603b705cfSriastradh 135703b705cfSriastradh x0 = xFixedToDouble(linear->p1.x); 135803b705cfSriastradh y0 = xFixedToDouble(linear->p1.y); 135903b705cfSriastradh 136003b705cfSriastradh if (tx | ty) { 136103b705cfSriastradh x0 -= pixman_fixed_to_double(tx); 136203b705cfSriastradh y0 -= pixman_fixed_to_double(ty); 136303b705cfSriastradh } 136403b705cfSriastradh } else { 136503b705cfSriastradh struct pixman_f_vector p1, p2; 136603b705cfSriastradh struct pixman_f_transform m, inv; 136703b705cfSriastradh 136803b705cfSriastradh pixman_f_transform_from_pixman_transform(&m, picture->transform); 136903b705cfSriastradh DBG(("%s: transform = [%f %f %f, %f %f %f, %f %f %f]\n", 137003b705cfSriastradh __FUNCTION__, 137103b705cfSriastradh m.m[0][0], m.m[0][1], m.m[0][2], 137203b705cfSriastradh m.m[1][0], m.m[1][1], m.m[1][2], 137303b705cfSriastradh m.m[2][0], m.m[2][1], m.m[2][2])); 137403b705cfSriastradh if (!pixman_f_transform_invert(&inv, &m)) 137503b705cfSriastradh return 0; 137603b705cfSriastradh 137703b705cfSriastradh p1.v[0] = pixman_fixed_to_double(linear->p1.x); 137803b705cfSriastradh p1.v[1] = pixman_fixed_to_double(linear->p1.y); 137903b705cfSriastradh p1.v[2] = 1.; 138003b705cfSriastradh pixman_f_transform_point(&inv, &p1); 138103b705cfSriastradh 138203b705cfSriastradh p2.v[0] = pixman_fixed_to_double(linear->p2.x); 138303b705cfSriastradh p2.v[1] = pixman_fixed_to_double(linear->p2.y); 138403b705cfSriastradh p2.v[2] = 1.; 138503b705cfSriastradh pixman_f_transform_point(&inv, &p2); 138603b705cfSriastradh 138703b705cfSriastradh DBG(("%s: untransformed: p1=(%f, %f, %f), p2=(%f, %f, %f)\n", 138803b705cfSriastradh __FUNCTION__, 138903b705cfSriastradh p1.v[0], p1.v[1], p1.v[2], 139003b705cfSriastradh p2.v[0], p2.v[1], p2.v[2])); 139103b705cfSriastradh 139203b705cfSriastradh dx = p2.v[0] - p1.v[0]; 139303b705cfSriastradh dy = p2.v[1] - p1.v[1]; 139403b705cfSriastradh 139503b705cfSriastradh x0 = p1.v[0]; 139603b705cfSriastradh y0 = p1.v[1]; 139703b705cfSriastradh } 139803b705cfSriastradh 139903b705cfSriastradh sf = dx*dx + dy*dy; 140003b705cfSriastradh dx /= sf; 140103b705cfSriastradh dy /= sf; 140203b705cfSriastradh 140303b705cfSriastradh channel->u.linear.dx = dx; 140403b705cfSriastradh channel->u.linear.dy = dy; 140503b705cfSriastradh channel->u.linear.offset = -dx*(x0+dst_x-x) + -dy*(y0+dst_y-y); 140603b705cfSriastradh 140703b705cfSriastradh DBG(("%s: dx=%f, dy=%f, offset=%f\n", 140803b705cfSriastradh __FUNCTION__, dx, dy, channel->u.linear.offset)); 140903b705cfSriastradh 141003b705cfSriastradh return channel->bo != NULL; 141103b705cfSriastradh} 141203b705cfSriastradh 141303b705cfSriastradhstatic bool source_is_covered(PicturePtr picture, 141403b705cfSriastradh int x, int y, 141503b705cfSriastradh int width, int height) 141603b705cfSriastradh{ 141703b705cfSriastradh int x1, y1, x2, y2; 141803b705cfSriastradh 141903b705cfSriastradh if (picture->repeat && picture->repeatType != RepeatNone) 142003b705cfSriastradh return true; 142103b705cfSriastradh 142203b705cfSriastradh if (picture->pDrawable == NULL) 142303b705cfSriastradh return false; 142403b705cfSriastradh 142503b705cfSriastradh if (picture->transform) { 142603b705cfSriastradh pixman_box16_t sample; 142703b705cfSriastradh 142803b705cfSriastradh sample.x1 = x; 142903b705cfSriastradh sample.y1 = y; 143003b705cfSriastradh sample.x2 = x + width; 143103b705cfSriastradh sample.y2 = y + height; 143203b705cfSriastradh 143303b705cfSriastradh pixman_transform_bounds(picture->transform, &sample); 143403b705cfSriastradh 143503b705cfSriastradh x1 = sample.x1; 143603b705cfSriastradh x2 = sample.x2; 143703b705cfSriastradh y1 = sample.y1; 143803b705cfSriastradh y2 = sample.y2; 143903b705cfSriastradh } else { 144003b705cfSriastradh x1 = x; 144103b705cfSriastradh y1 = y; 144203b705cfSriastradh x2 = x + width; 144303b705cfSriastradh y2 = y + height; 144403b705cfSriastradh } 144503b705cfSriastradh 144603b705cfSriastradh return 144703b705cfSriastradh x1 >= 0 && y1 >= 0 && 144803b705cfSriastradh x2 <= picture->pDrawable->width && 144903b705cfSriastradh y2 <= picture->pDrawable->height; 145003b705cfSriastradh} 145103b705cfSriastradh 145203b705cfSriastradhstatic bool 145303b705cfSriastradhgen2_check_card_format(struct sna *sna, 145403b705cfSriastradh PicturePtr picture, 145503b705cfSriastradh struct sna_composite_channel *channel, 145603b705cfSriastradh int x, int y, int w, int h, 145703b705cfSriastradh bool *fixup_alpha) 145803b705cfSriastradh{ 145903b705cfSriastradh uint32_t format = picture->format; 146003b705cfSriastradh unsigned int i; 146103b705cfSriastradh 146203b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i8xx_tex_formats); i++) { 146303b705cfSriastradh if (i8xx_tex_formats[i].fmt == format) 146403b705cfSriastradh return true; 146503b705cfSriastradh } 146603b705cfSriastradh 146703b705cfSriastradh for (i = 0; i < ARRAY_SIZE(i85x_tex_formats); i++) { 146803b705cfSriastradh if (i85x_tex_formats[i].fmt == format) { 146903b705cfSriastradh if (sna->kgem.gen >= 021) 147003b705cfSriastradh return true; 147103b705cfSriastradh 147203b705cfSriastradh if (source_is_covered(picture, x, y, w,h)) { 147303b705cfSriastradh channel->is_opaque = true; 147403b705cfSriastradh return true; 147503b705cfSriastradh } 147603b705cfSriastradh 147703b705cfSriastradh *fixup_alpha = true; 147803b705cfSriastradh return false; 147903b705cfSriastradh } 148003b705cfSriastradh } 148103b705cfSriastradh 148203b705cfSriastradh *fixup_alpha = false; 148303b705cfSriastradh return false; 148403b705cfSriastradh} 148503b705cfSriastradh 148603b705cfSriastradhstatic int 148703b705cfSriastradhgen2_composite_picture(struct sna *sna, 148803b705cfSriastradh PicturePtr picture, 148903b705cfSriastradh struct sna_composite_channel *channel, 149003b705cfSriastradh int x, int y, 149103b705cfSriastradh int w, int h, 149203b705cfSriastradh int dst_x, int dst_y, 149303b705cfSriastradh bool precise) 149403b705cfSriastradh{ 149503b705cfSriastradh PixmapPtr pixmap; 149603b705cfSriastradh uint32_t color; 149703b705cfSriastradh int16_t dx, dy; 149803b705cfSriastradh bool fixup_alpha; 149903b705cfSriastradh 150003b705cfSriastradh DBG(("%s: (%d, %d)x(%d, %d), dst=(%d, %d)\n", 150103b705cfSriastradh __FUNCTION__, x, y, w, h, dst_x, dst_y)); 150203b705cfSriastradh 150303b705cfSriastradh channel->is_solid = false; 150403b705cfSriastradh channel->is_linear = false; 150503b705cfSriastradh channel->is_opaque = false; 150603b705cfSriastradh channel->is_affine = true; 150703b705cfSriastradh channel->transform = NULL; 150842542f5fSchristos channel->card_format = -1; 150903b705cfSriastradh 151003b705cfSriastradh if (sna_picture_is_solid(picture, &color)) 151103b705cfSriastradh return gen2_composite_solid_init(sna, channel, color); 151203b705cfSriastradh 151303b705cfSriastradh if (!gen2_check_repeat(picture)) { 151403b705cfSriastradh DBG(("%s -- fallback, unhandled repeat %d\n", 151503b705cfSriastradh __FUNCTION__, picture->repeat)); 151603b705cfSriastradh return sna_render_picture_fixup(sna, picture, channel, 151703b705cfSriastradh x, y, w, h, dst_x, dst_y); 151803b705cfSriastradh } 151903b705cfSriastradh 152003b705cfSriastradh if (!gen2_check_filter(picture)) { 152103b705cfSriastradh DBG(("%s -- fallback, unhandled filter %d\n", 152203b705cfSriastradh __FUNCTION__, picture->filter)); 152303b705cfSriastradh return sna_render_picture_fixup(sna, picture, channel, 152403b705cfSriastradh x, y, w, h, dst_x, dst_y); 152503b705cfSriastradh } 152603b705cfSriastradh 152703b705cfSriastradh if (picture->pDrawable == NULL) { 152803b705cfSriastradh int ret; 152903b705cfSriastradh 153003b705cfSriastradh if (picture->pSourcePict->type == SourcePictTypeLinear) 153103b705cfSriastradh return gen2_composite_linear_init(sna, picture, channel, 153203b705cfSriastradh x, y, 153303b705cfSriastradh w, h, 153403b705cfSriastradh dst_x, dst_y); 153503b705cfSriastradh 153603b705cfSriastradh DBG(("%s -- fallback, unhandled source %d\n", 153703b705cfSriastradh __FUNCTION__, picture->pSourcePict->type)); 153803b705cfSriastradh ret = -1; 153903b705cfSriastradh if (!precise) 154003b705cfSriastradh ret = sna_render_picture_approximate_gradient(sna, picture, channel, 154103b705cfSriastradh x, y, w, h, dst_x, dst_y); 154203b705cfSriastradh if (ret == -1) 154303b705cfSriastradh ret = sna_render_picture_fixup(sna, picture, channel, 154403b705cfSriastradh x, y, w, h, dst_x, dst_y); 154503b705cfSriastradh return ret; 154603b705cfSriastradh } 154703b705cfSriastradh 154803b705cfSriastradh if (picture->alphaMap) { 154903b705cfSriastradh DBG(("%s -- fallback, alphamap\n", __FUNCTION__)); 155003b705cfSriastradh return sna_render_picture_fixup(sna, picture, channel, 155103b705cfSriastradh x, y, w, h, dst_x, dst_y); 155203b705cfSriastradh } 155303b705cfSriastradh 155403b705cfSriastradh channel->repeat = picture->repeat ? picture->repeatType : RepeatNone; 155503b705cfSriastradh channel->filter = picture->filter; 155603b705cfSriastradh 155703b705cfSriastradh pixmap = get_drawable_pixmap(picture->pDrawable); 155803b705cfSriastradh get_drawable_deltas(picture->pDrawable, pixmap, &dx, &dy); 155903b705cfSriastradh 156003b705cfSriastradh x += dx + picture->pDrawable->x; 156103b705cfSriastradh y += dy + picture->pDrawable->y; 156203b705cfSriastradh 156303b705cfSriastradh channel->is_affine = sna_transform_is_affine(picture->transform); 156442542f5fSchristos if (sna_transform_is_imprecise_integer_translation(picture->transform, picture->filter, precise, &dx, &dy)) { 156503b705cfSriastradh DBG(("%s: integer translation (%d, %d), removing\n", 156603b705cfSriastradh __FUNCTION__, dx, dy)); 156703b705cfSriastradh x += dx; 156803b705cfSriastradh y += dy; 156903b705cfSriastradh channel->transform = NULL; 157003b705cfSriastradh channel->filter = PictFilterNearest; 157142542f5fSchristos 157242542f5fSchristos if (channel->repeat && 157342542f5fSchristos (x >= 0 && 157442542f5fSchristos y >= 0 && 157542542f5fSchristos x + w < pixmap->drawable.width && 157642542f5fSchristos y + h < pixmap->drawable.height)) { 157742542f5fSchristos struct sna_pixmap *priv = sna_pixmap(pixmap); 157842542f5fSchristos if (priv && priv->clear) { 157942542f5fSchristos DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color)); 158042542f5fSchristos return gen2_composite_solid_init(sna, channel, priv->clear_color); 158142542f5fSchristos } 158242542f5fSchristos } 158303b705cfSriastradh } else 158403b705cfSriastradh channel->transform = picture->transform; 158503b705cfSriastradh 158603b705cfSriastradh if (!gen2_check_card_format(sna, picture, channel, x, y, w ,h, &fixup_alpha)) 158703b705cfSriastradh return sna_render_picture_convert(sna, picture, channel, pixmap, 158803b705cfSriastradh x, y, w, h, dst_x, dst_y, fixup_alpha); 158903b705cfSriastradh 159003b705cfSriastradh channel->pict_format = picture->format; 159103b705cfSriastradh if (too_large(pixmap->drawable.width, pixmap->drawable.height)) 159203b705cfSriastradh return sna_render_picture_extract(sna, picture, channel, 159303b705cfSriastradh x, y, w, h, dst_x, dst_y); 159403b705cfSriastradh 159503b705cfSriastradh return sna_render_pixmap_bo(sna, channel, pixmap, 159603b705cfSriastradh x, y, w, h, dst_x, dst_y); 159703b705cfSriastradh} 159803b705cfSriastradh 159903b705cfSriastradhstatic bool 160003b705cfSriastradhgen2_composite_set_target(struct sna *sna, 160103b705cfSriastradh struct sna_composite_op *op, 160203b705cfSriastradh PicturePtr dst, 160342542f5fSchristos int x, int y, int w, int h, 160442542f5fSchristos bool partial) 160503b705cfSriastradh{ 160603b705cfSriastradh BoxRec box; 160742542f5fSchristos unsigned hint; 160803b705cfSriastradh 160903b705cfSriastradh op->dst.pixmap = get_drawable_pixmap(dst->pDrawable); 161003b705cfSriastradh op->dst.format = dst->format; 161103b705cfSriastradh op->dst.width = op->dst.pixmap->drawable.width; 161203b705cfSriastradh op->dst.height = op->dst.pixmap->drawable.height; 161303b705cfSriastradh 161403b705cfSriastradh if (w && h) { 161503b705cfSriastradh box.x1 = x; 161603b705cfSriastradh box.y1 = y; 161703b705cfSriastradh box.x2 = x + w; 161803b705cfSriastradh box.y2 = y + h; 161903b705cfSriastradh } else 162003b705cfSriastradh sna_render_picture_extents(dst, &box); 162103b705cfSriastradh 162242542f5fSchristos hint = PREFER_GPU | FORCE_GPU | RENDER_GPU; 162342542f5fSchristos if (!partial) { 162442542f5fSchristos hint |= IGNORE_DAMAGE; 162542542f5fSchristos if (w == op->dst.width && h == op->dst.height) 162642542f5fSchristos hint |= REPLACES; 162742542f5fSchristos } 162842542f5fSchristos 162942542f5fSchristos op->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint, &box, &op->damage); 163003b705cfSriastradh if (op->dst.bo == NULL) 163103b705cfSriastradh return false; 163203b705cfSriastradh 163342542f5fSchristos if (hint & REPLACES) { 163442542f5fSchristos struct sna_pixmap *priv = sna_pixmap(op->dst.pixmap); 163542542f5fSchristos kgem_bo_pair_undo(&sna->kgem, priv->gpu_bo, priv->cpu_bo); 163603b705cfSriastradh } 163703b705cfSriastradh 163842542f5fSchristos assert((op->dst.bo->pitch & 7) == 0); 163942542f5fSchristos 164003b705cfSriastradh get_drawable_deltas(dst->pDrawable, op->dst.pixmap, 164103b705cfSriastradh &op->dst.x, &op->dst.y); 164203b705cfSriastradh 164342542f5fSchristos DBG(("%s: pixmap=%ld, format=%08x, size=%dx%d, pitch=%d, delta=(%d,%d),damage=%p\n", 164403b705cfSriastradh __FUNCTION__, 164542542f5fSchristos op->dst.pixmap->drawable.serialNumber, (int)op->dst.format, 164603b705cfSriastradh op->dst.width, op->dst.height, 164703b705cfSriastradh op->dst.bo->pitch, 164803b705cfSriastradh op->dst.x, op->dst.y, 164903b705cfSriastradh op->damage ? *op->damage : (void *)-1)); 165003b705cfSriastradh 165103b705cfSriastradh assert(op->dst.bo->proxy == NULL); 165242542f5fSchristos 165342542f5fSchristos if (((too_large(op->dst.width, op->dst.height) || 165442542f5fSchristos op->dst.bo->pitch > MAX_3D_PITCH)) && 165542542f5fSchristos !sna_render_composite_redirect(sna, op, x, y, w, h, partial)) 165642542f5fSchristos return false; 165742542f5fSchristos 165803b705cfSriastradh return true; 165903b705cfSriastradh} 166003b705cfSriastradh 166103b705cfSriastradhstatic bool 166203b705cfSriastradhis_unhandled_gradient(PicturePtr picture, bool precise) 166303b705cfSriastradh{ 166403b705cfSriastradh if (picture->pDrawable) 166503b705cfSriastradh return false; 166603b705cfSriastradh 166703b705cfSriastradh switch (picture->pSourcePict->type) { 166803b705cfSriastradh case SourcePictTypeSolidFill: 166903b705cfSriastradh case SourcePictTypeLinear: 167003b705cfSriastradh return false; 167103b705cfSriastradh default: 167203b705cfSriastradh return precise; 167303b705cfSriastradh } 167403b705cfSriastradh} 167503b705cfSriastradh 167603b705cfSriastradhstatic bool 167703b705cfSriastradhhas_alphamap(PicturePtr p) 167803b705cfSriastradh{ 167903b705cfSriastradh return p->alphaMap != NULL; 168003b705cfSriastradh} 168103b705cfSriastradh 168203b705cfSriastradhstatic bool 168303b705cfSriastradhneed_upload(PicturePtr p) 168403b705cfSriastradh{ 168503b705cfSriastradh return p->pDrawable && unattached(p->pDrawable) && untransformed(p); 168603b705cfSriastradh} 168703b705cfSriastradh 168803b705cfSriastradhstatic bool 168903b705cfSriastradhsource_is_busy(PixmapPtr pixmap) 169003b705cfSriastradh{ 169103b705cfSriastradh struct sna_pixmap *priv = sna_pixmap(pixmap); 169203b705cfSriastradh if (priv == NULL) 169303b705cfSriastradh return false; 169403b705cfSriastradh 169503b705cfSriastradh if (priv->clear) 169603b705cfSriastradh return false; 169703b705cfSriastradh 169803b705cfSriastradh if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo)) 169903b705cfSriastradh return true; 170003b705cfSriastradh 170103b705cfSriastradh if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) 170203b705cfSriastradh return true; 170303b705cfSriastradh 170403b705cfSriastradh return priv->gpu_damage && !priv->cpu_damage; 170503b705cfSriastradh} 170603b705cfSriastradh 170703b705cfSriastradhstatic bool 170803b705cfSriastradhsource_fallback(PicturePtr p, PixmapPtr pixmap, bool precise) 170903b705cfSriastradh{ 171003b705cfSriastradh if (sna_picture_is_solid(p, NULL)) 171103b705cfSriastradh return false; 171203b705cfSriastradh 171303b705cfSriastradh if (is_unhandled_gradient(p, precise) || !gen2_check_repeat(p)) 171403b705cfSriastradh return true; 171503b705cfSriastradh 171603b705cfSriastradh if (pixmap && source_is_busy(pixmap)) 171703b705cfSriastradh return false; 171803b705cfSriastradh 171903b705cfSriastradh return has_alphamap(p) || !gen2_check_filter(p) || need_upload(p); 172003b705cfSriastradh} 172103b705cfSriastradh 172203b705cfSriastradhstatic bool 172303b705cfSriastradhgen2_composite_fallback(struct sna *sna, 172403b705cfSriastradh PicturePtr src, 172503b705cfSriastradh PicturePtr mask, 172603b705cfSriastradh PicturePtr dst) 172703b705cfSriastradh{ 172803b705cfSriastradh PixmapPtr src_pixmap; 172903b705cfSriastradh PixmapPtr mask_pixmap; 173003b705cfSriastradh PixmapPtr dst_pixmap; 173103b705cfSriastradh bool src_fallback, mask_fallback; 173203b705cfSriastradh 173303b705cfSriastradh if (!gen2_check_dst_format(dst->format)) { 173403b705cfSriastradh DBG(("%s: unknown destination format: %d\n", 173503b705cfSriastradh __FUNCTION__, dst->format)); 173603b705cfSriastradh return true; 173703b705cfSriastradh } 173803b705cfSriastradh 173903b705cfSriastradh dst_pixmap = get_drawable_pixmap(dst->pDrawable); 174003b705cfSriastradh 174103b705cfSriastradh src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL; 174203b705cfSriastradh src_fallback = source_fallback(src, src_pixmap, 174303b705cfSriastradh dst->polyMode == PolyModePrecise); 174403b705cfSriastradh 174503b705cfSriastradh if (mask) { 174603b705cfSriastradh mask_pixmap = mask->pDrawable ? get_drawable_pixmap(mask->pDrawable) : NULL; 174703b705cfSriastradh mask_fallback = source_fallback(mask, mask_pixmap, 174803b705cfSriastradh dst->polyMode == PolyModePrecise); 174903b705cfSriastradh } else { 175003b705cfSriastradh mask_pixmap = NULL; 175103b705cfSriastradh mask_fallback = NULL; 175203b705cfSriastradh } 175303b705cfSriastradh 175403b705cfSriastradh /* If we are using the destination as a source and need to 175503b705cfSriastradh * readback in order to upload the source, do it all 175603b705cfSriastradh * on the cpu. 175703b705cfSriastradh */ 175803b705cfSriastradh if (src_pixmap == dst_pixmap && src_fallback) { 175903b705cfSriastradh DBG(("%s: src is dst and will fallback\n",__FUNCTION__)); 176003b705cfSriastradh return true; 176103b705cfSriastradh } 176203b705cfSriastradh if (mask_pixmap == dst_pixmap && mask_fallback) { 176303b705cfSriastradh DBG(("%s: mask is dst and will fallback\n",__FUNCTION__)); 176403b705cfSriastradh return true; 176503b705cfSriastradh } 176603b705cfSriastradh 176703b705cfSriastradh /* If anything is on the GPU, push everything out to the GPU */ 176803b705cfSriastradh if (dst_use_gpu(dst_pixmap)) { 176903b705cfSriastradh DBG(("%s: dst is already on the GPU, try to use GPU\n", 177003b705cfSriastradh __FUNCTION__)); 177103b705cfSriastradh return false; 177203b705cfSriastradh } 177303b705cfSriastradh 177403b705cfSriastradh if (src_pixmap && !src_fallback) { 177503b705cfSriastradh DBG(("%s: src is already on the GPU, try to use GPU\n", 177603b705cfSriastradh __FUNCTION__)); 177703b705cfSriastradh return false; 177803b705cfSriastradh } 177903b705cfSriastradh if (mask_pixmap && !mask_fallback) { 178003b705cfSriastradh DBG(("%s: mask is already on the GPU, try to use GPU\n", 178103b705cfSriastradh __FUNCTION__)); 178203b705cfSriastradh return false; 178303b705cfSriastradh } 178403b705cfSriastradh 178503b705cfSriastradh /* However if the dst is not on the GPU and we need to 178603b705cfSriastradh * render one of the sources using the CPU, we may 178703b705cfSriastradh * as well do the entire operation in place onthe CPU. 178803b705cfSriastradh */ 178903b705cfSriastradh if (src_fallback) { 179003b705cfSriastradh DBG(("%s: dst is on the CPU and src will fallback\n", 179103b705cfSriastradh __FUNCTION__)); 179203b705cfSriastradh return true; 179303b705cfSriastradh } 179403b705cfSriastradh 179503b705cfSriastradh if (mask && mask_fallback) { 179603b705cfSriastradh DBG(("%s: dst is on the CPU and mask will fallback\n", 179703b705cfSriastradh __FUNCTION__)); 179803b705cfSriastradh return true; 179903b705cfSriastradh } 180003b705cfSriastradh 180103b705cfSriastradh if (too_large(dst_pixmap->drawable.width, 180203b705cfSriastradh dst_pixmap->drawable.height) && 180303b705cfSriastradh dst_is_cpu(dst_pixmap)) { 180403b705cfSriastradh DBG(("%s: dst is on the CPU and too large\n", __FUNCTION__)); 180503b705cfSriastradh return true; 180603b705cfSriastradh } 180703b705cfSriastradh 180803b705cfSriastradh DBG(("%s: dst is not on the GPU and the operation should not fallback\n", 180903b705cfSriastradh __FUNCTION__)); 181003b705cfSriastradh return dst_use_cpu(dst_pixmap); 181103b705cfSriastradh} 181203b705cfSriastradh 181303b705cfSriastradhstatic int 181403b705cfSriastradhreuse_source(struct sna *sna, 181503b705cfSriastradh PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y, 181603b705cfSriastradh PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y) 181703b705cfSriastradh{ 181803b705cfSriastradh uint32_t color; 181903b705cfSriastradh 182003b705cfSriastradh if (src_x != msk_x || src_y != msk_y) 182103b705cfSriastradh return false; 182203b705cfSriastradh 182303b705cfSriastradh if (sna_picture_is_solid(mask, &color)) 182403b705cfSriastradh return gen2_composite_solid_init(sna, mc, color); 182503b705cfSriastradh 182603b705cfSriastradh if (sc->is_solid) 182703b705cfSriastradh return false; 182803b705cfSriastradh 182903b705cfSriastradh if (src == mask) { 183003b705cfSriastradh DBG(("%s: mask is source\n", __FUNCTION__)); 183103b705cfSriastradh *mc = *sc; 183203b705cfSriastradh mc->bo = kgem_bo_reference(mc->bo); 183303b705cfSriastradh return true; 183403b705cfSriastradh } 183503b705cfSriastradh 183603b705cfSriastradh if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable) 183703b705cfSriastradh return false; 183803b705cfSriastradh 183903b705cfSriastradh DBG(("%s: mask reuses source drawable\n", __FUNCTION__)); 184003b705cfSriastradh 184103b705cfSriastradh if (!sna_transform_equal(src->transform, mask->transform)) 184203b705cfSriastradh return false; 184303b705cfSriastradh 184403b705cfSriastradh if (!sna_picture_alphamap_equal(src, mask)) 184503b705cfSriastradh return false; 184603b705cfSriastradh 184703b705cfSriastradh if (!gen2_check_repeat(mask)) 184803b705cfSriastradh return false; 184903b705cfSriastradh 185003b705cfSriastradh if (!gen2_check_filter(mask)) 185103b705cfSriastradh return false; 185203b705cfSriastradh 185303b705cfSriastradh if (!gen2_check_format(sna, mask)) 185403b705cfSriastradh return false; 185503b705cfSriastradh 185603b705cfSriastradh DBG(("%s: reusing source channel for mask with a twist\n", 185703b705cfSriastradh __FUNCTION__)); 185803b705cfSriastradh 185903b705cfSriastradh *mc = *sc; 186003b705cfSriastradh mc->repeat = mask->repeat ? mask->repeatType : RepeatNone; 186103b705cfSriastradh mc->filter = mask->filter; 186203b705cfSriastradh mc->pict_format = mask->format; 186303b705cfSriastradh mc->bo = kgem_bo_reference(mc->bo); 186403b705cfSriastradh return true; 186503b705cfSriastradh} 186603b705cfSriastradh 186703b705cfSriastradhstatic bool 186803b705cfSriastradhgen2_render_composite(struct sna *sna, 186903b705cfSriastradh uint8_t op, 187003b705cfSriastradh PicturePtr src, 187103b705cfSriastradh PicturePtr mask, 187203b705cfSriastradh PicturePtr dst, 187303b705cfSriastradh int16_t src_x, int16_t src_y, 187403b705cfSriastradh int16_t mask_x, int16_t mask_y, 187503b705cfSriastradh int16_t dst_x, int16_t dst_y, 187603b705cfSriastradh int16_t width, int16_t height, 187742542f5fSchristos unsigned flags, 187803b705cfSriastradh struct sna_composite_op *tmp) 187903b705cfSriastradh{ 188003b705cfSriastradh DBG(("%s()\n", __FUNCTION__)); 188103b705cfSriastradh 188203b705cfSriastradh if (op >= ARRAY_SIZE(gen2_blend_op)) { 188303b705cfSriastradh DBG(("%s: fallback due to unhandled blend op: %d\n", 188403b705cfSriastradh __FUNCTION__, op)); 188503b705cfSriastradh return false; 188603b705cfSriastradh } 188703b705cfSriastradh 188803b705cfSriastradh if (mask == NULL && 188903b705cfSriastradh sna_blt_composite(sna, op, src, dst, 189003b705cfSriastradh src_x, src_y, 189103b705cfSriastradh dst_x, dst_y, 189203b705cfSriastradh width, height, 189342542f5fSchristos flags, tmp)) 189403b705cfSriastradh return true; 189503b705cfSriastradh 189603b705cfSriastradh if (gen2_composite_fallback(sna, src, mask, dst)) 189742542f5fSchristos goto fallback; 189803b705cfSriastradh 189903b705cfSriastradh if (need_tiling(sna, width, height)) 190003b705cfSriastradh return sna_tiling_composite(op, src, mask, dst, 190103b705cfSriastradh src_x, src_y, 190203b705cfSriastradh mask_x, mask_y, 190303b705cfSriastradh dst_x, dst_y, 190403b705cfSriastradh width, height, 190503b705cfSriastradh tmp); 190603b705cfSriastradh 190742542f5fSchristos tmp->op = op; 190842542f5fSchristos sna_render_composite_redirect_init(tmp); 190942542f5fSchristos 191003b705cfSriastradh if (!gen2_composite_set_target(sna, tmp, dst, 191142542f5fSchristos dst_x, dst_y, width, height, 191242542f5fSchristos flags & COMPOSITE_PARTIAL || op > PictOpSrc)) { 191303b705cfSriastradh DBG(("%s: unable to set render target\n", 191403b705cfSriastradh __FUNCTION__)); 191542542f5fSchristos goto fallback; 191603b705cfSriastradh } 191703b705cfSriastradh 191803b705cfSriastradh switch (gen2_composite_picture(sna, src, &tmp->src, 191903b705cfSriastradh src_x, src_y, 192003b705cfSriastradh width, height, 192103b705cfSriastradh dst_x, dst_y, 192203b705cfSriastradh dst->polyMode == PolyModePrecise)) { 192303b705cfSriastradh case -1: 192403b705cfSriastradh DBG(("%s: fallback -- unable to prepare source\n", 192503b705cfSriastradh __FUNCTION__)); 192603b705cfSriastradh goto cleanup_dst; 192703b705cfSriastradh case 0: 192803b705cfSriastradh gen2_composite_solid_init(sna, &tmp->src, 0); 192903b705cfSriastradh break; 193003b705cfSriastradh case 1: 193103b705cfSriastradh if (mask == NULL && tmp->src.bo && 193203b705cfSriastradh sna_blt_composite__convert(sna, 193303b705cfSriastradh dst_x, dst_y, width, height, 193403b705cfSriastradh tmp)) 193503b705cfSriastradh return true; 193603b705cfSriastradh break; 193703b705cfSriastradh } 193803b705cfSriastradh 193903b705cfSriastradh if (mask) { 194003b705cfSriastradh if (!reuse_source(sna, 194103b705cfSriastradh src, &tmp->src, src_x, src_y, 194203b705cfSriastradh mask, &tmp->mask, mask_x, mask_y)) { 194303b705cfSriastradh switch (gen2_composite_picture(sna, mask, &tmp->mask, 194403b705cfSriastradh mask_x, mask_y, 194503b705cfSriastradh width, height, 194603b705cfSriastradh dst_x, dst_y, 194703b705cfSriastradh dst->polyMode == PolyModePrecise)) { 194803b705cfSriastradh case -1: 194903b705cfSriastradh DBG(("%s: fallback -- unable to prepare mask\n", 195003b705cfSriastradh __FUNCTION__)); 195103b705cfSriastradh goto cleanup_src; 195203b705cfSriastradh case 0: 195303b705cfSriastradh gen2_composite_solid_init(sna, &tmp->mask, 0); 195403b705cfSriastradh case 1: 195503b705cfSriastradh break; 195603b705cfSriastradh } 195703b705cfSriastradh } 195803b705cfSriastradh 195903b705cfSriastradh if (mask->componentAlpha && PICT_FORMAT_RGB(mask->format)) { 196003b705cfSriastradh /* Check if it's component alpha that relies on a source alpha 196103b705cfSriastradh * and on the source value. We can only get one of those 196203b705cfSriastradh * into the single source value that we get to blend with. 196303b705cfSriastradh */ 196403b705cfSriastradh tmp->has_component_alpha = true; 196503b705cfSriastradh if (gen2_blend_op[op].src_alpha && 196603b705cfSriastradh (gen2_blend_op[op].src_blend != BLENDFACTOR_ZERO)) { 196703b705cfSriastradh if (op != PictOpOver) { 196803b705cfSriastradh DBG(("%s: fallback -- unsupported CA blend (src_blend=%d)\n", 196903b705cfSriastradh __FUNCTION__, 197003b705cfSriastradh gen2_blend_op[op].src_blend)); 197103b705cfSriastradh goto cleanup_src; 197203b705cfSriastradh } 197303b705cfSriastradh 197403b705cfSriastradh tmp->need_magic_ca_pass = true; 197503b705cfSriastradh tmp->op = PictOpOutReverse; 197603b705cfSriastradh } 197703b705cfSriastradh } 197803b705cfSriastradh 197903b705cfSriastradh /* convert solid to a texture (pure convenience) */ 198003b705cfSriastradh if (tmp->mask.is_solid && tmp->src.is_solid) { 198103b705cfSriastradh assert(tmp->mask.is_affine); 198203b705cfSriastradh tmp->mask.bo = sna_render_get_solid(sna, tmp->mask.u.gen2.pixel); 198303b705cfSriastradh if (!tmp->mask.bo) 198403b705cfSriastradh goto cleanup_src; 198503b705cfSriastradh } 198603b705cfSriastradh } 198703b705cfSriastradh 198803b705cfSriastradh tmp->floats_per_vertex = 2; 198903b705cfSriastradh if (!tmp->src.is_solid) 199003b705cfSriastradh tmp->floats_per_vertex += tmp->src.is_affine ? 2 : 3; 199103b705cfSriastradh if (tmp->mask.bo) 199203b705cfSriastradh tmp->floats_per_vertex += tmp->mask.is_affine ? 2 : 3; 199303b705cfSriastradh tmp->floats_per_rect = 3*tmp->floats_per_vertex; 199403b705cfSriastradh 199503b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive; 199603b705cfSriastradh if (tmp->mask.bo) { 199703b705cfSriastradh if (tmp->mask.transform == NULL) { 199803b705cfSriastradh if (tmp->src.is_solid) { 199903b705cfSriastradh assert(tmp->floats_per_rect == 12); 200003b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 200103b705cfSriastradh if (sna->cpu_features & SSE2) { 200203b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_constant_identity_mask__sse2; 200303b705cfSriastradh } else 200403b705cfSriastradh#endif 200503b705cfSriastradh { 200603b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_constant_identity_mask; 200703b705cfSriastradh } 200803b705cfSriastradh } 200903b705cfSriastradh } 201003b705cfSriastradh } else { 201103b705cfSriastradh if (tmp->src.is_solid) { 201203b705cfSriastradh assert(tmp->floats_per_rect == 6); 201303b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 201403b705cfSriastradh if (sna->cpu_features & SSE2) { 201503b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_constant__sse2; 201603b705cfSriastradh } else 201703b705cfSriastradh#endif 201803b705cfSriastradh { 201903b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_constant; 202003b705cfSriastradh } 202103b705cfSriastradh } else if (tmp->src.is_linear) { 202203b705cfSriastradh assert(tmp->floats_per_rect == 12); 202303b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 202403b705cfSriastradh if (sna->cpu_features & SSE2) { 202503b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_linear__sse2; 202603b705cfSriastradh } else 202703b705cfSriastradh#endif 202803b705cfSriastradh { 202903b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_linear; 203003b705cfSriastradh } 203103b705cfSriastradh } else if (tmp->src.transform == NULL) { 203203b705cfSriastradh assert(tmp->floats_per_rect == 12); 203303b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 203403b705cfSriastradh if (sna->cpu_features & SSE2) { 203503b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_identity__sse2; 203603b705cfSriastradh } else 203703b705cfSriastradh#endif 203803b705cfSriastradh { 203903b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_identity; 204003b705cfSriastradh } 204103b705cfSriastradh } else if (tmp->src.is_affine) { 204203b705cfSriastradh assert(tmp->floats_per_rect == 12); 204303b705cfSriastradh tmp->src.scale[0] /= tmp->src.transform->matrix[2][2]; 204403b705cfSriastradh tmp->src.scale[1] /= tmp->src.transform->matrix[2][2]; 204503b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 204603b705cfSriastradh if (sna->cpu_features & SSE2) { 204703b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_affine__sse2; 204803b705cfSriastradh } else 204903b705cfSriastradh#endif 205003b705cfSriastradh { 205103b705cfSriastradh tmp->prim_emit = gen2_emit_composite_primitive_affine; 205203b705cfSriastradh } 205303b705cfSriastradh } 205403b705cfSriastradh } 205503b705cfSriastradh 205603b705cfSriastradh tmp->blt = gen2_render_composite_blt; 205703b705cfSriastradh tmp->box = gen2_render_composite_box; 205803b705cfSriastradh tmp->boxes = gen2_render_composite_boxes; 205903b705cfSriastradh tmp->done = gen2_render_composite_done; 206003b705cfSriastradh 206103b705cfSriastradh if (!kgem_check_bo(&sna->kgem, 206203b705cfSriastradh tmp->dst.bo, tmp->src.bo, tmp->mask.bo, 206303b705cfSriastradh NULL)) { 206403b705cfSriastradh kgem_submit(&sna->kgem); 206503b705cfSriastradh if (!kgem_check_bo(&sna->kgem, 206603b705cfSriastradh tmp->dst.bo, tmp->src.bo, tmp->mask.bo, 206703b705cfSriastradh NULL)) { 206803b705cfSriastradh DBG(("%s: fallback, operation does not fit into GTT\n", 206903b705cfSriastradh __FUNCTION__)); 207003b705cfSriastradh goto cleanup_mask; 207103b705cfSriastradh } 207203b705cfSriastradh } 207303b705cfSriastradh 207403b705cfSriastradh gen2_emit_composite_state(sna, tmp); 207503b705cfSriastradh return true; 207603b705cfSriastradh 207703b705cfSriastradhcleanup_mask: 207842542f5fSchristos if (tmp->mask.bo) { 207903b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->mask.bo); 208042542f5fSchristos tmp->mask.bo = NULL; 208142542f5fSchristos } 208203b705cfSriastradhcleanup_src: 208342542f5fSchristos if (tmp->src.bo) { 208403b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->src.bo); 208542542f5fSchristos tmp->src.bo = NULL; 208642542f5fSchristos } 208703b705cfSriastradhcleanup_dst: 208842542f5fSchristos if (tmp->redirect.real_bo) { 208903b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->dst.bo); 209042542f5fSchristos tmp->redirect.real_bo = NULL; 209142542f5fSchristos } 209242542f5fSchristosfallback: 209342542f5fSchristos return (mask == NULL && 209442542f5fSchristos sna_blt_composite(sna, op, src, dst, 209542542f5fSchristos src_x, src_y, 209642542f5fSchristos dst_x, dst_y, 209742542f5fSchristos width, height, 209842542f5fSchristos flags | COMPOSITE_FALLBACK, tmp)); 209903b705cfSriastradh} 210003b705cfSriastradh 210103b705cfSriastradhfastcall static void 210203b705cfSriastradhgen2_emit_composite_spans_primitive_constant(struct sna *sna, 210303b705cfSriastradh const struct sna_composite_spans_op *op, 210403b705cfSriastradh const BoxRec *box, 210503b705cfSriastradh float opacity) 210603b705cfSriastradh{ 210703b705cfSriastradh float *v = (float *)sna->kgem.batch + sna->kgem.nbatch; 210803b705cfSriastradh uint32_t alpha = (uint8_t)(255 * opacity) << 24; 210903b705cfSriastradh sna->kgem.nbatch += 9; 211003b705cfSriastradh 211103b705cfSriastradh v[0] = op->base.dst.x + box->x2; 211203b705cfSriastradh v[1] = op->base.dst.y + box->y2; 211303b705cfSriastradh *((uint32_t *)v + 2) = alpha; 211403b705cfSriastradh 211503b705cfSriastradh v[3] = op->base.dst.x + box->x1; 211603b705cfSriastradh v[4] = v[1]; 211703b705cfSriastradh *((uint32_t *)v + 5) = alpha; 211803b705cfSriastradh 211903b705cfSriastradh v[6] = v[3]; 212003b705cfSriastradh v[7] = op->base.dst.y + box->y1; 212103b705cfSriastradh *((uint32_t *)v + 8) = alpha; 212203b705cfSriastradh} 212303b705cfSriastradh 212403b705cfSriastradhfastcall static void 212503b705cfSriastradhgen2_emit_composite_spans_primitive_linear(struct sna *sna, 212603b705cfSriastradh const struct sna_composite_spans_op *op, 212703b705cfSriastradh const BoxRec *box, 212803b705cfSriastradh float opacity) 212903b705cfSriastradh{ 213003b705cfSriastradh union { 213103b705cfSriastradh float f; 213203b705cfSriastradh uint32_t u; 213303b705cfSriastradh } alpha; 213403b705cfSriastradh 213503b705cfSriastradh alpha.u = (uint8_t)(255 * opacity) << 24; 213603b705cfSriastradh 213703b705cfSriastradh gen2_emit_composite_dstcoord(sna, 213803b705cfSriastradh op->base.dst.x + box->x2, 213903b705cfSriastradh op->base.dst.y + box->y2); 214003b705cfSriastradh VERTEX(alpha.f); 214103b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, box->x2, box->y2); 214203b705cfSriastradh 214303b705cfSriastradh gen2_emit_composite_dstcoord(sna, 214403b705cfSriastradh op->base.dst.x + box->x1, 214503b705cfSriastradh op->base.dst.y + box->y2); 214603b705cfSriastradh VERTEX(alpha.f); 214703b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, box->x1, box->y2); 214803b705cfSriastradh 214903b705cfSriastradh gen2_emit_composite_dstcoord(sna, 215003b705cfSriastradh op->base.dst.x + box->x1, 215103b705cfSriastradh op->base.dst.y + box->y1); 215203b705cfSriastradh VERTEX(alpha.f); 215303b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, box->x1, box->y1); 215403b705cfSriastradh} 215503b705cfSriastradh 215603b705cfSriastradhfastcall static void 215703b705cfSriastradhgen2_emit_composite_spans_primitive_identity_source(struct sna *sna, 215803b705cfSriastradh const struct sna_composite_spans_op *op, 215903b705cfSriastradh const BoxRec *box, 216003b705cfSriastradh float opacity) 216103b705cfSriastradh{ 216203b705cfSriastradh float *v = (float *)sna->kgem.batch + sna->kgem.nbatch; 216303b705cfSriastradh uint32_t alpha = (uint8_t)(255 * opacity) << 24; 216403b705cfSriastradh sna->kgem.nbatch += 15; 216503b705cfSriastradh 216603b705cfSriastradh v[0] = op->base.dst.x + box->x2; 216703b705cfSriastradh v[1] = op->base.dst.y + box->y2; 216803b705cfSriastradh *((uint32_t *)v + 2) = alpha; 216903b705cfSriastradh v[3] = (op->base.src.offset[0] + box->x2) * op->base.src.scale[0]; 217003b705cfSriastradh v[4] = (op->base.src.offset[1] + box->y2) * op->base.src.scale[1]; 217103b705cfSriastradh 217203b705cfSriastradh v[5] = op->base.dst.x + box->x1; 217303b705cfSriastradh v[6] = v[1]; 217403b705cfSriastradh *((uint32_t *)v + 7) = alpha; 217503b705cfSriastradh v[8] = (op->base.src.offset[0] + box->x1) * op->base.src.scale[0]; 217603b705cfSriastradh v[9] = v[4]; 217703b705cfSriastradh 217803b705cfSriastradh v[10] = v[5]; 217903b705cfSriastradh v[11] = op->base.dst.y + box->y1; 218003b705cfSriastradh *((uint32_t *)v + 12) = alpha; 218103b705cfSriastradh v[13] = v[8]; 218203b705cfSriastradh v[14] = (op->base.src.offset[1] + box->y1) * op->base.src.scale[1]; 218303b705cfSriastradh} 218403b705cfSriastradh 218503b705cfSriastradhfastcall static void 218603b705cfSriastradhgen2_emit_composite_spans_primitive_affine_source(struct sna *sna, 218703b705cfSriastradh const struct sna_composite_spans_op *op, 218803b705cfSriastradh const BoxRec *box, 218903b705cfSriastradh float opacity) 219003b705cfSriastradh{ 219103b705cfSriastradh PictTransform *transform = op->base.src.transform; 219203b705cfSriastradh uint32_t alpha = (uint8_t)(255 * opacity) << 24; 219303b705cfSriastradh float *v; 219403b705cfSriastradh 219503b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 219603b705cfSriastradh sna->kgem.nbatch += 15; 219703b705cfSriastradh 219803b705cfSriastradh v[0] = op->base.dst.x + box->x2; 219903b705cfSriastradh v[6] = v[1] = op->base.dst.y + box->y2; 220003b705cfSriastradh v[10] = v[5] = op->base.dst.x + box->x1; 220103b705cfSriastradh v[11] = op->base.dst.y + box->y1; 220203b705cfSriastradh *((uint32_t *)v + 2) = alpha; 220303b705cfSriastradh *((uint32_t *)v + 7) = alpha; 220403b705cfSriastradh *((uint32_t *)v + 12) = alpha; 220503b705cfSriastradh 220603b705cfSriastradh _sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x2, 220703b705cfSriastradh (int)op->base.src.offset[1] + box->y2, 220803b705cfSriastradh transform, op->base.src.scale, 220903b705cfSriastradh &v[3], &v[4]); 221003b705cfSriastradh 221103b705cfSriastradh _sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x1, 221203b705cfSriastradh (int)op->base.src.offset[1] + box->y2, 221303b705cfSriastradh transform, op->base.src.scale, 221403b705cfSriastradh &v[8], &v[9]); 221503b705cfSriastradh 221603b705cfSriastradh _sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x1, 221703b705cfSriastradh (int)op->base.src.offset[1] + box->y1, 221803b705cfSriastradh transform, op->base.src.scale, 221903b705cfSriastradh &v[13], &v[14]); 222003b705cfSriastradh} 222103b705cfSriastradh 222203b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 222303b705cfSriastradhsse2 fastcall static void 222403b705cfSriastradhgen2_emit_composite_spans_primitive_constant__sse2(struct sna *sna, 222503b705cfSriastradh const struct sna_composite_spans_op *op, 222603b705cfSriastradh const BoxRec *box, 222703b705cfSriastradh float opacity) 222803b705cfSriastradh{ 222903b705cfSriastradh float *v = (float *)sna->kgem.batch + sna->kgem.nbatch; 223003b705cfSriastradh uint32_t alpha = (uint8_t)(255 * opacity) << 24; 223103b705cfSriastradh sna->kgem.nbatch += 9; 223203b705cfSriastradh 223303b705cfSriastradh v[0] = op->base.dst.x + box->x2; 223403b705cfSriastradh v[1] = op->base.dst.y + box->y2; 223503b705cfSriastradh *((uint32_t *)v + 2) = alpha; 223603b705cfSriastradh 223703b705cfSriastradh v[3] = op->base.dst.x + box->x1; 223803b705cfSriastradh v[4] = v[1]; 223903b705cfSriastradh *((uint32_t *)v + 5) = alpha; 224003b705cfSriastradh 224103b705cfSriastradh v[6] = v[3]; 224203b705cfSriastradh v[7] = op->base.dst.y + box->y1; 224303b705cfSriastradh *((uint32_t *)v + 8) = alpha; 224403b705cfSriastradh} 224503b705cfSriastradh 224603b705cfSriastradhsse2 fastcall static void 224703b705cfSriastradhgen2_emit_composite_spans_primitive_linear__sse2(struct sna *sna, 224803b705cfSriastradh const struct sna_composite_spans_op *op, 224903b705cfSriastradh const BoxRec *box, 225003b705cfSriastradh float opacity) 225103b705cfSriastradh{ 225203b705cfSriastradh union { 225303b705cfSriastradh float f; 225403b705cfSriastradh uint32_t u; 225503b705cfSriastradh } alpha; 225603b705cfSriastradh 225703b705cfSriastradh alpha.u = (uint8_t)(255 * opacity) << 24; 225803b705cfSriastradh 225903b705cfSriastradh gen2_emit_composite_dstcoord(sna, 226003b705cfSriastradh op->base.dst.x + box->x2, 226103b705cfSriastradh op->base.dst.y + box->y2); 226203b705cfSriastradh VERTEX(alpha.f); 226303b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, box->x2, box->y2); 226403b705cfSriastradh 226503b705cfSriastradh gen2_emit_composite_dstcoord(sna, 226603b705cfSriastradh op->base.dst.x + box->x1, 226703b705cfSriastradh op->base.dst.y + box->y2); 226803b705cfSriastradh VERTEX(alpha.f); 226903b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, box->x1, box->y2); 227003b705cfSriastradh 227103b705cfSriastradh gen2_emit_composite_dstcoord(sna, 227203b705cfSriastradh op->base.dst.x + box->x1, 227303b705cfSriastradh op->base.dst.y + box->y1); 227403b705cfSriastradh VERTEX(alpha.f); 227503b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, box->x1, box->y1); 227603b705cfSriastradh} 227703b705cfSriastradh 227803b705cfSriastradhsse2 fastcall static void 227903b705cfSriastradhgen2_emit_composite_spans_primitive_identity_source__sse2(struct sna *sna, 228003b705cfSriastradh const struct sna_composite_spans_op *op, 228103b705cfSriastradh const BoxRec *box, 228203b705cfSriastradh float opacity) 228303b705cfSriastradh{ 228403b705cfSriastradh float *v = (float *)sna->kgem.batch + sna->kgem.nbatch; 228503b705cfSriastradh uint32_t alpha = (uint8_t)(255 * opacity) << 24; 228603b705cfSriastradh sna->kgem.nbatch += 15; 228703b705cfSriastradh 228803b705cfSriastradh v[0] = op->base.dst.x + box->x2; 228903b705cfSriastradh v[1] = op->base.dst.y + box->y2; 229003b705cfSriastradh *((uint32_t *)v + 2) = alpha; 229103b705cfSriastradh v[3] = (op->base.src.offset[0] + box->x2) * op->base.src.scale[0]; 229203b705cfSriastradh v[4] = (op->base.src.offset[1] + box->y2) * op->base.src.scale[1]; 229303b705cfSriastradh 229403b705cfSriastradh v[5] = op->base.dst.x + box->x1; 229503b705cfSriastradh v[6] = v[1]; 229603b705cfSriastradh *((uint32_t *)v + 7) = alpha; 229703b705cfSriastradh v[8] = (op->base.src.offset[0] + box->x1) * op->base.src.scale[0]; 229803b705cfSriastradh v[9] = v[4]; 229903b705cfSriastradh 230003b705cfSriastradh v[10] = v[5]; 230103b705cfSriastradh v[11] = op->base.dst.y + box->y1; 230203b705cfSriastradh *((uint32_t *)v + 12) = alpha; 230303b705cfSriastradh v[13] = v[8]; 230403b705cfSriastradh v[14] = (op->base.src.offset[1] + box->y1) * op->base.src.scale[1]; 230503b705cfSriastradh} 230603b705cfSriastradh 230703b705cfSriastradhsse2 fastcall static void 230803b705cfSriastradhgen2_emit_composite_spans_primitive_affine_source__sse2(struct sna *sna, 230903b705cfSriastradh const struct sna_composite_spans_op *op, 231003b705cfSriastradh const BoxRec *box, 231103b705cfSriastradh float opacity) 231203b705cfSriastradh{ 231303b705cfSriastradh PictTransform *transform = op->base.src.transform; 231403b705cfSriastradh uint32_t alpha = (uint8_t)(255 * opacity) << 24; 231503b705cfSriastradh float *v; 231603b705cfSriastradh 231703b705cfSriastradh v = (float *)sna->kgem.batch + sna->kgem.nbatch; 231803b705cfSriastradh sna->kgem.nbatch += 15; 231903b705cfSriastradh 232003b705cfSriastradh v[0] = op->base.dst.x + box->x2; 232103b705cfSriastradh v[6] = v[1] = op->base.dst.y + box->y2; 232203b705cfSriastradh v[10] = v[5] = op->base.dst.x + box->x1; 232303b705cfSriastradh v[11] = op->base.dst.y + box->y1; 232403b705cfSriastradh *((uint32_t *)v + 2) = alpha; 232503b705cfSriastradh *((uint32_t *)v + 7) = alpha; 232603b705cfSriastradh *((uint32_t *)v + 12) = alpha; 232703b705cfSriastradh 232803b705cfSriastradh _sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x2, 232903b705cfSriastradh (int)op->base.src.offset[1] + box->y2, 233003b705cfSriastradh transform, op->base.src.scale, 233103b705cfSriastradh &v[3], &v[4]); 233203b705cfSriastradh 233303b705cfSriastradh _sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x1, 233403b705cfSriastradh (int)op->base.src.offset[1] + box->y2, 233503b705cfSriastradh transform, op->base.src.scale, 233603b705cfSriastradh &v[8], &v[9]); 233703b705cfSriastradh 233803b705cfSriastradh _sna_get_transformed_scaled((int)op->base.src.offset[0] + box->x1, 233903b705cfSriastradh (int)op->base.src.offset[1] + box->y1, 234003b705cfSriastradh transform, op->base.src.scale, 234103b705cfSriastradh &v[13], &v[14]); 234203b705cfSriastradh} 234303b705cfSriastradh#endif 234403b705cfSriastradh 234503b705cfSriastradhstatic void 234603b705cfSriastradhgen2_emit_composite_spans_vertex(struct sna *sna, 234703b705cfSriastradh const struct sna_composite_spans_op *op, 234803b705cfSriastradh int16_t x, int16_t y, 234903b705cfSriastradh float opacity) 235003b705cfSriastradh{ 235103b705cfSriastradh gen2_emit_composite_dstcoord(sna, x + op->base.dst.x, y + op->base.dst.y); 235203b705cfSriastradh BATCH((uint8_t)(opacity * 255) << 24); 235303b705cfSriastradh assert(!op->base.src.is_solid); 235403b705cfSriastradh if (op->base.src.is_linear) 235503b705cfSriastradh gen2_emit_composite_linear(sna, &op->base.src, x, y); 235603b705cfSriastradh else 235703b705cfSriastradh gen2_emit_composite_texcoord(sna, &op->base.src, x, y); 235803b705cfSriastradh} 235903b705cfSriastradh 236003b705cfSriastradhfastcall static void 236103b705cfSriastradhgen2_emit_composite_spans_primitive(struct sna *sna, 236203b705cfSriastradh const struct sna_composite_spans_op *op, 236303b705cfSriastradh const BoxRec *box, 236403b705cfSriastradh float opacity) 236503b705cfSriastradh{ 236603b705cfSriastradh gen2_emit_composite_spans_vertex(sna, op, box->x2, box->y2, opacity); 236703b705cfSriastradh gen2_emit_composite_spans_vertex(sna, op, box->x1, box->y2, opacity); 236803b705cfSriastradh gen2_emit_composite_spans_vertex(sna, op, box->x1, box->y1, opacity); 236903b705cfSriastradh} 237003b705cfSriastradh 237103b705cfSriastradhstatic void 237203b705cfSriastradhgen2_emit_spans_pipeline(struct sna *sna, 237303b705cfSriastradh const struct sna_composite_spans_op *op) 237403b705cfSriastradh{ 237503b705cfSriastradh uint32_t cblend, ablend; 237603b705cfSriastradh uint32_t unwind; 237703b705cfSriastradh 237803b705cfSriastradh cblend = 237903b705cfSriastradh TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_MODULATE | 238003b705cfSriastradh TB0C_ARG1_SEL_DIFFUSE | TB0C_ARG1_REPLICATE_ALPHA | 238103b705cfSriastradh TB0C_OUTPUT_WRITE_CURRENT; 238203b705cfSriastradh ablend = 238303b705cfSriastradh TB0A_RESULT_SCALE_1X | TB0A_OP_MODULATE | 238403b705cfSriastradh TB0A_ARG1_SEL_DIFFUSE | 238503b705cfSriastradh TB0A_OUTPUT_WRITE_CURRENT; 238603b705cfSriastradh 238703b705cfSriastradh if (op->base.src.is_solid) { 238803b705cfSriastradh ablend |= TB0A_ARG2_SEL_SPECULAR; 238903b705cfSriastradh cblend |= TB0C_ARG2_SEL_SPECULAR; 239003b705cfSriastradh if (op->base.dst.format == PICT_a8) 239103b705cfSriastradh cblend |= TB0C_ARG2_REPLICATE_ALPHA; 239203b705cfSriastradh } else if (op->base.dst.format == PICT_a8) { 239303b705cfSriastradh ablend |= TB0A_ARG2_SEL_TEXEL0; 239403b705cfSriastradh cblend |= TB0C_ARG2_SEL_TEXEL0 | TB0C_ARG2_REPLICATE_ALPHA; 239503b705cfSriastradh } else { 239603b705cfSriastradh if (PICT_FORMAT_RGB(op->base.src.pict_format) != 0) 239703b705cfSriastradh cblend |= TB0C_ARG2_SEL_TEXEL0; 239803b705cfSriastradh else 239903b705cfSriastradh cblend |= TB0C_ARG2_SEL_ONE | TB0C_ARG2_INVERT; 240003b705cfSriastradh 240103b705cfSriastradh if (op->base.src.is_opaque) 240203b705cfSriastradh ablend |= TB0A_ARG2_SEL_ONE; 240303b705cfSriastradh else 240403b705cfSriastradh ablend |= TB0A_ARG2_SEL_TEXEL0; 240503b705cfSriastradh } 240603b705cfSriastradh 240703b705cfSriastradh unwind = sna->kgem.nbatch; 240803b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 240903b705cfSriastradh LOAD_TEXTURE_BLEND_STAGE(0) | 1); 241003b705cfSriastradh BATCH(cblend); 241103b705cfSriastradh BATCH(ablend); 241203b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1, 241303b705cfSriastradh sna->kgem.batch + unwind + 1, 241403b705cfSriastradh 2 * sizeof(uint32_t)) == 0) 241503b705cfSriastradh sna->kgem.nbatch = unwind; 241603b705cfSriastradh else 241703b705cfSriastradh sna->render_state.gen2.ls2 = unwind; 241803b705cfSriastradh} 241903b705cfSriastradh 242003b705cfSriastradhstatic void gen2_emit_composite_spans_state(struct sna *sna, 242103b705cfSriastradh const struct sna_composite_spans_op *op) 242203b705cfSriastradh{ 242303b705cfSriastradh uint32_t unwind; 242403b705cfSriastradh 242503b705cfSriastradh gen2_get_batch(sna, &op->base); 242603b705cfSriastradh gen2_emit_target(sna, &op->base); 242703b705cfSriastradh 242803b705cfSriastradh unwind = sna->kgem.nbatch; 242903b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 243003b705cfSriastradh I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2); 243103b705cfSriastradh BATCH(!op->base.src.is_solid << 12); 243203b705cfSriastradh BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY | S3_DIFFUSE_PRESENT); 243303b705cfSriastradh BATCH(gen2_get_blend_cntl(op->base.op, false, op->base.dst.format)); 243403b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1, 243503b705cfSriastradh sna->kgem.batch + unwind + 1, 243603b705cfSriastradh 3 * sizeof(uint32_t)) == 0) 243703b705cfSriastradh sna->kgem.nbatch = unwind; 243803b705cfSriastradh else 243903b705cfSriastradh sna->render_state.gen2.ls1 = unwind; 244003b705cfSriastradh 244103b705cfSriastradh gen2_disable_logic_op(sna); 244203b705cfSriastradh gen2_emit_spans_pipeline(sna, op); 244303b705cfSriastradh 244403b705cfSriastradh if (op->base.src.is_solid) { 244503b705cfSriastradh if (op->base.src.u.gen2.pixel != sna->render_state.gen2.specular) { 244603b705cfSriastradh BATCH(_3DSTATE_DFLT_SPECULAR_CMD); 244703b705cfSriastradh BATCH(op->base.src.u.gen2.pixel); 244803b705cfSriastradh sna->render_state.gen2.specular = op->base.src.u.gen2.pixel; 244903b705cfSriastradh } 245003b705cfSriastradh } else { 245103b705cfSriastradh uint32_t v =_3DSTATE_VERTEX_FORMAT_2_CMD | 245203b705cfSriastradh (op->base.src.is_affine ? TEXCOORDFMT_2D : TEXCOORDFMT_3D); 245303b705cfSriastradh if (sna->render_state.gen2.vft != v) { 245403b705cfSriastradh BATCH(v); 245503b705cfSriastradh sna->render_state.gen2.vft = v; 245603b705cfSriastradh } 245703b705cfSriastradh gen2_emit_texture(sna, &op->base.src, 0); 245803b705cfSriastradh } 245903b705cfSriastradh} 246003b705cfSriastradh 246103b705cfSriastradhfastcall static void 246203b705cfSriastradhgen2_render_composite_spans_box(struct sna *sna, 246303b705cfSriastradh const struct sna_composite_spans_op *op, 246403b705cfSriastradh const BoxRec *box, float opacity) 246503b705cfSriastradh{ 246603b705cfSriastradh DBG(("%s: src=+(%d, %d), opacity=%f, dst=+(%d, %d), box=(%d, %d) x (%d, %d)\n", 246703b705cfSriastradh __FUNCTION__, 246803b705cfSriastradh op->base.src.offset[0], op->base.src.offset[1], 246903b705cfSriastradh opacity, 247003b705cfSriastradh op->base.dst.x, op->base.dst.y, 247103b705cfSriastradh box->x1, box->y1, 247203b705cfSriastradh box->x2 - box->x1, 247303b705cfSriastradh box->y2 - box->y1)); 247403b705cfSriastradh 247503b705cfSriastradh if (gen2_get_rectangles(sna, &op->base, 1) == 0) { 247603b705cfSriastradh gen2_emit_composite_spans_state(sna, op); 247703b705cfSriastradh gen2_get_rectangles(sna, &op->base, 1); 247803b705cfSriastradh } 247903b705cfSriastradh 248003b705cfSriastradh op->prim_emit(sna, op, box, opacity); 248103b705cfSriastradh} 248203b705cfSriastradh 248303b705cfSriastradhstatic void 248403b705cfSriastradhgen2_render_composite_spans_boxes(struct sna *sna, 248503b705cfSriastradh const struct sna_composite_spans_op *op, 248603b705cfSriastradh const BoxRec *box, int nbox, 248703b705cfSriastradh float opacity) 248803b705cfSriastradh{ 248903b705cfSriastradh DBG(("%s: nbox=%d, src=+(%d, %d), opacity=%f, dst=+(%d, %d)\n", 249003b705cfSriastradh __FUNCTION__, nbox, 249103b705cfSriastradh op->base.src.offset[0], op->base.src.offset[1], 249203b705cfSriastradh opacity, 249303b705cfSriastradh op->base.dst.x, op->base.dst.y)); 249403b705cfSriastradh 249503b705cfSriastradh do { 249603b705cfSriastradh int nbox_this_time; 249703b705cfSriastradh 249803b705cfSriastradh nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox); 249903b705cfSriastradh if (nbox_this_time == 0) { 250003b705cfSriastradh gen2_emit_composite_spans_state(sna, op); 250103b705cfSriastradh nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox); 250203b705cfSriastradh } 250303b705cfSriastradh nbox -= nbox_this_time; 250403b705cfSriastradh 250503b705cfSriastradh do { 250603b705cfSriastradh DBG((" %s: (%d, %d) x (%d, %d)\n", __FUNCTION__, 250703b705cfSriastradh box->x1, box->y1, 250803b705cfSriastradh box->x2 - box->x1, 250903b705cfSriastradh box->y2 - box->y1)); 251003b705cfSriastradh 251103b705cfSriastradh op->prim_emit(sna, op, box++, opacity); 251203b705cfSriastradh } while (--nbox_this_time); 251303b705cfSriastradh } while (nbox); 251403b705cfSriastradh} 251503b705cfSriastradh 251603b705cfSriastradhfastcall static void 251703b705cfSriastradhgen2_render_composite_spans_done(struct sna *sna, 251803b705cfSriastradh const struct sna_composite_spans_op *op) 251903b705cfSriastradh{ 252003b705cfSriastradh DBG(("%s()\n", __FUNCTION__)); 252103b705cfSriastradh 252203b705cfSriastradh gen2_vertex_flush(sna, &op->base); 252303b705cfSriastradh 252403b705cfSriastradh if (op->base.src.bo) 252503b705cfSriastradh kgem_bo_destroy(&sna->kgem, op->base.src.bo); 252603b705cfSriastradh 252703b705cfSriastradh sna_render_composite_redirect_done(sna, &op->base); 252803b705cfSriastradh} 252903b705cfSriastradh 253003b705cfSriastradhstatic bool 253103b705cfSriastradhgen2_check_composite_spans(struct sna *sna, 253203b705cfSriastradh uint8_t op, PicturePtr src, PicturePtr dst, 253303b705cfSriastradh int16_t width, int16_t height, unsigned flags) 253403b705cfSriastradh{ 253503b705cfSriastradh if (op >= ARRAY_SIZE(gen2_blend_op)) 253603b705cfSriastradh return false; 253703b705cfSriastradh 253803b705cfSriastradh if (gen2_composite_fallback(sna, src, NULL, dst)) 253903b705cfSriastradh return false; 254003b705cfSriastradh 254103b705cfSriastradh if (need_tiling(sna, width, height)) { 254203b705cfSriastradh if (!is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) { 254303b705cfSriastradh DBG(("%s: fallback, tiled operation not on GPU\n", 254403b705cfSriastradh __FUNCTION__)); 254503b705cfSriastradh return false; 254603b705cfSriastradh } 254703b705cfSriastradh } 254803b705cfSriastradh 254903b705cfSriastradh return true; 255003b705cfSriastradh} 255103b705cfSriastradh 255203b705cfSriastradhstatic bool 255303b705cfSriastradhgen2_render_composite_spans(struct sna *sna, 255403b705cfSriastradh uint8_t op, 255503b705cfSriastradh PicturePtr src, 255603b705cfSriastradh PicturePtr dst, 255703b705cfSriastradh int16_t src_x, int16_t src_y, 255803b705cfSriastradh int16_t dst_x, int16_t dst_y, 255903b705cfSriastradh int16_t width, int16_t height, 256003b705cfSriastradh unsigned flags, 256103b705cfSriastradh struct sna_composite_spans_op *tmp) 256203b705cfSriastradh{ 256303b705cfSriastradh DBG(("%s(src=(%d, %d), dst=(%d, %d), size=(%d, %d))\n", __FUNCTION__, 256403b705cfSriastradh src_x, src_y, dst_x, dst_y, width, height)); 256503b705cfSriastradh 256603b705cfSriastradh assert(gen2_check_composite_spans(sna, op, src, dst, width, height, flags)); 256703b705cfSriastradh if (need_tiling(sna, width, height)) { 256803b705cfSriastradh DBG(("%s: tiling, operation (%dx%d) too wide for pipeline\n", 256903b705cfSriastradh __FUNCTION__, width, height)); 257003b705cfSriastradh return sna_tiling_composite_spans(op, src, dst, 257103b705cfSriastradh src_x, src_y, dst_x, dst_y, 257203b705cfSriastradh width, height, flags, tmp); 257303b705cfSriastradh } 257403b705cfSriastradh 257542542f5fSchristos tmp->base.op = op; 257642542f5fSchristos sna_render_composite_redirect_init(&tmp->base); 257703b705cfSriastradh if (!gen2_composite_set_target(sna, &tmp->base, dst, 257842542f5fSchristos dst_x, dst_y, width, height, 257942542f5fSchristos true)) { 258003b705cfSriastradh DBG(("%s: unable to set render target\n", 258103b705cfSriastradh __FUNCTION__)); 258203b705cfSriastradh return false; 258303b705cfSriastradh } 258403b705cfSriastradh 258503b705cfSriastradh switch (gen2_composite_picture(sna, src, &tmp->base.src, 258603b705cfSriastradh src_x, src_y, 258703b705cfSriastradh width, height, 258803b705cfSriastradh dst_x, dst_y, 258903b705cfSriastradh dst->polyMode == PolyModePrecise)) { 259003b705cfSriastradh case -1: 259103b705cfSriastradh goto cleanup_dst; 259203b705cfSriastradh case 0: 259303b705cfSriastradh gen2_composite_solid_init(sna, &tmp->base.src, 0); 259403b705cfSriastradh case 1: 259503b705cfSriastradh break; 259603b705cfSriastradh } 259742542f5fSchristos assert(tmp->base.src.bo || tmp->base.src.is_solid); 259803b705cfSriastradh 259903b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive; 260003b705cfSriastradh tmp->base.floats_per_vertex = 3; 260103b705cfSriastradh if (tmp->base.src.is_solid) { 260203b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 260303b705cfSriastradh if (sna->cpu_features & SSE2) { 260403b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_constant__sse2; 260503b705cfSriastradh } else 260603b705cfSriastradh#endif 260703b705cfSriastradh { 260803b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_constant; 260903b705cfSriastradh } 261003b705cfSriastradh } else if (tmp->base.src.is_linear) { 261103b705cfSriastradh tmp->base.floats_per_vertex += 2; 261203b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 261303b705cfSriastradh if (sna->cpu_features & SSE2) { 261403b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_linear__sse2; 261503b705cfSriastradh } else 261603b705cfSriastradh#endif 261703b705cfSriastradh { 261803b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_linear; 261903b705cfSriastradh } 262003b705cfSriastradh } else { 262103b705cfSriastradh assert(tmp->base.src.bo); 262203b705cfSriastradh tmp->base.floats_per_vertex += tmp->base.src.is_affine ? 2 : 3; 262303b705cfSriastradh if (tmp->base.src.transform == NULL) { 262403b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 262503b705cfSriastradh if (sna->cpu_features & SSE2) { 262603b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_identity_source__sse2; 262703b705cfSriastradh } else 262803b705cfSriastradh#endif 262903b705cfSriastradh { 263003b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_identity_source; 263103b705cfSriastradh } 263203b705cfSriastradh } else if (tmp->base.src.is_affine) { 263303b705cfSriastradh tmp->base.src.scale[0] /= tmp->base.src.transform->matrix[2][2]; 263403b705cfSriastradh tmp->base.src.scale[1] /= tmp->base.src.transform->matrix[2][2]; 263503b705cfSriastradh#if defined(sse2) && !defined(__x86_64__) 263603b705cfSriastradh if (sna->cpu_features & SSE2) { 263703b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_affine_source__sse2; 263803b705cfSriastradh } else 263903b705cfSriastradh#endif 264003b705cfSriastradh { 264103b705cfSriastradh tmp->prim_emit = gen2_emit_composite_spans_primitive_affine_source; 264203b705cfSriastradh } 264303b705cfSriastradh } 264403b705cfSriastradh } 264503b705cfSriastradh tmp->base.mask.bo = NULL; 264603b705cfSriastradh tmp->base.floats_per_rect = 3*tmp->base.floats_per_vertex; 264703b705cfSriastradh 264803b705cfSriastradh tmp->box = gen2_render_composite_spans_box; 264903b705cfSriastradh tmp->boxes = gen2_render_composite_spans_boxes; 265003b705cfSriastradh tmp->done = gen2_render_composite_spans_done; 265103b705cfSriastradh 265203b705cfSriastradh if (!kgem_check_bo(&sna->kgem, 265303b705cfSriastradh tmp->base.dst.bo, tmp->base.src.bo, 265403b705cfSriastradh NULL)) { 265503b705cfSriastradh kgem_submit(&sna->kgem); 265603b705cfSriastradh if (!kgem_check_bo(&sna->kgem, 265703b705cfSriastradh tmp->base.dst.bo, tmp->base.src.bo, 265803b705cfSriastradh NULL)) 265903b705cfSriastradh goto cleanup_src; 266003b705cfSriastradh } 266103b705cfSriastradh 266203b705cfSriastradh gen2_emit_composite_spans_state(sna, tmp); 266303b705cfSriastradh return true; 266403b705cfSriastradh 266503b705cfSriastradhcleanup_src: 266603b705cfSriastradh if (tmp->base.src.bo) 266703b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->base.src.bo); 266803b705cfSriastradhcleanup_dst: 266903b705cfSriastradh if (tmp->base.redirect.real_bo) 267003b705cfSriastradh kgem_bo_destroy(&sna->kgem, tmp->base.dst.bo); 267103b705cfSriastradh return false; 267203b705cfSriastradh} 267303b705cfSriastradh 267403b705cfSriastradhstatic void 267503b705cfSriastradhgen2_emit_fill_pipeline(struct sna *sna, const struct sna_composite_op *op) 267603b705cfSriastradh{ 267703b705cfSriastradh uint32_t blend, unwind; 267803b705cfSriastradh 267903b705cfSriastradh unwind = sna->kgem.nbatch; 268003b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 268103b705cfSriastradh LOAD_TEXTURE_BLEND_STAGE(0) | 1); 268203b705cfSriastradh 268303b705cfSriastradh blend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_ARG1 | 268403b705cfSriastradh TB0C_ARG1_SEL_DIFFUSE | 268503b705cfSriastradh TB0C_OUTPUT_WRITE_CURRENT; 268603b705cfSriastradh if (op->dst.format == PICT_a8) 268703b705cfSriastradh blend |= TB0C_ARG1_REPLICATE_ALPHA; 268803b705cfSriastradh BATCH(blend); 268903b705cfSriastradh 269003b705cfSriastradh BATCH(TB0A_RESULT_SCALE_1X | TB0A_OP_ARG1 | 269103b705cfSriastradh TB0A_ARG1_SEL_DIFFUSE | 269203b705cfSriastradh TB0A_OUTPUT_WRITE_CURRENT); 269303b705cfSriastradh 269403b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1, 269503b705cfSriastradh sna->kgem.batch + unwind + 1, 269603b705cfSriastradh 2 * sizeof(uint32_t)) == 0) 269703b705cfSriastradh sna->kgem.nbatch = unwind; 269803b705cfSriastradh else 269903b705cfSriastradh sna->render_state.gen2.ls2 = unwind; 270003b705cfSriastradh} 270103b705cfSriastradh 270203b705cfSriastradhstatic void gen2_emit_fill_composite_state(struct sna *sna, 270303b705cfSriastradh const struct sna_composite_op *op, 270403b705cfSriastradh uint32_t pixel) 270503b705cfSriastradh{ 270603b705cfSriastradh uint32_t ls1; 270703b705cfSriastradh 270803b705cfSriastradh gen2_get_batch(sna, op); 270903b705cfSriastradh gen2_emit_target(sna, op); 271003b705cfSriastradh 271103b705cfSriastradh ls1 = sna->kgem.nbatch; 271203b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 271303b705cfSriastradh I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2); 271403b705cfSriastradh BATCH(0); 271503b705cfSriastradh BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY); 271603b705cfSriastradh BATCH(gen2_get_blend_cntl(op->op, false, op->dst.format)); 271703b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1, 271803b705cfSriastradh sna->kgem.batch + ls1 + 1, 271903b705cfSriastradh 3 * sizeof(uint32_t)) == 0) 272003b705cfSriastradh sna->kgem.nbatch = ls1; 272103b705cfSriastradh else 272203b705cfSriastradh sna->render_state.gen2.ls1 = ls1; 272303b705cfSriastradh 272403b705cfSriastradh gen2_emit_fill_pipeline(sna, op); 272503b705cfSriastradh 272603b705cfSriastradh if (pixel != sna->render_state.gen2.diffuse) { 272703b705cfSriastradh BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); 272803b705cfSriastradh BATCH(pixel); 272903b705cfSriastradh sna->render_state.gen2.diffuse = pixel; 273003b705cfSriastradh } 273103b705cfSriastradh} 273203b705cfSriastradh 273303b705cfSriastradhstatic bool 273403b705cfSriastradhgen2_render_fill_boxes_try_blt(struct sna *sna, 273503b705cfSriastradh CARD8 op, PictFormat format, 273603b705cfSriastradh const xRenderColor *color, 273742542f5fSchristos const DrawableRec *dst, struct kgem_bo *dst_bo, 273803b705cfSriastradh const BoxRec *box, int n) 273903b705cfSriastradh{ 274003b705cfSriastradh uint8_t alu; 274103b705cfSriastradh uint32_t pixel; 274203b705cfSriastradh 274303b705cfSriastradh if (op > PictOpSrc) 274403b705cfSriastradh return false; 274503b705cfSriastradh 274603b705cfSriastradh if (op == PictOpClear) { 274703b705cfSriastradh alu = GXclear; 274803b705cfSriastradh pixel = 0; 274903b705cfSriastradh } else if (!sna_get_pixel_from_rgba(&pixel, 275003b705cfSriastradh color->red, 275103b705cfSriastradh color->green, 275203b705cfSriastradh color->blue, 275303b705cfSriastradh color->alpha, 275403b705cfSriastradh format)) 275503b705cfSriastradh return false; 275603b705cfSriastradh else 275703b705cfSriastradh alu = GXcopy; 275803b705cfSriastradh 275903b705cfSriastradh return sna_blt_fill_boxes(sna, alu, 276042542f5fSchristos dst_bo, dst->bitsPerPixel, 276103b705cfSriastradh pixel, box, n); 276203b705cfSriastradh} 276303b705cfSriastradh 276403b705cfSriastradhstatic bool 276503b705cfSriastradhgen2_render_fill_boxes(struct sna *sna, 276603b705cfSriastradh CARD8 op, 276703b705cfSriastradh PictFormat format, 276803b705cfSriastradh const xRenderColor *color, 276942542f5fSchristos const DrawableRec *dst, struct kgem_bo *dst_bo, 277003b705cfSriastradh const BoxRec *box, int n) 277103b705cfSriastradh{ 277203b705cfSriastradh struct sna_composite_op tmp; 277303b705cfSriastradh uint32_t pixel; 277403b705cfSriastradh 277503b705cfSriastradh if (op >= ARRAY_SIZE(gen2_blend_op)) { 277603b705cfSriastradh DBG(("%s: fallback due to unhandled blend op: %d\n", 277703b705cfSriastradh __FUNCTION__, op)); 277803b705cfSriastradh return false; 277903b705cfSriastradh } 278003b705cfSriastradh 278103b705cfSriastradh#if NO_FILL_BOXES 278203b705cfSriastradh return gen2_render_fill_boxes_try_blt(sna, op, format, color, 278303b705cfSriastradh dst, dst_bo, 278403b705cfSriastradh box, n); 278503b705cfSriastradh#endif 278603b705cfSriastradh if (gen2_render_fill_boxes_try_blt(sna, op, format, color, 278703b705cfSriastradh dst, dst_bo, 278803b705cfSriastradh box, n)) 278903b705cfSriastradh return true; 279003b705cfSriastradh 279103b705cfSriastradh 279203b705cfSriastradh DBG(("%s (op=%d, format=%x, color=(%04x,%04x,%04x, %04x))\n", 279303b705cfSriastradh __FUNCTION__, op, (int)format, 279403b705cfSriastradh color->red, color->green, color->blue, color->alpha)); 279503b705cfSriastradh 279642542f5fSchristos if (too_large(dst->width, dst->height) || 279703b705cfSriastradh dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH || 279803b705cfSriastradh !gen2_check_dst_format(format)) { 279903b705cfSriastradh DBG(("%s: try blt, too large or incompatible destination\n", 280003b705cfSriastradh __FUNCTION__)); 280103b705cfSriastradh if (!gen2_check_dst_format(format)) 280203b705cfSriastradh return false; 280303b705cfSriastradh 280403b705cfSriastradh assert(dst_bo->pitch >= 8); 280503b705cfSriastradh return sna_tiling_fill_boxes(sna, op, format, color, 280603b705cfSriastradh dst, dst_bo, box, n); 280703b705cfSriastradh } 280803b705cfSriastradh 280903b705cfSriastradh if (op == PictOpClear) 281003b705cfSriastradh pixel = 0; 281103b705cfSriastradh else if (!sna_get_pixel_from_rgba(&pixel, 281203b705cfSriastradh color->red, 281303b705cfSriastradh color->green, 281403b705cfSriastradh color->blue, 281503b705cfSriastradh color->alpha, 281603b705cfSriastradh PICT_a8r8g8b8)) 281703b705cfSriastradh return false; 281803b705cfSriastradh 281903b705cfSriastradh DBG(("%s: using shader for op=%d, format=%x, pixel=%x\n", 282003b705cfSriastradh __FUNCTION__, op, (int)format, pixel)); 282103b705cfSriastradh 282203b705cfSriastradh memset(&tmp, 0, sizeof(tmp)); 282303b705cfSriastradh tmp.op = op; 282442542f5fSchristos tmp.dst.pixmap = (PixmapPtr)dst; 282542542f5fSchristos tmp.dst.width = dst->width; 282642542f5fSchristos tmp.dst.height = dst->height; 282703b705cfSriastradh tmp.dst.format = format; 282803b705cfSriastradh tmp.dst.bo = dst_bo; 282903b705cfSriastradh tmp.floats_per_vertex = 2; 283003b705cfSriastradh tmp.floats_per_rect = 6; 283103b705cfSriastradh 283203b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) { 283303b705cfSriastradh kgem_submit(&sna->kgem); 283442542f5fSchristos if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) 283542542f5fSchristos return false; 283603b705cfSriastradh } 283703b705cfSriastradh 283803b705cfSriastradh gen2_emit_fill_composite_state(sna, &tmp, pixel); 283903b705cfSriastradh 284003b705cfSriastradh do { 284103b705cfSriastradh int n_this_time = gen2_get_rectangles(sna, &tmp, n); 284203b705cfSriastradh if (n_this_time == 0) { 284303b705cfSriastradh gen2_emit_fill_composite_state(sna, &tmp, pixel); 284403b705cfSriastradh n_this_time = gen2_get_rectangles(sna, &tmp, n); 284503b705cfSriastradh } 284603b705cfSriastradh n -= n_this_time; 284703b705cfSriastradh 284803b705cfSriastradh do { 284903b705cfSriastradh DBG((" (%d, %d), (%d, %d): %x\n", 285003b705cfSriastradh box->x1, box->y1, box->x2, box->y2, pixel)); 285103b705cfSriastradh VERTEX(box->x2); 285203b705cfSriastradh VERTEX(box->y2); 285303b705cfSriastradh VERTEX(box->x1); 285403b705cfSriastradh VERTEX(box->y2); 285503b705cfSriastradh VERTEX(box->x1); 285603b705cfSriastradh VERTEX(box->y1); 285703b705cfSriastradh box++; 285803b705cfSriastradh } while (--n_this_time); 285903b705cfSriastradh } while (n); 286003b705cfSriastradh 286103b705cfSriastradh gen2_vertex_flush(sna, &tmp); 286203b705cfSriastradh return true; 286303b705cfSriastradh} 286403b705cfSriastradh 286503b705cfSriastradhstatic void gen2_emit_fill_state(struct sna *sna, 286603b705cfSriastradh const struct sna_composite_op *op) 286703b705cfSriastradh{ 286803b705cfSriastradh uint32_t ls1; 286903b705cfSriastradh 287003b705cfSriastradh gen2_get_batch(sna, op); 287103b705cfSriastradh gen2_emit_target(sna, op); 287203b705cfSriastradh 287303b705cfSriastradh ls1 = sna->kgem.nbatch; 287403b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 287503b705cfSriastradh I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2); 287603b705cfSriastradh BATCH(0); 287703b705cfSriastradh BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY); 287803b705cfSriastradh BATCH(S8_ENABLE_COLOR_BUFFER_WRITE); 287903b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1, 288003b705cfSriastradh sna->kgem.batch + ls1 + 1, 288103b705cfSriastradh 3 * sizeof(uint32_t)) == 0) 288203b705cfSriastradh sna->kgem.nbatch = ls1; 288303b705cfSriastradh else 288403b705cfSriastradh sna->render_state.gen2.ls1 = ls1; 288503b705cfSriastradh 288603b705cfSriastradh gen2_enable_logic_op(sna, op->op); 288703b705cfSriastradh gen2_emit_fill_pipeline(sna, op); 288803b705cfSriastradh 288903b705cfSriastradh if (op->src.u.gen2.pixel != sna->render_state.gen2.diffuse) { 289003b705cfSriastradh BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); 289103b705cfSriastradh BATCH(op->src.u.gen2.pixel); 289203b705cfSriastradh sna->render_state.gen2.diffuse = op->src.u.gen2.pixel; 289303b705cfSriastradh } 289403b705cfSriastradh} 289503b705cfSriastradh 289603b705cfSriastradhstatic void 289703b705cfSriastradhgen2_render_fill_op_blt(struct sna *sna, 289803b705cfSriastradh const struct sna_fill_op *op, 289903b705cfSriastradh int16_t x, int16_t y, int16_t w, int16_t h) 290003b705cfSriastradh{ 290103b705cfSriastradh if (!gen2_get_rectangles(sna, &op->base, 1)) { 290203b705cfSriastradh gen2_emit_fill_state(sna, &op->base); 290303b705cfSriastradh gen2_get_rectangles(sna, &op->base, 1); 290403b705cfSriastradh } 290503b705cfSriastradh 290603b705cfSriastradh VERTEX(x+w); 290703b705cfSriastradh VERTEX(y+h); 290803b705cfSriastradh VERTEX(x); 290903b705cfSriastradh VERTEX(y+h); 291003b705cfSriastradh VERTEX(x); 291103b705cfSriastradh VERTEX(y); 291203b705cfSriastradh} 291303b705cfSriastradh 291403b705cfSriastradhfastcall static void 291503b705cfSriastradhgen2_render_fill_op_box(struct sna *sna, 291603b705cfSriastradh const struct sna_fill_op *op, 291703b705cfSriastradh const BoxRec *box) 291803b705cfSriastradh{ 291903b705cfSriastradh if (!gen2_get_rectangles(sna, &op->base, 1)) { 292003b705cfSriastradh gen2_emit_fill_state(sna, &op->base); 292103b705cfSriastradh gen2_get_rectangles(sna, &op->base, 1); 292203b705cfSriastradh } 292303b705cfSriastradh 292403b705cfSriastradh VERTEX(box->x2); 292503b705cfSriastradh VERTEX(box->y2); 292603b705cfSriastradh VERTEX(box->x1); 292703b705cfSriastradh VERTEX(box->y2); 292803b705cfSriastradh VERTEX(box->x1); 292903b705cfSriastradh VERTEX(box->y1); 293003b705cfSriastradh} 293103b705cfSriastradh 293203b705cfSriastradhfastcall static void 293303b705cfSriastradhgen2_render_fill_op_boxes(struct sna *sna, 293403b705cfSriastradh const struct sna_fill_op *op, 293503b705cfSriastradh const BoxRec *box, 293603b705cfSriastradh int nbox) 293703b705cfSriastradh{ 293803b705cfSriastradh DBG(("%s: (%d, %d),(%d, %d)... x %d\n", __FUNCTION__, 293903b705cfSriastradh box->x1, box->y1, box->x2, box->y2, nbox)); 294003b705cfSriastradh 294103b705cfSriastradh do { 294203b705cfSriastradh int nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox); 294303b705cfSriastradh if (nbox_this_time == 0) { 294403b705cfSriastradh gen2_emit_fill_state(sna, &op->base); 294503b705cfSriastradh nbox_this_time = gen2_get_rectangles(sna, &op->base, nbox); 294603b705cfSriastradh } 294703b705cfSriastradh nbox -= nbox_this_time; 294803b705cfSriastradh 294903b705cfSriastradh do { 295003b705cfSriastradh VERTEX(box->x2); 295103b705cfSriastradh VERTEX(box->y2); 295203b705cfSriastradh VERTEX(box->x1); 295303b705cfSriastradh VERTEX(box->y2); 295403b705cfSriastradh VERTEX(box->x1); 295503b705cfSriastradh VERTEX(box->y1); 295603b705cfSriastradh box++; 295703b705cfSriastradh } while (--nbox_this_time); 295803b705cfSriastradh } while (nbox); 295903b705cfSriastradh} 296003b705cfSriastradh 296103b705cfSriastradhstatic void 296203b705cfSriastradhgen2_render_fill_op_done(struct sna *sna, const struct sna_fill_op *op) 296303b705cfSriastradh{ 296403b705cfSriastradh gen2_vertex_flush(sna, &op->base); 296503b705cfSriastradh} 296603b705cfSriastradh 296703b705cfSriastradhstatic bool 296803b705cfSriastradhgen2_render_fill(struct sna *sna, uint8_t alu, 296903b705cfSriastradh PixmapPtr dst, struct kgem_bo *dst_bo, 297042542f5fSchristos uint32_t color, unsigned flags, 297103b705cfSriastradh struct sna_fill_op *tmp) 297203b705cfSriastradh{ 297303b705cfSriastradh#if NO_FILL 297403b705cfSriastradh return sna_blt_fill(sna, alu, 297503b705cfSriastradh dst_bo, dst->drawable.bitsPerPixel, 297603b705cfSriastradh color, 297703b705cfSriastradh tmp); 297803b705cfSriastradh#endif 297903b705cfSriastradh 298003b705cfSriastradh /* Prefer to use the BLT if already engaged */ 298103b705cfSriastradh if (sna_blt_fill(sna, alu, 298203b705cfSriastradh dst_bo, dst->drawable.bitsPerPixel, 298303b705cfSriastradh color, 298403b705cfSriastradh tmp)) 298503b705cfSriastradh return true; 298603b705cfSriastradh 298703b705cfSriastradh /* Must use the BLT if we can't RENDER... */ 298803b705cfSriastradh if (too_large(dst->drawable.width, dst->drawable.height) || 298903b705cfSriastradh dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH) 299003b705cfSriastradh return false; 299103b705cfSriastradh 299203b705cfSriastradh tmp->base.op = alu; 299303b705cfSriastradh tmp->base.dst.pixmap = dst; 299403b705cfSriastradh tmp->base.dst.width = dst->drawable.width; 299503b705cfSriastradh tmp->base.dst.height = dst->drawable.height; 299603b705cfSriastradh tmp->base.dst.format = sna_format_for_depth(dst->drawable.depth); 299703b705cfSriastradh tmp->base.dst.bo = dst_bo; 299803b705cfSriastradh tmp->base.dst.x = tmp->base.dst.y = 0; 299903b705cfSriastradh tmp->base.floats_per_vertex = 2; 300003b705cfSriastradh tmp->base.floats_per_rect = 6; 300103b705cfSriastradh 300203b705cfSriastradh tmp->base.src.u.gen2.pixel = 300303b705cfSriastradh sna_rgba_for_color(color, dst->drawable.depth); 300403b705cfSriastradh 300503b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, NULL)) { 300603b705cfSriastradh kgem_submit(&sna->kgem); 300703b705cfSriastradh return sna_blt_fill(sna, alu, 300803b705cfSriastradh dst_bo, dst->drawable.bitsPerPixel, 300903b705cfSriastradh color, 301003b705cfSriastradh tmp); 301103b705cfSriastradh } 301203b705cfSriastradh 301303b705cfSriastradh tmp->blt = gen2_render_fill_op_blt; 301403b705cfSriastradh tmp->box = gen2_render_fill_op_box; 301503b705cfSriastradh tmp->boxes = gen2_render_fill_op_boxes; 301642542f5fSchristos tmp->points = NULL; 301703b705cfSriastradh tmp->done = gen2_render_fill_op_done; 301803b705cfSriastradh 301903b705cfSriastradh gen2_emit_fill_state(sna, &tmp->base); 302003b705cfSriastradh return true; 302103b705cfSriastradh} 302203b705cfSriastradh 302303b705cfSriastradhstatic bool 302403b705cfSriastradhgen2_render_fill_one_try_blt(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo, 302503b705cfSriastradh uint32_t color, 302603b705cfSriastradh int16_t x1, int16_t y1, int16_t x2, int16_t y2, 302703b705cfSriastradh uint8_t alu) 302803b705cfSriastradh{ 302903b705cfSriastradh BoxRec box; 303003b705cfSriastradh 303103b705cfSriastradh box.x1 = x1; 303203b705cfSriastradh box.y1 = y1; 303303b705cfSriastradh box.x2 = x2; 303403b705cfSriastradh box.y2 = y2; 303503b705cfSriastradh 303603b705cfSriastradh return sna_blt_fill_boxes(sna, alu, 303703b705cfSriastradh bo, dst->drawable.bitsPerPixel, 303803b705cfSriastradh color, &box, 1); 303903b705cfSriastradh} 304003b705cfSriastradh 304103b705cfSriastradhstatic bool 304203b705cfSriastradhgen2_render_fill_one(struct sna *sna, PixmapPtr dst, struct kgem_bo *bo, 304303b705cfSriastradh uint32_t color, 304403b705cfSriastradh int16_t x1, int16_t y1, 304503b705cfSriastradh int16_t x2, int16_t y2, 304603b705cfSriastradh uint8_t alu) 304703b705cfSriastradh{ 304803b705cfSriastradh struct sna_composite_op tmp; 304903b705cfSriastradh 305003b705cfSriastradh#if NO_FILL_ONE 305103b705cfSriastradh return gen2_render_fill_one_try_blt(sna, dst, bo, color, 305203b705cfSriastradh x1, y1, x2, y2, alu); 305303b705cfSriastradh#endif 305403b705cfSriastradh 305503b705cfSriastradh /* Prefer to use the BLT if already engaged */ 305603b705cfSriastradh if (gen2_render_fill_one_try_blt(sna, dst, bo, color, 305703b705cfSriastradh x1, y1, x2, y2, alu)) 305803b705cfSriastradh return true; 305903b705cfSriastradh 306003b705cfSriastradh /* Must use the BLT if we can't RENDER... */ 306103b705cfSriastradh if (too_large(dst->drawable.width, dst->drawable.height) || 306203b705cfSriastradh bo->pitch < 8 || bo->pitch > MAX_3D_PITCH) 306303b705cfSriastradh return false; 306403b705cfSriastradh 306503b705cfSriastradh if (!kgem_check_bo(&sna->kgem, bo, NULL)) { 306603b705cfSriastradh kgem_submit(&sna->kgem); 306742542f5fSchristos 306803b705cfSriastradh if (gen2_render_fill_one_try_blt(sna, dst, bo, color, 306903b705cfSriastradh x1, y1, x2, y2, alu)) 307003b705cfSriastradh return true; 307142542f5fSchristos 307242542f5fSchristos if (!kgem_check_bo(&sna->kgem, bo, NULL)) 307342542f5fSchristos return false; 307403b705cfSriastradh } 307503b705cfSriastradh 307603b705cfSriastradh tmp.op = alu; 307703b705cfSriastradh tmp.dst.pixmap = dst; 307803b705cfSriastradh tmp.dst.width = dst->drawable.width; 307903b705cfSriastradh tmp.dst.height = dst->drawable.height; 308003b705cfSriastradh tmp.dst.format = sna_format_for_depth(dst->drawable.depth); 308103b705cfSriastradh tmp.dst.bo = bo; 308203b705cfSriastradh tmp.floats_per_vertex = 2; 308303b705cfSriastradh tmp.floats_per_rect = 6; 308403b705cfSriastradh tmp.need_magic_ca_pass = false; 308503b705cfSriastradh 308603b705cfSriastradh tmp.src.u.gen2.pixel = 308703b705cfSriastradh sna_rgba_for_color(color, dst->drawable.depth); 308803b705cfSriastradh 308903b705cfSriastradh gen2_emit_fill_state(sna, &tmp); 309003b705cfSriastradh gen2_get_rectangles(sna, &tmp, 1); 309103b705cfSriastradh DBG(("%s: (%d, %d), (%d, %d): %x\n", __FUNCTION__, 309203b705cfSriastradh x1, y1, x2, y2, tmp.src.u.gen2.pixel)); 309303b705cfSriastradh VERTEX(x2); 309403b705cfSriastradh VERTEX(y2); 309503b705cfSriastradh VERTEX(x1); 309603b705cfSriastradh VERTEX(y2); 309703b705cfSriastradh VERTEX(x1); 309803b705cfSriastradh VERTEX(y1); 309903b705cfSriastradh gen2_vertex_flush(sna, &tmp); 310003b705cfSriastradh 310103b705cfSriastradh return true; 310203b705cfSriastradh} 310303b705cfSriastradh 310403b705cfSriastradhstatic void 310503b705cfSriastradhgen2_render_copy_setup_source(struct sna_composite_channel *channel, 310642542f5fSchristos const DrawableRec *draw, 310703b705cfSriastradh struct kgem_bo *bo) 310803b705cfSriastradh{ 310942542f5fSchristos assert(draw->width && draw->height); 311003b705cfSriastradh 311103b705cfSriastradh channel->filter = PictFilterNearest; 311203b705cfSriastradh channel->repeat = RepeatNone; 311342542f5fSchristos channel->width = draw->width; 311442542f5fSchristos channel->height = draw->height; 311542542f5fSchristos channel->scale[0] = 1.f/draw->width; 311642542f5fSchristos channel->scale[1] = 1.f/draw->height; 311703b705cfSriastradh channel->offset[0] = 0; 311803b705cfSriastradh channel->offset[1] = 0; 311942542f5fSchristos channel->pict_format = sna_format_for_depth(draw->depth); 312003b705cfSriastradh channel->bo = bo; 312103b705cfSriastradh channel->is_affine = 1; 312203b705cfSriastradh 312303b705cfSriastradh DBG(("%s: source=%d, (%dx%d), format=%08x\n", 312403b705cfSriastradh __FUNCTION__, bo->handle, 312503b705cfSriastradh channel->width, channel->height, 312603b705cfSriastradh channel->pict_format)); 312703b705cfSriastradh} 312803b705cfSriastradh 312903b705cfSriastradhstatic void 313003b705cfSriastradhgen2_emit_copy_pipeline(struct sna *sna, const struct sna_composite_op *op) 313103b705cfSriastradh{ 313203b705cfSriastradh uint32_t blend, unwind; 313303b705cfSriastradh 313403b705cfSriastradh unwind = sna->kgem.nbatch; 313503b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 313603b705cfSriastradh LOAD_TEXTURE_BLEND_STAGE(0) | 1); 313703b705cfSriastradh 313803b705cfSriastradh blend = TB0C_LAST_STAGE | TB0C_RESULT_SCALE_1X | TB0C_OP_ARG1 | 313903b705cfSriastradh TB0C_OUTPUT_WRITE_CURRENT; 314003b705cfSriastradh if (op->dst.format == PICT_a8) 314103b705cfSriastradh blend |= TB0C_ARG1_REPLICATE_ALPHA | TB0C_ARG1_SEL_TEXEL0; 314203b705cfSriastradh else if (PICT_FORMAT_RGB(op->src.pict_format) != 0) 314303b705cfSriastradh blend |= TB0C_ARG1_SEL_TEXEL0; 314403b705cfSriastradh else 314503b705cfSriastradh blend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT; /* 0.0 */ 314603b705cfSriastradh BATCH(blend); 314703b705cfSriastradh 314803b705cfSriastradh blend = TB0A_RESULT_SCALE_1X | TB0A_OP_ARG1 | 314903b705cfSriastradh TB0A_OUTPUT_WRITE_CURRENT; 315003b705cfSriastradh if (PICT_FORMAT_A(op->src.pict_format) == 0) 315103b705cfSriastradh blend |= TB0A_ARG1_SEL_ONE; 315203b705cfSriastradh else 315303b705cfSriastradh blend |= TB0A_ARG1_SEL_TEXEL0; 315403b705cfSriastradh BATCH(blend); 315503b705cfSriastradh 315603b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls2 + 1, 315703b705cfSriastradh sna->kgem.batch + unwind + 1, 315803b705cfSriastradh 2 * sizeof(uint32_t)) == 0) 315903b705cfSriastradh sna->kgem.nbatch = unwind; 316003b705cfSriastradh else 316103b705cfSriastradh sna->render_state.gen2.ls2 = unwind; 316203b705cfSriastradh} 316303b705cfSriastradh 316403b705cfSriastradhstatic void gen2_emit_copy_state(struct sna *sna, const struct sna_composite_op *op) 316503b705cfSriastradh{ 316603b705cfSriastradh uint32_t ls1, v; 316703b705cfSriastradh 316803b705cfSriastradh gen2_get_batch(sna, op); 316903b705cfSriastradh 317003b705cfSriastradh if (kgem_bo_is_dirty(op->src.bo)) { 317103b705cfSriastradh if (op->src.bo == op->dst.bo) 317203b705cfSriastradh BATCH(MI_FLUSH | MI_INVALIDATE_MAP_CACHE); 317303b705cfSriastradh else 317403b705cfSriastradh BATCH(_3DSTATE_MODES_5_CMD | 317503b705cfSriastradh PIPELINE_FLUSH_RENDER_CACHE | 317603b705cfSriastradh PIPELINE_FLUSH_TEXTURE_CACHE); 317703b705cfSriastradh kgem_clear_dirty(&sna->kgem); 317803b705cfSriastradh } 317903b705cfSriastradh gen2_emit_target(sna, op); 318003b705cfSriastradh 318103b705cfSriastradh ls1 = sna->kgem.nbatch; 318203b705cfSriastradh BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | 318303b705cfSriastradh I1_LOAD_S(2) | I1_LOAD_S(3) | I1_LOAD_S(8) | 2); 318403b705cfSriastradh BATCH(1<<12); 318503b705cfSriastradh BATCH(S3_CULLMODE_NONE | S3_VERTEXHAS_XY); 318603b705cfSriastradh BATCH(S8_ENABLE_COLOR_BUFFER_WRITE); 318703b705cfSriastradh if (memcmp(sna->kgem.batch + sna->render_state.gen2.ls1 + 1, 318803b705cfSriastradh sna->kgem.batch + ls1 + 1, 318903b705cfSriastradh 3 * sizeof(uint32_t)) == 0) 319003b705cfSriastradh sna->kgem.nbatch = ls1; 319103b705cfSriastradh else 319203b705cfSriastradh sna->render_state.gen2.ls1 = ls1; 319303b705cfSriastradh 319403b705cfSriastradh gen2_enable_logic_op(sna, op->op); 319503b705cfSriastradh gen2_emit_copy_pipeline(sna, op); 319603b705cfSriastradh 319703b705cfSriastradh v = _3DSTATE_VERTEX_FORMAT_2_CMD | TEXCOORDFMT_2D; 319803b705cfSriastradh if (sna->render_state.gen2.vft != v) { 319903b705cfSriastradh BATCH(v); 320003b705cfSriastradh sna->render_state.gen2.vft = v; 320103b705cfSriastradh } 320203b705cfSriastradh 320303b705cfSriastradh gen2_emit_texture(sna, &op->src, 0); 320403b705cfSriastradh} 320503b705cfSriastradh 320603b705cfSriastradhstatic bool 320703b705cfSriastradhgen2_render_copy_boxes(struct sna *sna, uint8_t alu, 320842542f5fSchristos const DrawableRec *src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, 320942542f5fSchristos const DrawableRec *dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, 321003b705cfSriastradh const BoxRec *box, int n, unsigned flags) 321103b705cfSriastradh{ 321203b705cfSriastradh struct sna_composite_op tmp; 321303b705cfSriastradh 321403b705cfSriastradh#if NO_COPY_BOXES 321503b705cfSriastradh if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) 321603b705cfSriastradh return false; 321703b705cfSriastradh 321803b705cfSriastradh return sna_blt_copy_boxes(sna, alu, 321903b705cfSriastradh src_bo, src_dx, src_dy, 322003b705cfSriastradh dst_bo, dst_dx, dst_dy, 322103b705cfSriastradh dst->drawable.bitsPerPixel, 322203b705cfSriastradh box, n); 322303b705cfSriastradh#endif 322403b705cfSriastradh 322503b705cfSriastradh DBG(("%s (%d, %d)->(%d, %d) x %d\n", 322603b705cfSriastradh __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n)); 322703b705cfSriastradh 322842542f5fSchristos if (sna_blt_compare_depth(src, dst) && 322903b705cfSriastradh sna_blt_copy_boxes(sna, alu, 323003b705cfSriastradh src_bo, src_dx, src_dy, 323103b705cfSriastradh dst_bo, dst_dx, dst_dy, 323242542f5fSchristos dst->bitsPerPixel, 323303b705cfSriastradh box, n)) 323403b705cfSriastradh return true; 323503b705cfSriastradh 323603b705cfSriastradh if (src_bo == dst_bo || /* XXX handle overlap using 3D ? */ 323742542f5fSchristos too_large(src->width, src->height) || 323803b705cfSriastradh src_bo->pitch > MAX_3D_PITCH || dst_bo->pitch < 8) { 323903b705cfSriastradhfallback: 324003b705cfSriastradh return sna_blt_copy_boxes_fallback(sna, alu, 324103b705cfSriastradh src, src_bo, src_dx, src_dy, 324203b705cfSriastradh dst, dst_bo, dst_dx, dst_dy, 324303b705cfSriastradh box, n); 324403b705cfSriastradh } 324503b705cfSriastradh 324603b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) { 324703b705cfSriastradh kgem_submit(&sna->kgem); 324803b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) 324903b705cfSriastradh goto fallback; 325003b705cfSriastradh } 325103b705cfSriastradh 325203b705cfSriastradh assert(dst_bo->pitch >= 8); 325303b705cfSriastradh 325403b705cfSriastradh memset(&tmp, 0, sizeof(tmp)); 325503b705cfSriastradh tmp.op = alu; 325603b705cfSriastradh 325742542f5fSchristos tmp.dst.pixmap = (PixmapPtr)dst; 325842542f5fSchristos tmp.dst.width = dst->width; 325942542f5fSchristos tmp.dst.height = dst->height; 326042542f5fSchristos tmp.dst.format = sna_format_for_depth(dst->depth); 326103b705cfSriastradh tmp.dst.bo = dst_bo; 326203b705cfSriastradh tmp.dst.x = tmp.dst.y = 0; 326303b705cfSriastradh tmp.damage = NULL; 326403b705cfSriastradh 326503b705cfSriastradh DBG(("%s: target=%d, format=%08x, size=%dx%d\n", 326603b705cfSriastradh __FUNCTION__, dst_bo->handle, 326703b705cfSriastradh (unsigned)tmp.dst.format, 326803b705cfSriastradh tmp.dst.width, 326903b705cfSriastradh tmp.dst.height)); 327003b705cfSriastradh 327103b705cfSriastradh sna_render_composite_redirect_init(&tmp); 327203b705cfSriastradh if (too_large(tmp.dst.width, tmp.dst.height) || 327303b705cfSriastradh dst_bo->pitch > MAX_3D_PITCH) { 327403b705cfSriastradh BoxRec extents = box[0]; 327503b705cfSriastradh int i; 327603b705cfSriastradh 327703b705cfSriastradh for (i = 1; i < n; i++) { 327803b705cfSriastradh if (box[i].x1 < extents.x1) 327903b705cfSriastradh extents.x1 = box[i].x1; 328003b705cfSriastradh if (box[i].y1 < extents.y1) 328103b705cfSriastradh extents.y1 = box[i].y1; 328203b705cfSriastradh 328303b705cfSriastradh if (box[i].x2 > extents.x2) 328403b705cfSriastradh extents.x2 = box[i].x2; 328503b705cfSriastradh if (box[i].y2 > extents.y2) 328603b705cfSriastradh extents.y2 = box[i].y2; 328703b705cfSriastradh } 328803b705cfSriastradh if (!sna_render_composite_redirect(sna, &tmp, 328903b705cfSriastradh extents.x1 + dst_dx, 329003b705cfSriastradh extents.y1 + dst_dy, 329103b705cfSriastradh extents.x2 - extents.x1, 329203b705cfSriastradh extents.y2 - extents.y1, 329303b705cfSriastradh alu != GXcopy || n > 1)) 329403b705cfSriastradh goto fallback_tiled; 329503b705cfSriastradh } 329603b705cfSriastradh 329703b705cfSriastradh tmp.floats_per_vertex = 4; 329803b705cfSriastradh tmp.floats_per_rect = 12; 329903b705cfSriastradh 330003b705cfSriastradh dst_dx += tmp.dst.x; 330103b705cfSriastradh dst_dy += tmp.dst.y; 330203b705cfSriastradh tmp.dst.x = tmp.dst.y = 0; 330303b705cfSriastradh 330403b705cfSriastradh gen2_render_copy_setup_source(&tmp.src, src, src_bo); 330503b705cfSriastradh gen2_emit_copy_state(sna, &tmp); 330603b705cfSriastradh do { 330703b705cfSriastradh int n_this_time; 330803b705cfSriastradh 330903b705cfSriastradh n_this_time = gen2_get_rectangles(sna, &tmp, n); 331003b705cfSriastradh if (n_this_time == 0) { 331103b705cfSriastradh gen2_emit_copy_state(sna, &tmp); 331203b705cfSriastradh n_this_time = gen2_get_rectangles(sna, &tmp, n); 331303b705cfSriastradh } 331403b705cfSriastradh n -= n_this_time; 331503b705cfSriastradh 331603b705cfSriastradh do { 331703b705cfSriastradh DBG((" (%d, %d) -> (%d, %d) + (%d, %d)\n", 331803b705cfSriastradh box->x1 + src_dx, box->y1 + src_dy, 331903b705cfSriastradh box->x1 + dst_dx, box->y1 + dst_dy, 332003b705cfSriastradh box->x2 - box->x1, box->y2 - box->y1)); 332103b705cfSriastradh VERTEX(box->x2 + dst_dx); 332203b705cfSriastradh VERTEX(box->y2 + dst_dy); 332303b705cfSriastradh VERTEX((box->x2 + src_dx) * tmp.src.scale[0]); 332403b705cfSriastradh VERTEX((box->y2 + src_dy) * tmp.src.scale[1]); 332503b705cfSriastradh 332603b705cfSriastradh VERTEX(box->x1 + dst_dx); 332703b705cfSriastradh VERTEX(box->y2 + dst_dy); 332803b705cfSriastradh VERTEX((box->x1 + src_dx) * tmp.src.scale[0]); 332903b705cfSriastradh VERTEX((box->y2 + src_dy) * tmp.src.scale[1]); 333003b705cfSriastradh 333103b705cfSriastradh VERTEX(box->x1 + dst_dx); 333203b705cfSriastradh VERTEX(box->y1 + dst_dy); 333303b705cfSriastradh VERTEX((box->x1 + src_dx) * tmp.src.scale[0]); 333403b705cfSriastradh VERTEX((box->y1 + src_dy) * tmp.src.scale[1]); 333503b705cfSriastradh 333603b705cfSriastradh box++; 333703b705cfSriastradh } while (--n_this_time); 333803b705cfSriastradh } while (n); 333903b705cfSriastradh 334003b705cfSriastradh gen2_vertex_flush(sna, &tmp); 334103b705cfSriastradh sna_render_composite_redirect_done(sna, &tmp); 334203b705cfSriastradh return true; 334303b705cfSriastradh 334403b705cfSriastradhfallback_tiled: 334503b705cfSriastradh return sna_tiling_copy_boxes(sna, alu, 334603b705cfSriastradh src, src_bo, src_dx, src_dy, 334703b705cfSriastradh dst, dst_bo, dst_dx, dst_dy, 334803b705cfSriastradh box, n); 334903b705cfSriastradh} 335003b705cfSriastradh 335103b705cfSriastradhstatic void 335203b705cfSriastradhgen2_render_copy_blt(struct sna *sna, 335303b705cfSriastradh const struct sna_copy_op *op, 335403b705cfSriastradh int16_t sx, int16_t sy, 335503b705cfSriastradh int16_t w, int16_t h, 335603b705cfSriastradh int16_t dx, int16_t dy) 335703b705cfSriastradh{ 335803b705cfSriastradh if (!gen2_get_rectangles(sna, &op->base, 1)) { 335903b705cfSriastradh gen2_emit_copy_state(sna, &op->base); 336003b705cfSriastradh gen2_get_rectangles(sna, &op->base, 1); 336103b705cfSriastradh } 336203b705cfSriastradh 336303b705cfSriastradh VERTEX(dx+w); 336403b705cfSriastradh VERTEX(dy+h); 336503b705cfSriastradh VERTEX((sx+w)*op->base.src.scale[0]); 336603b705cfSriastradh VERTEX((sy+h)*op->base.src.scale[1]); 336703b705cfSriastradh 336803b705cfSriastradh VERTEX(dx); 336903b705cfSriastradh VERTEX(dy+h); 337003b705cfSriastradh VERTEX(sx*op->base.src.scale[0]); 337103b705cfSriastradh VERTEX((sy+h)*op->base.src.scale[1]); 337203b705cfSriastradh 337303b705cfSriastradh VERTEX(dx); 337403b705cfSriastradh VERTEX(dy); 337503b705cfSriastradh VERTEX(sx*op->base.src.scale[0]); 337603b705cfSriastradh VERTEX(sy*op->base.src.scale[1]); 337703b705cfSriastradh} 337803b705cfSriastradh 337903b705cfSriastradhstatic void 338003b705cfSriastradhgen2_render_copy_done(struct sna *sna, const struct sna_copy_op *op) 338103b705cfSriastradh{ 338203b705cfSriastradh gen2_vertex_flush(sna, &op->base); 338303b705cfSriastradh} 338403b705cfSriastradh 338503b705cfSriastradhstatic bool 338603b705cfSriastradhgen2_render_copy(struct sna *sna, uint8_t alu, 338703b705cfSriastradh PixmapPtr src, struct kgem_bo *src_bo, 338803b705cfSriastradh PixmapPtr dst, struct kgem_bo *dst_bo, 338903b705cfSriastradh struct sna_copy_op *tmp) 339003b705cfSriastradh{ 339103b705cfSriastradh#if NO_COPY 339203b705cfSriastradh if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) 339303b705cfSriastradh return false; 339403b705cfSriastradh 339503b705cfSriastradh return sna_blt_copy(sna, alu, 339603b705cfSriastradh src_bo, dst_bo, 339703b705cfSriastradh dst->drawable.bitsPerPixel, 339803b705cfSriastradh tmp); 339903b705cfSriastradh#endif 340003b705cfSriastradh 340103b705cfSriastradh /* Prefer to use the BLT */ 340203b705cfSriastradh if (sna_blt_compare_depth(&src->drawable, &dst->drawable) && 340303b705cfSriastradh sna_blt_copy(sna, alu, 340403b705cfSriastradh src_bo, dst_bo, 340503b705cfSriastradh dst->drawable.bitsPerPixel, 340603b705cfSriastradh tmp)) 340703b705cfSriastradh return true; 340803b705cfSriastradh 340903b705cfSriastradh /* Must use the BLT if we can't RENDER... */ 341003b705cfSriastradh if (too_large(src->drawable.width, src->drawable.height) || 341103b705cfSriastradh too_large(dst->drawable.width, dst->drawable.height) || 341203b705cfSriastradh src_bo->pitch > MAX_3D_PITCH || 341303b705cfSriastradh dst_bo->pitch < 8 || dst_bo->pitch > MAX_3D_PITCH) { 341403b705cfSriastradhfallback: 341503b705cfSriastradh if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) 341603b705cfSriastradh return false; 341703b705cfSriastradh 341803b705cfSriastradh return sna_blt_copy(sna, alu, src_bo, dst_bo, 341903b705cfSriastradh dst->drawable.bitsPerPixel, 342003b705cfSriastradh tmp); 342103b705cfSriastradh } 342203b705cfSriastradh 342303b705cfSriastradh tmp->base.op = alu; 342403b705cfSriastradh 342503b705cfSriastradh tmp->base.dst.pixmap = dst; 342603b705cfSriastradh tmp->base.dst.width = dst->drawable.width; 342703b705cfSriastradh tmp->base.dst.height = dst->drawable.height; 342803b705cfSriastradh tmp->base.dst.format = sna_format_for_depth(dst->drawable.depth); 342903b705cfSriastradh tmp->base.dst.bo = dst_bo; 343003b705cfSriastradh 343142542f5fSchristos gen2_render_copy_setup_source(&tmp->base.src, &src->drawable, src_bo); 343203b705cfSriastradh tmp->base.mask.bo = NULL; 343303b705cfSriastradh 343403b705cfSriastradh tmp->base.floats_per_vertex = 4; 343503b705cfSriastradh tmp->base.floats_per_rect = 12; 343603b705cfSriastradh 343703b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) { 343803b705cfSriastradh kgem_submit(&sna->kgem); 343903b705cfSriastradh if (!kgem_check_bo(&sna->kgem, dst_bo, src_bo, NULL)) 344003b705cfSriastradh goto fallback; 344103b705cfSriastradh } 344203b705cfSriastradh 344303b705cfSriastradh tmp->blt = gen2_render_copy_blt; 344403b705cfSriastradh tmp->done = gen2_render_copy_done; 344503b705cfSriastradh 344603b705cfSriastradh gen2_emit_composite_state(sna, &tmp->base); 344703b705cfSriastradh return true; 344803b705cfSriastradh} 344903b705cfSriastradh 345003b705cfSriastradhstatic void 345103b705cfSriastradhgen2_render_reset(struct sna *sna) 345203b705cfSriastradh{ 345303b705cfSriastradh sna->render_state.gen2.need_invariant = true; 345403b705cfSriastradh sna->render_state.gen2.logic_op_enabled = 0; 345503b705cfSriastradh sna->render_state.gen2.target = 0; 345603b705cfSriastradh 345703b705cfSriastradh sna->render_state.gen2.ls1 = 0; 345803b705cfSriastradh sna->render_state.gen2.ls2 = 0; 345903b705cfSriastradh sna->render_state.gen2.vft = 0; 346003b705cfSriastradh 346103b705cfSriastradh sna->render_state.gen2.diffuse = 0x0c0ffee0; 346203b705cfSriastradh sna->render_state.gen2.specular = 0x0c0ffee0; 346303b705cfSriastradh} 346403b705cfSriastradh 346503b705cfSriastradhstatic void 346603b705cfSriastradhgen2_render_flush(struct sna *sna) 346703b705cfSriastradh{ 346803b705cfSriastradh assert(sna->render.vertex_index == 0); 346903b705cfSriastradh assert(sna->render.vertex_offset == 0); 347003b705cfSriastradh} 347103b705cfSriastradh 347203b705cfSriastradhstatic void 347303b705cfSriastradhgen2_render_context_switch(struct kgem *kgem, 347403b705cfSriastradh int new_mode) 347503b705cfSriastradh{ 347603b705cfSriastradh struct sna *sna = container_of(kgem, struct sna, kgem); 347703b705cfSriastradh 347803b705cfSriastradh if (!kgem->nbatch) 347903b705cfSriastradh return; 348003b705cfSriastradh 348103b705cfSriastradh /* Reload BLT registers following a lost context */ 348203b705cfSriastradh sna->blt_state.fill_bo = 0; 348303b705cfSriastradh 348403b705cfSriastradh if (kgem_ring_is_idle(kgem, kgem->ring)) { 348503b705cfSriastradh DBG(("%s: GPU idle, flushing\n", __FUNCTION__)); 348603b705cfSriastradh _kgem_submit(kgem); 348703b705cfSriastradh } 348803b705cfSriastradh} 348903b705cfSriastradh 349003b705cfSriastradhconst char *gen2_render_init(struct sna *sna, const char *backend) 349103b705cfSriastradh{ 349203b705cfSriastradh struct sna_render *render = &sna->render; 349303b705cfSriastradh 349403b705cfSriastradh sna->kgem.context_switch = gen2_render_context_switch; 349503b705cfSriastradh 349603b705cfSriastradh /* Use the BLT (and overlay) for everything except when forced to 349703b705cfSriastradh * use the texture combiners. 349803b705cfSriastradh */ 349903b705cfSriastradh#if !NO_COMPOSITE 350003b705cfSriastradh render->composite = gen2_render_composite; 350103b705cfSriastradh render->prefer_gpu |= PREFER_GPU_RENDER; 350203b705cfSriastradh#endif 350303b705cfSriastradh#if !NO_COMPOSITE_SPANS 350403b705cfSriastradh render->check_composite_spans = gen2_check_composite_spans; 350503b705cfSriastradh render->composite_spans = gen2_render_composite_spans; 350603b705cfSriastradh render->prefer_gpu |= PREFER_GPU_SPANS; 350703b705cfSriastradh#endif 350803b705cfSriastradh render->fill_boxes = gen2_render_fill_boxes; 350903b705cfSriastradh render->fill = gen2_render_fill; 351003b705cfSriastradh render->fill_one = gen2_render_fill_one; 351103b705cfSriastradh render->copy = gen2_render_copy; 351203b705cfSriastradh render->copy_boxes = gen2_render_copy_boxes; 351303b705cfSriastradh 351403b705cfSriastradh /* XXX YUV color space conversion for video? */ 351503b705cfSriastradh 351603b705cfSriastradh render->reset = gen2_render_reset; 351703b705cfSriastradh render->flush = gen2_render_flush; 351803b705cfSriastradh 351903b705cfSriastradh render->max_3d_size = MAX_3D_SIZE; 352003b705cfSriastradh render->max_3d_pitch = MAX_3D_PITCH; 352103b705cfSriastradh return "Almador (gen2)"; 352203b705cfSriastradh} 3523