sna_blt.c revision 03b705cf
103b705cfSriastradh/* 203b705cfSriastradh * Based on code from intel_uxa.c and i830_xaa.c 303b705cfSriastradh * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 403b705cfSriastradh * Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org> 503b705cfSriastradh * Copyright (c) 2009-2011 Intel Corporation 603b705cfSriastradh * 703b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a 803b705cfSriastradh * copy of this software and associated documentation files (the "Software"), 903b705cfSriastradh * to deal in the Software without restriction, including without limitation 1003b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1103b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the 1203b705cfSriastradh * Software is furnished to do so, subject to the following conditions: 1303b705cfSriastradh * 1403b705cfSriastradh * The above copyright notice and this permission notice (including the next 1503b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the 1603b705cfSriastradh * Software. 1703b705cfSriastradh * 1803b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1903b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2003b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2103b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2203b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2303b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2403b705cfSriastradh * SOFTWARE. 2503b705cfSriastradh * 2603b705cfSriastradh * Authors: 2703b705cfSriastradh * Chris Wilson <chris@chris-wilson.co.uk> 2803b705cfSriastradh * 2903b705cfSriastradh */ 3003b705cfSriastradh 3103b705cfSriastradh#ifdef HAVE_CONFIG_H 3203b705cfSriastradh#include "config.h" 3303b705cfSriastradh#endif 3403b705cfSriastradh 3503b705cfSriastradh#include "sna.h" 3603b705cfSriastradh#include "sna_render.h" 3703b705cfSriastradh#include "sna_render_inline.h" 3803b705cfSriastradh#include "sna_reg.h" 3903b705cfSriastradh#include "rop.h" 4003b705cfSriastradh 4103b705cfSriastradh#define NO_BLT_COMPOSITE 0 4203b705cfSriastradh#define NO_BLT_COPY 0 4303b705cfSriastradh#define NO_BLT_COPY_BOXES 0 4403b705cfSriastradh#define NO_BLT_FILL 0 4503b705cfSriastradh#define NO_BLT_FILL_BOXES 0 4603b705cfSriastradh 4703b705cfSriastradhstatic const uint8_t copy_ROP[] = { 4803b705cfSriastradh ROP_0, /* GXclear */ 4903b705cfSriastradh ROP_DSa, /* GXand */ 5003b705cfSriastradh ROP_SDna, /* GXandReverse */ 5103b705cfSriastradh ROP_S, /* GXcopy */ 5203b705cfSriastradh ROP_DSna, /* GXandInverted */ 5303b705cfSriastradh ROP_D, /* GXnoop */ 5403b705cfSriastradh ROP_DSx, /* GXxor */ 5503b705cfSriastradh ROP_DSo, /* GXor */ 5603b705cfSriastradh ROP_DSon, /* GXnor */ 5703b705cfSriastradh ROP_DSxn, /* GXequiv */ 5803b705cfSriastradh ROP_Dn, /* GXinvert */ 5903b705cfSriastradh ROP_SDno, /* GXorReverse */ 6003b705cfSriastradh ROP_Sn, /* GXcopyInverted */ 6103b705cfSriastradh ROP_DSno, /* GXorInverted */ 6203b705cfSriastradh ROP_DSan, /* GXnand */ 6303b705cfSriastradh ROP_1 /* GXset */ 6403b705cfSriastradh}; 6503b705cfSriastradh 6603b705cfSriastradhstatic const uint8_t fill_ROP[] = { 6703b705cfSriastradh ROP_0, 6803b705cfSriastradh ROP_DPa, 6903b705cfSriastradh ROP_PDna, 7003b705cfSriastradh ROP_P, 7103b705cfSriastradh ROP_DPna, 7203b705cfSriastradh ROP_D, 7303b705cfSriastradh ROP_DPx, 7403b705cfSriastradh ROP_DPo, 7503b705cfSriastradh ROP_DPon, 7603b705cfSriastradh ROP_PDxn, 7703b705cfSriastradh ROP_Dn, 7803b705cfSriastradh ROP_PDno, 7903b705cfSriastradh ROP_Pn, 8003b705cfSriastradh ROP_DPno, 8103b705cfSriastradh ROP_DPan, 8203b705cfSriastradh ROP_1 8303b705cfSriastradh}; 8403b705cfSriastradh 8503b705cfSriastradhstatic void nop_done(struct sna *sna, const struct sna_composite_op *op) 8603b705cfSriastradh{ 8703b705cfSriastradh assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem)); 8803b705cfSriastradh if (sna->kgem.nexec > 1 && __kgem_ring_empty(&sna->kgem)) 8903b705cfSriastradh _kgem_submit(&sna->kgem); 9003b705cfSriastradh (void)op; 9103b705cfSriastradh} 9203b705cfSriastradh 9303b705cfSriastradhstatic void gen6_blt_copy_done(struct sna *sna, const struct sna_composite_op *op) 9403b705cfSriastradh{ 9503b705cfSriastradh struct kgem *kgem = &sna->kgem; 9603b705cfSriastradh 9703b705cfSriastradh assert(kgem->nbatch <= KGEM_BATCH_SIZE(kgem)); 9803b705cfSriastradh if (kgem->nexec > 1 && __kgem_ring_empty(kgem)) { 9903b705cfSriastradh _kgem_submit(kgem); 10003b705cfSriastradh return; 10103b705cfSriastradh } 10203b705cfSriastradh 10303b705cfSriastradh if (kgem_check_batch(kgem, 3)) { 10403b705cfSriastradh uint32_t *b = kgem->batch + kgem->nbatch; 10503b705cfSriastradh b[0] = XY_SETUP_CLIP; 10603b705cfSriastradh b[1] = b[2] = 0; 10703b705cfSriastradh kgem->nbatch += 3; 10803b705cfSriastradh assert(kgem->nbatch < kgem->surface); 10903b705cfSriastradh } 11003b705cfSriastradh assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem)); 11103b705cfSriastradh (void)op; 11203b705cfSriastradh} 11303b705cfSriastradh 11403b705cfSriastradhstatic bool sna_blt_fill_init(struct sna *sna, 11503b705cfSriastradh struct sna_blt_state *blt, 11603b705cfSriastradh struct kgem_bo *bo, 11703b705cfSriastradh int bpp, 11803b705cfSriastradh uint8_t alu, 11903b705cfSriastradh uint32_t pixel) 12003b705cfSriastradh{ 12103b705cfSriastradh struct kgem *kgem = &sna->kgem; 12203b705cfSriastradh 12303b705cfSriastradh assert(kgem_bo_can_blt (kgem, bo)); 12403b705cfSriastradh assert(bo->tiling != I915_TILING_Y); 12503b705cfSriastradh blt->bo[0] = bo; 12603b705cfSriastradh 12703b705cfSriastradh blt->br13 = bo->pitch; 12803b705cfSriastradh blt->cmd = XY_SCANLINE_BLT; 12903b705cfSriastradh if (kgem->gen >= 040 && bo->tiling) { 13003b705cfSriastradh blt->cmd |= BLT_DST_TILED; 13103b705cfSriastradh blt->br13 >>= 2; 13203b705cfSriastradh } 13303b705cfSriastradh assert(blt->br13 <= MAXSHORT); 13403b705cfSriastradh 13503b705cfSriastradh if (alu == GXclear) 13603b705cfSriastradh pixel = 0; 13703b705cfSriastradh else if (alu == GXcopy) { 13803b705cfSriastradh if (pixel == 0) 13903b705cfSriastradh alu = GXclear; 14003b705cfSriastradh else if (pixel == -1) 14103b705cfSriastradh alu = GXset; 14203b705cfSriastradh } 14303b705cfSriastradh 14403b705cfSriastradh blt->br13 |= 1<<31 | (fill_ROP[alu] << 16); 14503b705cfSriastradh switch (bpp) { 14603b705cfSriastradh default: assert(0); 14703b705cfSriastradh case 32: blt->br13 |= 1 << 25; /* RGB8888 */ 14803b705cfSriastradh case 16: blt->br13 |= 1 << 24; /* RGB565 */ 14903b705cfSriastradh case 8: break; 15003b705cfSriastradh } 15103b705cfSriastradh 15203b705cfSriastradh blt->pixel = pixel; 15303b705cfSriastradh blt->bpp = bpp; 15403b705cfSriastradh 15503b705cfSriastradh kgem_set_mode(kgem, KGEM_BLT, bo); 15603b705cfSriastradh if (!kgem_check_batch(kgem, 12) || 15703b705cfSriastradh !kgem_check_bo_fenced(kgem, bo)) { 15803b705cfSriastradh kgem_submit(kgem); 15903b705cfSriastradh if (!kgem_check_bo_fenced(kgem, bo)) 16003b705cfSriastradh return false; 16103b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 16203b705cfSriastradh } 16303b705cfSriastradh 16403b705cfSriastradh if (sna->blt_state.fill_bo != bo->unique_id || 16503b705cfSriastradh sna->blt_state.fill_pixel != pixel || 16603b705cfSriastradh sna->blt_state.fill_alu != alu) 16703b705cfSriastradh { 16803b705cfSriastradh uint32_t *b; 16903b705cfSriastradh 17003b705cfSriastradh if (!kgem_check_reloc(kgem, 1)) { 17103b705cfSriastradh _kgem_submit(kgem); 17203b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 17303b705cfSriastradh } 17403b705cfSriastradh 17503b705cfSriastradh b = kgem->batch + kgem->nbatch; 17603b705cfSriastradh b[0] = XY_SETUP_MONO_PATTERN_SL_BLT; 17703b705cfSriastradh if (bpp == 32) 17803b705cfSriastradh b[0] |= BLT_WRITE_ALPHA | BLT_WRITE_RGB; 17903b705cfSriastradh b[1] = blt->br13; 18003b705cfSriastradh b[2] = 0; 18103b705cfSriastradh b[3] = 0; 18203b705cfSriastradh b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, bo, 18303b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 18403b705cfSriastradh I915_GEM_DOMAIN_RENDER | 18503b705cfSriastradh KGEM_RELOC_FENCED, 18603b705cfSriastradh 0); 18703b705cfSriastradh b[5] = pixel; 18803b705cfSriastradh b[6] = pixel; 18903b705cfSriastradh b[7] = 0; 19003b705cfSriastradh b[8] = 0; 19103b705cfSriastradh kgem->nbatch += 9; 19203b705cfSriastradh assert(kgem->nbatch < kgem->surface); 19303b705cfSriastradh 19403b705cfSriastradh sna->blt_state.fill_bo = bo->unique_id; 19503b705cfSriastradh sna->blt_state.fill_pixel = pixel; 19603b705cfSriastradh sna->blt_state.fill_alu = alu; 19703b705cfSriastradh } 19803b705cfSriastradh 19903b705cfSriastradh return true; 20003b705cfSriastradh} 20103b705cfSriastradh 20203b705cfSriastradhnoinline static void sna_blt_fill_begin(struct sna *sna, 20303b705cfSriastradh const struct sna_blt_state *blt) 20403b705cfSriastradh{ 20503b705cfSriastradh struct kgem *kgem = &sna->kgem; 20603b705cfSriastradh uint32_t *b; 20703b705cfSriastradh 20803b705cfSriastradh _kgem_submit(kgem); 20903b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 21003b705cfSriastradh 21103b705cfSriastradh assert(kgem->nbatch == 0); 21203b705cfSriastradh b = kgem->batch; 21303b705cfSriastradh b[0] = XY_SETUP_MONO_PATTERN_SL_BLT; 21403b705cfSriastradh if (blt->bpp == 32) 21503b705cfSriastradh b[0] |= BLT_WRITE_ALPHA | BLT_WRITE_RGB; 21603b705cfSriastradh b[1] = blt->br13; 21703b705cfSriastradh b[2] = 0; 21803b705cfSriastradh b[3] = 0; 21903b705cfSriastradh b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, blt->bo[0], 22003b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 22103b705cfSriastradh I915_GEM_DOMAIN_RENDER | 22203b705cfSriastradh KGEM_RELOC_FENCED, 22303b705cfSriastradh 0); 22403b705cfSriastradh b[5] = blt->pixel; 22503b705cfSriastradh b[6] = blt->pixel; 22603b705cfSriastradh b[7] = 0; 22703b705cfSriastradh b[8] = 0; 22803b705cfSriastradh kgem->nbatch = 9; 22903b705cfSriastradh} 23003b705cfSriastradh 23103b705cfSriastradhinline static void sna_blt_fill_one(struct sna *sna, 23203b705cfSriastradh const struct sna_blt_state *blt, 23303b705cfSriastradh int16_t x, int16_t y, 23403b705cfSriastradh int16_t width, int16_t height) 23503b705cfSriastradh{ 23603b705cfSriastradh struct kgem *kgem = &sna->kgem; 23703b705cfSriastradh uint32_t *b; 23803b705cfSriastradh 23903b705cfSriastradh DBG(("%s: (%d, %d) x (%d, %d): %08x\n", 24003b705cfSriastradh __FUNCTION__, x, y, width, height, blt->pixel)); 24103b705cfSriastradh 24203b705cfSriastradh assert(x >= 0); 24303b705cfSriastradh assert(y >= 0); 24403b705cfSriastradh assert((y+height) * blt->bo[0]->pitch <= kgem_bo_size(blt->bo[0])); 24503b705cfSriastradh 24603b705cfSriastradh if (!kgem_check_batch(kgem, 3)) 24703b705cfSriastradh sna_blt_fill_begin(sna, blt); 24803b705cfSriastradh 24903b705cfSriastradh b = kgem->batch + kgem->nbatch; 25003b705cfSriastradh kgem->nbatch += 3; 25103b705cfSriastradh assert(kgem->nbatch < kgem->surface); 25203b705cfSriastradh 25303b705cfSriastradh b[0] = blt->cmd; 25403b705cfSriastradh b[1] = y << 16 | x; 25503b705cfSriastradh b[2] = b[1] + (height << 16 | width); 25603b705cfSriastradh} 25703b705cfSriastradh 25803b705cfSriastradhstatic bool sna_blt_copy_init(struct sna *sna, 25903b705cfSriastradh struct sna_blt_state *blt, 26003b705cfSriastradh struct kgem_bo *src, 26103b705cfSriastradh struct kgem_bo *dst, 26203b705cfSriastradh int bpp, 26303b705cfSriastradh uint8_t alu) 26403b705cfSriastradh{ 26503b705cfSriastradh struct kgem *kgem = &sna->kgem; 26603b705cfSriastradh 26703b705cfSriastradh assert(kgem_bo_can_blt (kgem, src)); 26803b705cfSriastradh assert(kgem_bo_can_blt (kgem, dst)); 26903b705cfSriastradh 27003b705cfSriastradh blt->bo[0] = src; 27103b705cfSriastradh blt->bo[1] = dst; 27203b705cfSriastradh 27303b705cfSriastradh blt->cmd = XY_SRC_COPY_BLT_CMD; 27403b705cfSriastradh if (bpp == 32) 27503b705cfSriastradh blt->cmd |= BLT_WRITE_ALPHA | BLT_WRITE_RGB; 27603b705cfSriastradh 27703b705cfSriastradh blt->pitch[0] = src->pitch; 27803b705cfSriastradh if (kgem->gen >= 040 && src->tiling) { 27903b705cfSriastradh blt->cmd |= BLT_SRC_TILED; 28003b705cfSriastradh blt->pitch[0] >>= 2; 28103b705cfSriastradh } 28203b705cfSriastradh assert(blt->pitch[0] <= MAXSHORT); 28303b705cfSriastradh 28403b705cfSriastradh blt->pitch[1] = dst->pitch; 28503b705cfSriastradh if (kgem->gen >= 040 && dst->tiling) { 28603b705cfSriastradh blt->cmd |= BLT_DST_TILED; 28703b705cfSriastradh blt->pitch[1] >>= 2; 28803b705cfSriastradh } 28903b705cfSriastradh assert(blt->pitch[1] <= MAXSHORT); 29003b705cfSriastradh 29103b705cfSriastradh blt->overwrites = alu == GXcopy || alu == GXclear || alu == GXset; 29203b705cfSriastradh blt->br13 = (copy_ROP[alu] << 16) | blt->pitch[1]; 29303b705cfSriastradh switch (bpp) { 29403b705cfSriastradh default: assert(0); 29503b705cfSriastradh case 32: blt->br13 |= 1 << 25; /* RGB8888 */ 29603b705cfSriastradh case 16: blt->br13 |= 1 << 24; /* RGB565 */ 29703b705cfSriastradh case 8: break; 29803b705cfSriastradh } 29903b705cfSriastradh 30003b705cfSriastradh kgem_set_mode(kgem, KGEM_BLT, dst); 30103b705cfSriastradh if (!kgem_check_many_bo_fenced(kgem, src, dst, NULL)) { 30203b705cfSriastradh kgem_submit(kgem); 30303b705cfSriastradh if (!kgem_check_many_bo_fenced(kgem, src, dst, NULL)) 30403b705cfSriastradh return false; 30503b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 30603b705cfSriastradh } 30703b705cfSriastradh 30803b705cfSriastradh sna->blt_state.fill_bo = 0; 30903b705cfSriastradh return true; 31003b705cfSriastradh} 31103b705cfSriastradh 31203b705cfSriastradhstatic bool sna_blt_alpha_fixup_init(struct sna *sna, 31303b705cfSriastradh struct sna_blt_state *blt, 31403b705cfSriastradh struct kgem_bo *src, 31503b705cfSriastradh struct kgem_bo *dst, 31603b705cfSriastradh int bpp, uint32_t alpha) 31703b705cfSriastradh{ 31803b705cfSriastradh struct kgem *kgem = &sna->kgem; 31903b705cfSriastradh 32003b705cfSriastradh assert(kgem_bo_can_blt (kgem, src)); 32103b705cfSriastradh assert(kgem_bo_can_blt (kgem, dst)); 32203b705cfSriastradh 32303b705cfSriastradh blt->bo[0] = src; 32403b705cfSriastradh blt->bo[1] = dst; 32503b705cfSriastradh 32603b705cfSriastradh blt->cmd = XY_FULL_MONO_PATTERN_BLT; 32703b705cfSriastradh blt->pitch[0] = src->pitch; 32803b705cfSriastradh if (kgem->gen >= 040 && src->tiling) { 32903b705cfSriastradh blt->cmd |= BLT_SRC_TILED; 33003b705cfSriastradh blt->pitch[0] >>= 2; 33103b705cfSriastradh } 33203b705cfSriastradh assert(blt->pitch[0] <= MAXSHORT); 33303b705cfSriastradh 33403b705cfSriastradh blt->pitch[1] = dst->pitch; 33503b705cfSriastradh if (kgem->gen >= 040 && dst->tiling) { 33603b705cfSriastradh blt->cmd |= BLT_DST_TILED; 33703b705cfSriastradh blt->pitch[1] >>= 2; 33803b705cfSriastradh } 33903b705cfSriastradh assert(blt->pitch[1] <= MAXSHORT); 34003b705cfSriastradh 34103b705cfSriastradh blt->overwrites = 1; 34203b705cfSriastradh blt->br13 = (0xfc << 16) | blt->pitch[1]; 34303b705cfSriastradh switch (bpp) { 34403b705cfSriastradh default: assert(0); 34503b705cfSriastradh case 32: blt->cmd |= BLT_WRITE_ALPHA | BLT_WRITE_RGB; 34603b705cfSriastradh blt->br13 |= 1 << 25; /* RGB8888 */ 34703b705cfSriastradh case 16: blt->br13 |= 1 << 24; /* RGB565 */ 34803b705cfSriastradh case 8: break; 34903b705cfSriastradh } 35003b705cfSriastradh blt->pixel = alpha; 35103b705cfSriastradh 35203b705cfSriastradh kgem_set_mode(kgem, KGEM_BLT, dst); 35303b705cfSriastradh if (!kgem_check_many_bo_fenced(kgem, src, dst, NULL)) { 35403b705cfSriastradh kgem_submit(kgem); 35503b705cfSriastradh if (!kgem_check_many_bo_fenced(kgem, src, dst, NULL)) 35603b705cfSriastradh return false; 35703b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 35803b705cfSriastradh } 35903b705cfSriastradh 36003b705cfSriastradh sna->blt_state.fill_bo = 0; 36103b705cfSriastradh return true; 36203b705cfSriastradh} 36303b705cfSriastradh 36403b705cfSriastradhstatic void sna_blt_alpha_fixup_one(struct sna *sna, 36503b705cfSriastradh const struct sna_blt_state *blt, 36603b705cfSriastradh int src_x, int src_y, 36703b705cfSriastradh int width, int height, 36803b705cfSriastradh int dst_x, int dst_y) 36903b705cfSriastradh{ 37003b705cfSriastradh struct kgem *kgem = &sna->kgem; 37103b705cfSriastradh uint32_t *b; 37203b705cfSriastradh 37303b705cfSriastradh DBG(("%s: (%d, %d) -> (%d, %d) x (%d, %d)\n", 37403b705cfSriastradh __FUNCTION__, src_x, src_y, dst_x, dst_y, width, height)); 37503b705cfSriastradh 37603b705cfSriastradh assert(src_x >= 0); 37703b705cfSriastradh assert(src_y >= 0); 37803b705cfSriastradh assert((src_y + height) * blt->bo[0]->pitch <= kgem_bo_size(blt->bo[0])); 37903b705cfSriastradh assert(dst_x >= 0); 38003b705cfSriastradh assert(dst_y >= 0); 38103b705cfSriastradh assert((dst_y + height) * blt->bo[1]->pitch <= kgem_bo_size(blt->bo[1])); 38203b705cfSriastradh assert(width > 0); 38303b705cfSriastradh assert(height > 0); 38403b705cfSriastradh 38503b705cfSriastradh if (!kgem_check_batch(kgem, 12) || 38603b705cfSriastradh !kgem_check_reloc(kgem, 2)) { 38703b705cfSriastradh _kgem_submit(kgem); 38803b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 38903b705cfSriastradh } 39003b705cfSriastradh 39103b705cfSriastradh b = kgem->batch + kgem->nbatch; 39203b705cfSriastradh b[0] = blt->cmd; 39303b705cfSriastradh b[1] = blt->br13; 39403b705cfSriastradh b[2] = (dst_y << 16) | dst_x; 39503b705cfSriastradh b[3] = ((dst_y + height) << 16) | (dst_x + width); 39603b705cfSriastradh b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, 39703b705cfSriastradh blt->bo[1], 39803b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 39903b705cfSriastradh I915_GEM_DOMAIN_RENDER | 40003b705cfSriastradh KGEM_RELOC_FENCED, 40103b705cfSriastradh 0); 40203b705cfSriastradh b[5] = blt->pitch[0]; 40303b705cfSriastradh b[6] = (src_y << 16) | src_x; 40403b705cfSriastradh b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7, 40503b705cfSriastradh blt->bo[0], 40603b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 40703b705cfSriastradh KGEM_RELOC_FENCED, 40803b705cfSriastradh 0); 40903b705cfSriastradh b[8] = blt->pixel; 41003b705cfSriastradh b[9] = blt->pixel; 41103b705cfSriastradh b[10] = 0; 41203b705cfSriastradh b[11] = 0; 41303b705cfSriastradh kgem->nbatch += 12; 41403b705cfSriastradh assert(kgem->nbatch < kgem->surface); 41503b705cfSriastradh} 41603b705cfSriastradh 41703b705cfSriastradhstatic void sna_blt_copy_one(struct sna *sna, 41803b705cfSriastradh const struct sna_blt_state *blt, 41903b705cfSriastradh int src_x, int src_y, 42003b705cfSriastradh int width, int height, 42103b705cfSriastradh int dst_x, int dst_y) 42203b705cfSriastradh{ 42303b705cfSriastradh struct kgem *kgem = &sna->kgem; 42403b705cfSriastradh uint32_t *b; 42503b705cfSriastradh 42603b705cfSriastradh DBG(("%s: (%d, %d) -> (%d, %d) x (%d, %d)\n", 42703b705cfSriastradh __FUNCTION__, src_x, src_y, dst_x, dst_y, width, height)); 42803b705cfSriastradh 42903b705cfSriastradh assert(src_x >= 0); 43003b705cfSriastradh assert(src_y >= 0); 43103b705cfSriastradh assert((src_y + height) * blt->bo[0]->pitch <= kgem_bo_size(blt->bo[0])); 43203b705cfSriastradh assert(dst_x >= 0); 43303b705cfSriastradh assert(dst_y >= 0); 43403b705cfSriastradh assert((dst_y + height) * blt->bo[1]->pitch <= kgem_bo_size(blt->bo[1])); 43503b705cfSriastradh assert(width > 0); 43603b705cfSriastradh assert(height > 0); 43703b705cfSriastradh 43803b705cfSriastradh /* Compare against a previous fill */ 43903b705cfSriastradh if (kgem->nbatch >= 6 && 44003b705cfSriastradh blt->overwrites && 44103b705cfSriastradh kgem->batch[kgem->nbatch-6] == (XY_COLOR_BLT | (blt->cmd & (BLT_WRITE_ALPHA | BLT_WRITE_RGB))) && 44203b705cfSriastradh kgem->batch[kgem->nbatch-4] == ((uint32_t)dst_y << 16 | (uint16_t)dst_x) && 44303b705cfSriastradh kgem->batch[kgem->nbatch-3] == ((uint32_t)(dst_y+height) << 16 | (uint16_t)(dst_x+width)) && 44403b705cfSriastradh kgem->reloc[kgem->nreloc-1].target_handle == blt->bo[1]->target_handle) { 44503b705cfSriastradh DBG(("%s: replacing last fill\n", __FUNCTION__)); 44603b705cfSriastradh if (kgem_check_batch(kgem, 8-6)) { 44703b705cfSriastradh b = kgem->batch + kgem->nbatch - 6; 44803b705cfSriastradh b[0] = blt->cmd; 44903b705cfSriastradh b[1] = blt->br13; 45003b705cfSriastradh b[5] = (src_y << 16) | src_x; 45103b705cfSriastradh b[6] = blt->pitch[0]; 45203b705cfSriastradh b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7 - 6, 45303b705cfSriastradh blt->bo[0], 45403b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 45503b705cfSriastradh KGEM_RELOC_FENCED, 45603b705cfSriastradh 0); 45703b705cfSriastradh kgem->nbatch += 8 - 6; 45803b705cfSriastradh assert(kgem->nbatch < kgem->surface); 45903b705cfSriastradh return; 46003b705cfSriastradh } 46103b705cfSriastradh kgem->nbatch -= 6; 46203b705cfSriastradh kgem->nreloc--; 46303b705cfSriastradh } 46403b705cfSriastradh 46503b705cfSriastradh if (!kgem_check_batch(kgem, 8) || 46603b705cfSriastradh !kgem_check_reloc(kgem, 2)) { 46703b705cfSriastradh _kgem_submit(kgem); 46803b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 46903b705cfSriastradh } 47003b705cfSriastradh 47103b705cfSriastradh b = kgem->batch + kgem->nbatch; 47203b705cfSriastradh b[0] = blt->cmd; 47303b705cfSriastradh b[1] = blt->br13; 47403b705cfSriastradh b[2] = (dst_y << 16) | dst_x; 47503b705cfSriastradh b[3] = ((dst_y + height) << 16) | (dst_x + width); 47603b705cfSriastradh b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, 47703b705cfSriastradh blt->bo[1], 47803b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 47903b705cfSriastradh I915_GEM_DOMAIN_RENDER | 48003b705cfSriastradh KGEM_RELOC_FENCED, 48103b705cfSriastradh 0); 48203b705cfSriastradh b[5] = (src_y << 16) | src_x; 48303b705cfSriastradh b[6] = blt->pitch[0]; 48403b705cfSriastradh b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7, 48503b705cfSriastradh blt->bo[0], 48603b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 48703b705cfSriastradh KGEM_RELOC_FENCED, 48803b705cfSriastradh 0); 48903b705cfSriastradh kgem->nbatch += 8; 49003b705cfSriastradh assert(kgem->nbatch < kgem->surface); 49103b705cfSriastradh} 49203b705cfSriastradh 49303b705cfSriastradhbool 49403b705cfSriastradhsna_get_rgba_from_pixel(uint32_t pixel, 49503b705cfSriastradh uint16_t *red, 49603b705cfSriastradh uint16_t *green, 49703b705cfSriastradh uint16_t *blue, 49803b705cfSriastradh uint16_t *alpha, 49903b705cfSriastradh uint32_t format) 50003b705cfSriastradh{ 50103b705cfSriastradh int rbits, bbits, gbits, abits; 50203b705cfSriastradh int rshift, bshift, gshift, ashift; 50303b705cfSriastradh 50403b705cfSriastradh rbits = PICT_FORMAT_R(format); 50503b705cfSriastradh gbits = PICT_FORMAT_G(format); 50603b705cfSriastradh bbits = PICT_FORMAT_B(format); 50703b705cfSriastradh abits = PICT_FORMAT_A(format); 50803b705cfSriastradh 50903b705cfSriastradh if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) { 51003b705cfSriastradh rshift = gshift = bshift = ashift = 0; 51103b705cfSriastradh } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 51203b705cfSriastradh bshift = 0; 51303b705cfSriastradh gshift = bbits; 51403b705cfSriastradh rshift = gshift + gbits; 51503b705cfSriastradh ashift = rshift + rbits; 51603b705cfSriastradh } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { 51703b705cfSriastradh rshift = 0; 51803b705cfSriastradh gshift = rbits; 51903b705cfSriastradh bshift = gshift + gbits; 52003b705cfSriastradh ashift = bshift + bbits; 52103b705cfSriastradh } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { 52203b705cfSriastradh ashift = 0; 52303b705cfSriastradh rshift = abits; 52403b705cfSriastradh if (abits == 0) 52503b705cfSriastradh rshift = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits); 52603b705cfSriastradh gshift = rshift + rbits; 52703b705cfSriastradh bshift = gshift + gbits; 52803b705cfSriastradh } else { 52903b705cfSriastradh return false; 53003b705cfSriastradh } 53103b705cfSriastradh 53203b705cfSriastradh if (rbits) { 53303b705cfSriastradh *red = ((pixel >> rshift) & ((1 << rbits) - 1)) << (16 - rbits); 53403b705cfSriastradh while (rbits < 16) { 53503b705cfSriastradh *red |= *red >> rbits; 53603b705cfSriastradh rbits <<= 1; 53703b705cfSriastradh } 53803b705cfSriastradh } else 53903b705cfSriastradh *red = 0; 54003b705cfSriastradh 54103b705cfSriastradh if (gbits) { 54203b705cfSriastradh *green = ((pixel >> gshift) & ((1 << gbits) - 1)) << (16 - gbits); 54303b705cfSriastradh while (gbits < 16) { 54403b705cfSriastradh *green |= *green >> gbits; 54503b705cfSriastradh gbits <<= 1; 54603b705cfSriastradh } 54703b705cfSriastradh } else 54803b705cfSriastradh *green = 0; 54903b705cfSriastradh 55003b705cfSriastradh if (bbits) { 55103b705cfSriastradh *blue = ((pixel >> bshift) & ((1 << bbits) - 1)) << (16 - bbits); 55203b705cfSriastradh while (bbits < 16) { 55303b705cfSriastradh *blue |= *blue >> bbits; 55403b705cfSriastradh bbits <<= 1; 55503b705cfSriastradh } 55603b705cfSriastradh } else 55703b705cfSriastradh *blue = 0; 55803b705cfSriastradh 55903b705cfSriastradh if (abits) { 56003b705cfSriastradh *alpha = ((pixel >> ashift) & ((1 << abits) - 1)) << (16 - abits); 56103b705cfSriastradh while (abits < 16) { 56203b705cfSriastradh *alpha |= *alpha >> abits; 56303b705cfSriastradh abits <<= 1; 56403b705cfSriastradh } 56503b705cfSriastradh } else 56603b705cfSriastradh *alpha = 0xffff; 56703b705cfSriastradh 56803b705cfSriastradh return true; 56903b705cfSriastradh} 57003b705cfSriastradh 57103b705cfSriastradhbool 57203b705cfSriastradh_sna_get_pixel_from_rgba(uint32_t * pixel, 57303b705cfSriastradh uint16_t red, 57403b705cfSriastradh uint16_t green, 57503b705cfSriastradh uint16_t blue, 57603b705cfSriastradh uint16_t alpha, 57703b705cfSriastradh uint32_t format) 57803b705cfSriastradh{ 57903b705cfSriastradh int rbits, bbits, gbits, abits; 58003b705cfSriastradh int rshift, bshift, gshift, ashift; 58103b705cfSriastradh 58203b705cfSriastradh rbits = PICT_FORMAT_R(format); 58303b705cfSriastradh gbits = PICT_FORMAT_G(format); 58403b705cfSriastradh bbits = PICT_FORMAT_B(format); 58503b705cfSriastradh abits = PICT_FORMAT_A(format); 58603b705cfSriastradh if (abits == 0) 58703b705cfSriastradh abits = PICT_FORMAT_BPP(format) - (rbits+gbits+bbits); 58803b705cfSriastradh 58903b705cfSriastradh if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A) { 59003b705cfSriastradh *pixel = alpha >> (16 - abits); 59103b705cfSriastradh return true; 59203b705cfSriastradh } 59303b705cfSriastradh 59403b705cfSriastradh if (!PICT_FORMAT_COLOR(format)) 59503b705cfSriastradh return false; 59603b705cfSriastradh 59703b705cfSriastradh if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { 59803b705cfSriastradh bshift = 0; 59903b705cfSriastradh gshift = bbits; 60003b705cfSriastradh rshift = gshift + gbits; 60103b705cfSriastradh ashift = rshift + rbits; 60203b705cfSriastradh } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { 60303b705cfSriastradh rshift = 0; 60403b705cfSriastradh gshift = rbits; 60503b705cfSriastradh bshift = gshift + gbits; 60603b705cfSriastradh ashift = bshift + bbits; 60703b705cfSriastradh } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { 60803b705cfSriastradh ashift = 0; 60903b705cfSriastradh rshift = abits; 61003b705cfSriastradh gshift = rshift + rbits; 61103b705cfSriastradh bshift = gshift + gbits; 61203b705cfSriastradh } else 61303b705cfSriastradh return false; 61403b705cfSriastradh 61503b705cfSriastradh *pixel = 0; 61603b705cfSriastradh *pixel |= (blue >> (16 - bbits)) << bshift; 61703b705cfSriastradh *pixel |= (green >> (16 - gbits)) << gshift; 61803b705cfSriastradh *pixel |= (red >> (16 - rbits)) << rshift; 61903b705cfSriastradh *pixel |= (alpha >> (16 - abits)) << ashift; 62003b705cfSriastradh 62103b705cfSriastradh return true; 62203b705cfSriastradh} 62303b705cfSriastradh 62403b705cfSriastradhuint32_t 62503b705cfSriastradhsna_rgba_for_color(uint32_t color, int depth) 62603b705cfSriastradh{ 62703b705cfSriastradh return color_convert(color, sna_format_for_depth(depth), PICT_a8r8g8b8); 62803b705cfSriastradh} 62903b705cfSriastradh 63003b705cfSriastradhuint32_t 63103b705cfSriastradhsna_rgba_to_color(uint32_t rgba, uint32_t format) 63203b705cfSriastradh{ 63303b705cfSriastradh return color_convert(rgba, PICT_a8r8g8b8, format); 63403b705cfSriastradh} 63503b705cfSriastradh 63603b705cfSriastradhstatic uint32_t 63703b705cfSriastradhget_pixel(PicturePtr picture) 63803b705cfSriastradh{ 63903b705cfSriastradh PixmapPtr pixmap = get_drawable_pixmap(picture->pDrawable); 64003b705cfSriastradh 64103b705cfSriastradh DBG(("%s: %p\n", __FUNCTION__, pixmap)); 64203b705cfSriastradh 64303b705cfSriastradh if (!sna_pixmap_move_to_cpu(pixmap, MOVE_READ)) 64403b705cfSriastradh return 0; 64503b705cfSriastradh 64603b705cfSriastradh switch (pixmap->drawable.bitsPerPixel) { 64703b705cfSriastradh case 32: return *(uint32_t *)pixmap->devPrivate.ptr; 64803b705cfSriastradh case 16: return *(uint16_t *)pixmap->devPrivate.ptr; 64903b705cfSriastradh default: return *(uint8_t *)pixmap->devPrivate.ptr; 65003b705cfSriastradh } 65103b705cfSriastradh} 65203b705cfSriastradh 65303b705cfSriastradhstatic uint32_t 65403b705cfSriastradhget_solid_color(PicturePtr picture, uint32_t format) 65503b705cfSriastradh{ 65603b705cfSriastradh if (picture->pSourcePict) { 65703b705cfSriastradh PictSolidFill *fill = (PictSolidFill *)picture->pSourcePict; 65803b705cfSriastradh return color_convert(fill->color, PICT_a8r8g8b8, format); 65903b705cfSriastradh } else 66003b705cfSriastradh return color_convert(get_pixel(picture), picture->format, format); 66103b705cfSriastradh} 66203b705cfSriastradh 66303b705cfSriastradhstatic bool 66403b705cfSriastradhis_solid(PicturePtr picture) 66503b705cfSriastradh{ 66603b705cfSriastradh if (picture->pSourcePict) { 66703b705cfSriastradh if (picture->pSourcePict->type == SourcePictTypeSolidFill) 66803b705cfSriastradh return true; 66903b705cfSriastradh } 67003b705cfSriastradh 67103b705cfSriastradh if (picture->pDrawable) { 67203b705cfSriastradh if (picture->pDrawable->width == 1 && 67303b705cfSriastradh picture->pDrawable->height == 1 && 67403b705cfSriastradh picture->repeat) 67503b705cfSriastradh return true; 67603b705cfSriastradh } 67703b705cfSriastradh 67803b705cfSriastradh return false; 67903b705cfSriastradh} 68003b705cfSriastradh 68103b705cfSriastradhbool 68203b705cfSriastradhsna_picture_is_solid(PicturePtr picture, uint32_t *color) 68303b705cfSriastradh{ 68403b705cfSriastradh if (!is_solid(picture)) 68503b705cfSriastradh return false; 68603b705cfSriastradh 68703b705cfSriastradh if (color) 68803b705cfSriastradh *color = get_solid_color(picture, PICT_a8r8g8b8); 68903b705cfSriastradh return true; 69003b705cfSriastradh} 69103b705cfSriastradh 69203b705cfSriastradhstatic bool 69303b705cfSriastradhpixel_is_opaque(uint32_t pixel, uint32_t format) 69403b705cfSriastradh{ 69503b705cfSriastradh unsigned int abits; 69603b705cfSriastradh 69703b705cfSriastradh abits = PICT_FORMAT_A(format); 69803b705cfSriastradh if (!abits) 69903b705cfSriastradh return true; 70003b705cfSriastradh 70103b705cfSriastradh if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A || 70203b705cfSriastradh PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { 70303b705cfSriastradh return (pixel & ((1 << abits) - 1)) == (unsigned)((1 << abits) - 1); 70403b705cfSriastradh } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB || 70503b705cfSriastradh PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { 70603b705cfSriastradh unsigned int ashift = PICT_FORMAT_BPP(format) - abits; 70703b705cfSriastradh return (pixel >> ashift) == (unsigned)((1 << abits) - 1); 70803b705cfSriastradh } else 70903b705cfSriastradh return false; 71003b705cfSriastradh} 71103b705cfSriastradh 71203b705cfSriastradhstatic bool 71303b705cfSriastradhpixel_is_white(uint32_t pixel, uint32_t format) 71403b705cfSriastradh{ 71503b705cfSriastradh switch (PICT_FORMAT_TYPE(format)) { 71603b705cfSriastradh case PICT_TYPE_A: 71703b705cfSriastradh case PICT_TYPE_ARGB: 71803b705cfSriastradh case PICT_TYPE_ABGR: 71903b705cfSriastradh case PICT_TYPE_BGRA: 72003b705cfSriastradh return pixel == ((1U << PICT_FORMAT_BPP(format)) - 1); 72103b705cfSriastradh default: 72203b705cfSriastradh return false; 72303b705cfSriastradh } 72403b705cfSriastradh} 72503b705cfSriastradh 72603b705cfSriastradhstatic bool 72703b705cfSriastradhis_opaque_solid(PicturePtr picture) 72803b705cfSriastradh{ 72903b705cfSriastradh if (picture->pSourcePict) { 73003b705cfSriastradh PictSolidFill *fill = (PictSolidFill *) picture->pSourcePict; 73103b705cfSriastradh return (fill->color >> 24) == 0xff; 73203b705cfSriastradh } else 73303b705cfSriastradh return pixel_is_opaque(get_pixel(picture), picture->format); 73403b705cfSriastradh} 73503b705cfSriastradh 73603b705cfSriastradhstatic bool 73703b705cfSriastradhis_white(PicturePtr picture) 73803b705cfSriastradh{ 73903b705cfSriastradh if (picture->pSourcePict) { 74003b705cfSriastradh PictSolidFill *fill = (PictSolidFill *) picture->pSourcePict; 74103b705cfSriastradh return fill->color == 0xffffffff; 74203b705cfSriastradh } else 74303b705cfSriastradh return pixel_is_white(get_pixel(picture), picture->format); 74403b705cfSriastradh} 74503b705cfSriastradh 74603b705cfSriastradhbool 74703b705cfSriastradhsna_composite_mask_is_opaque(PicturePtr mask) 74803b705cfSriastradh{ 74903b705cfSriastradh if (mask->componentAlpha && PICT_FORMAT_RGB(mask->format)) 75003b705cfSriastradh return is_solid(mask) && is_white(mask); 75103b705cfSriastradh else if (!PICT_FORMAT_A(mask->format)) 75203b705cfSriastradh return true; 75303b705cfSriastradh else 75403b705cfSriastradh return is_solid(mask) && is_opaque_solid(mask); 75503b705cfSriastradh} 75603b705cfSriastradh 75703b705cfSriastradhfastcall 75803b705cfSriastradhstatic void blt_composite_fill(struct sna *sna, 75903b705cfSriastradh const struct sna_composite_op *op, 76003b705cfSriastradh const struct sna_composite_rectangles *r) 76103b705cfSriastradh{ 76203b705cfSriastradh int x1, x2, y1, y2; 76303b705cfSriastradh 76403b705cfSriastradh x1 = r->dst.x + op->dst.x; 76503b705cfSriastradh y1 = r->dst.y + op->dst.y; 76603b705cfSriastradh x2 = x1 + r->width; 76703b705cfSriastradh y2 = y1 + r->height; 76803b705cfSriastradh 76903b705cfSriastradh if (x1 < 0) 77003b705cfSriastradh x1 = 0; 77103b705cfSriastradh if (y1 < 0) 77203b705cfSriastradh y1 = 0; 77303b705cfSriastradh 77403b705cfSriastradh if (x2 > op->dst.width) 77503b705cfSriastradh x2 = op->dst.width; 77603b705cfSriastradh if (y2 > op->dst.height) 77703b705cfSriastradh y2 = op->dst.height; 77803b705cfSriastradh 77903b705cfSriastradh if (x2 <= x1 || y2 <= y1) 78003b705cfSriastradh return; 78103b705cfSriastradh 78203b705cfSriastradh sna_blt_fill_one(sna, &op->u.blt, x1, y1, x2-x1, y2-y1); 78303b705cfSriastradh} 78403b705cfSriastradh 78503b705cfSriastradhfastcall 78603b705cfSriastradhstatic void blt_composite_fill__cpu(struct sna *sna, 78703b705cfSriastradh const struct sna_composite_op *op, 78803b705cfSriastradh const struct sna_composite_rectangles *r) 78903b705cfSriastradh{ 79003b705cfSriastradh int x1, x2, y1, y2; 79103b705cfSriastradh 79203b705cfSriastradh x1 = r->dst.x + op->dst.x; 79303b705cfSriastradh y1 = r->dst.y + op->dst.y; 79403b705cfSriastradh x2 = x1 + r->width; 79503b705cfSriastradh y2 = y1 + r->height; 79603b705cfSriastradh 79703b705cfSriastradh if (x1 < 0) 79803b705cfSriastradh x1 = 0; 79903b705cfSriastradh if (y1 < 0) 80003b705cfSriastradh y1 = 0; 80103b705cfSriastradh 80203b705cfSriastradh if (x2 > op->dst.width) 80303b705cfSriastradh x2 = op->dst.width; 80403b705cfSriastradh if (y2 > op->dst.height) 80503b705cfSriastradh y2 = op->dst.height; 80603b705cfSriastradh 80703b705cfSriastradh if (x2 <= x1 || y2 <= y1) 80803b705cfSriastradh return; 80903b705cfSriastradh 81003b705cfSriastradh pixman_fill(op->dst.pixmap->devPrivate.ptr, 81103b705cfSriastradh op->dst.pixmap->devKind / sizeof(uint32_t), 81203b705cfSriastradh op->dst.pixmap->drawable.bitsPerPixel, 81303b705cfSriastradh x1, y1, x2-x1, y2-y1, 81403b705cfSriastradh op->u.blt.pixel); 81503b705cfSriastradh} 81603b705cfSriastradh 81703b705cfSriastradhfastcall static void 81803b705cfSriastradhblt_composite_fill_box__cpu(struct sna *sna, 81903b705cfSriastradh const struct sna_composite_op *op, 82003b705cfSriastradh const BoxRec *box) 82103b705cfSriastradh{ 82203b705cfSriastradh pixman_fill(op->dst.pixmap->devPrivate.ptr, 82303b705cfSriastradh op->dst.pixmap->devKind / sizeof(uint32_t), 82403b705cfSriastradh op->dst.pixmap->drawable.bitsPerPixel, 82503b705cfSriastradh box->x1, box->y1, box->x2-box->x1, box->y2-box->y1, 82603b705cfSriastradh op->u.blt.pixel); 82703b705cfSriastradh} 82803b705cfSriastradh 82903b705cfSriastradhstatic void 83003b705cfSriastradhblt_composite_fill_boxes__cpu(struct sna *sna, 83103b705cfSriastradh const struct sna_composite_op *op, 83203b705cfSriastradh const BoxRec *box, int n) 83303b705cfSriastradh{ 83403b705cfSriastradh do { 83503b705cfSriastradh pixman_fill(op->dst.pixmap->devPrivate.ptr, 83603b705cfSriastradh op->dst.pixmap->devKind / sizeof(uint32_t), 83703b705cfSriastradh op->dst.pixmap->drawable.bitsPerPixel, 83803b705cfSriastradh box->x1, box->y1, box->x2-box->x1, box->y2-box->y1, 83903b705cfSriastradh op->u.blt.pixel); 84003b705cfSriastradh box++; 84103b705cfSriastradh } while (--n); 84203b705cfSriastradh} 84303b705cfSriastradh 84403b705cfSriastradhinline static void _sna_blt_fill_box(struct sna *sna, 84503b705cfSriastradh const struct sna_blt_state *blt, 84603b705cfSriastradh const BoxRec *box) 84703b705cfSriastradh{ 84803b705cfSriastradh struct kgem *kgem = &sna->kgem; 84903b705cfSriastradh uint32_t *b; 85003b705cfSriastradh 85103b705cfSriastradh DBG(("%s: (%d, %d), (%d, %d): %08x\n", __FUNCTION__, 85203b705cfSriastradh box->x1, box->y1, box->x2, box->y2, 85303b705cfSriastradh blt->pixel)); 85403b705cfSriastradh 85503b705cfSriastradh assert(box->x1 >= 0); 85603b705cfSriastradh assert(box->y1 >= 0); 85703b705cfSriastradh assert(box->y2 * blt->bo[0]->pitch <= kgem_bo_size(blt->bo[0])); 85803b705cfSriastradh 85903b705cfSriastradh if (!kgem_check_batch(kgem, 3)) 86003b705cfSriastradh sna_blt_fill_begin(sna, blt); 86103b705cfSriastradh 86203b705cfSriastradh b = kgem->batch + kgem->nbatch; 86303b705cfSriastradh kgem->nbatch += 3; 86403b705cfSriastradh assert(kgem->nbatch < kgem->surface); 86503b705cfSriastradh 86603b705cfSriastradh b[0] = blt->cmd; 86703b705cfSriastradh *(uint64_t *)(b+1) = *(const uint64_t *)box; 86803b705cfSriastradh} 86903b705cfSriastradh 87003b705cfSriastradhinline static void _sna_blt_fill_boxes(struct sna *sna, 87103b705cfSriastradh const struct sna_blt_state *blt, 87203b705cfSriastradh const BoxRec *box, 87303b705cfSriastradh int nbox) 87403b705cfSriastradh{ 87503b705cfSriastradh struct kgem *kgem = &sna->kgem; 87603b705cfSriastradh uint32_t cmd = blt->cmd; 87703b705cfSriastradh 87803b705cfSriastradh DBG(("%s: %08x x %d\n", __FUNCTION__, blt->pixel, nbox)); 87903b705cfSriastradh 88003b705cfSriastradh if (!kgem_check_batch(kgem, 3)) 88103b705cfSriastradh sna_blt_fill_begin(sna, blt); 88203b705cfSriastradh 88303b705cfSriastradh do { 88403b705cfSriastradh uint32_t *b = kgem->batch + kgem->nbatch; 88503b705cfSriastradh int nbox_this_time; 88603b705cfSriastradh 88703b705cfSriastradh nbox_this_time = nbox; 88803b705cfSriastradh if (3*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) 88903b705cfSriastradh nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 3; 89003b705cfSriastradh assert(nbox_this_time); 89103b705cfSriastradh nbox -= nbox_this_time; 89203b705cfSriastradh 89303b705cfSriastradh kgem->nbatch += 3 * nbox_this_time; 89403b705cfSriastradh assert(kgem->nbatch < kgem->surface); 89503b705cfSriastradh while (nbox_this_time >= 8) { 89603b705cfSriastradh b[0] = cmd; *(uint64_t *)(b+1) = *(const uint64_t *)box++; 89703b705cfSriastradh b[3] = cmd; *(uint64_t *)(b+4) = *(const uint64_t *)box++; 89803b705cfSriastradh b[6] = cmd; *(uint64_t *)(b+7) = *(const uint64_t *)box++; 89903b705cfSriastradh b[9] = cmd; *(uint64_t *)(b+10) = *(const uint64_t *)box++; 90003b705cfSriastradh b[12] = cmd; *(uint64_t *)(b+13) = *(const uint64_t *)box++; 90103b705cfSriastradh b[15] = cmd; *(uint64_t *)(b+16) = *(const uint64_t *)box++; 90203b705cfSriastradh b[18] = cmd; *(uint64_t *)(b+19) = *(const uint64_t *)box++; 90303b705cfSriastradh b[21] = cmd; *(uint64_t *)(b+22) = *(const uint64_t *)box++; 90403b705cfSriastradh b += 24; 90503b705cfSriastradh nbox_this_time -= 8; 90603b705cfSriastradh } 90703b705cfSriastradh if (nbox_this_time & 4) { 90803b705cfSriastradh b[0] = cmd; *(uint64_t *)(b+1) = *(const uint64_t *)box++; 90903b705cfSriastradh b[3] = cmd; *(uint64_t *)(b+4) = *(const uint64_t *)box++; 91003b705cfSriastradh b[6] = cmd; *(uint64_t *)(b+7) = *(const uint64_t *)box++; 91103b705cfSriastradh b[9] = cmd; *(uint64_t *)(b+10) = *(const uint64_t *)box++; 91203b705cfSriastradh b += 12; 91303b705cfSriastradh } 91403b705cfSriastradh if (nbox_this_time & 2) { 91503b705cfSriastradh b[0] = cmd; *(uint64_t *)(b+1) = *(const uint64_t *)box++; 91603b705cfSriastradh b[3] = cmd; *(uint64_t *)(b+4) = *(const uint64_t *)box++; 91703b705cfSriastradh b += 6; 91803b705cfSriastradh } 91903b705cfSriastradh if (nbox_this_time & 1) { 92003b705cfSriastradh b[0] = cmd; *(uint64_t *)(b+1) = *(const uint64_t *)box++; 92103b705cfSriastradh } 92203b705cfSriastradh 92303b705cfSriastradh if (!nbox) 92403b705cfSriastradh return; 92503b705cfSriastradh 92603b705cfSriastradh sna_blt_fill_begin(sna, blt); 92703b705cfSriastradh } while (1); 92803b705cfSriastradh} 92903b705cfSriastradh 93003b705cfSriastradhfastcall static void blt_composite_fill_box_no_offset(struct sna *sna, 93103b705cfSriastradh const struct sna_composite_op *op, 93203b705cfSriastradh const BoxRec *box) 93303b705cfSriastradh{ 93403b705cfSriastradh _sna_blt_fill_box(sna, &op->u.blt, box); 93503b705cfSriastradh} 93603b705cfSriastradh 93703b705cfSriastradhstatic void blt_composite_fill_boxes_no_offset(struct sna *sna, 93803b705cfSriastradh const struct sna_composite_op *op, 93903b705cfSriastradh const BoxRec *box, int n) 94003b705cfSriastradh{ 94103b705cfSriastradh _sna_blt_fill_boxes(sna, &op->u.blt, box, n); 94203b705cfSriastradh} 94303b705cfSriastradh 94403b705cfSriastradhstatic void blt_composite_fill_boxes_no_offset__thread(struct sna *sna, 94503b705cfSriastradh const struct sna_composite_op *op, 94603b705cfSriastradh const BoxRec *box, int nbox) 94703b705cfSriastradh{ 94803b705cfSriastradh struct kgem *kgem = &sna->kgem; 94903b705cfSriastradh const struct sna_blt_state *blt = &op->u.blt; 95003b705cfSriastradh uint32_t cmd = blt->cmd; 95103b705cfSriastradh 95203b705cfSriastradh DBG(("%s: %08x x %d\n", __FUNCTION__, blt->pixel, nbox)); 95303b705cfSriastradh 95403b705cfSriastradh sna_vertex_lock(&sna->render); 95503b705cfSriastradh if (!kgem_check_batch(kgem, 3)) { 95603b705cfSriastradh sna_vertex_wait__locked(&sna->render); 95703b705cfSriastradh sna_blt_fill_begin(sna, blt); 95803b705cfSriastradh } 95903b705cfSriastradh 96003b705cfSriastradh do { 96103b705cfSriastradh uint32_t *b = kgem->batch + kgem->nbatch; 96203b705cfSriastradh int nbox_this_time; 96303b705cfSriastradh 96403b705cfSriastradh nbox_this_time = nbox; 96503b705cfSriastradh if (3*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) 96603b705cfSriastradh nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 3; 96703b705cfSriastradh assert(nbox_this_time); 96803b705cfSriastradh nbox -= nbox_this_time; 96903b705cfSriastradh 97003b705cfSriastradh kgem->nbatch += 3 * nbox_this_time; 97103b705cfSriastradh assert(kgem->nbatch < kgem->surface); 97203b705cfSriastradh sna_vertex_acquire__locked(&sna->render); 97303b705cfSriastradh sna_vertex_unlock(&sna->render); 97403b705cfSriastradh 97503b705cfSriastradh while (nbox_this_time >= 8) { 97603b705cfSriastradh b[0] = cmd; *(uint64_t *)(b+1) = *(const uint64_t *)box++; 97703b705cfSriastradh b[3] = cmd; *(uint64_t *)(b+4) = *(const uint64_t *)box++; 97803b705cfSriastradh b[6] = cmd; *(uint64_t *)(b+7) = *(const uint64_t *)box++; 97903b705cfSriastradh b[9] = cmd; *(uint64_t *)(b+10) = *(const uint64_t *)box++; 98003b705cfSriastradh b[12] = cmd; *(uint64_t *)(b+13) = *(const uint64_t *)box++; 98103b705cfSriastradh b[15] = cmd; *(uint64_t *)(b+16) = *(const uint64_t *)box++; 98203b705cfSriastradh b[18] = cmd; *(uint64_t *)(b+19) = *(const uint64_t *)box++; 98303b705cfSriastradh b[21] = cmd; *(uint64_t *)(b+22) = *(const uint64_t *)box++; 98403b705cfSriastradh b += 24; 98503b705cfSriastradh nbox_this_time -= 8; 98603b705cfSriastradh } 98703b705cfSriastradh if (nbox_this_time & 4) { 98803b705cfSriastradh b[0] = cmd; *(uint64_t *)(b+1) = *(const uint64_t *)box++; 98903b705cfSriastradh b[3] = cmd; *(uint64_t *)(b+4) = *(const uint64_t *)box++; 99003b705cfSriastradh b[6] = cmd; *(uint64_t *)(b+7) = *(const uint64_t *)box++; 99103b705cfSriastradh b[9] = cmd; *(uint64_t *)(b+10) = *(const uint64_t *)box++; 99203b705cfSriastradh b += 12; 99303b705cfSriastradh } 99403b705cfSriastradh if (nbox_this_time & 2) { 99503b705cfSriastradh b[0] = cmd; *(uint64_t *)(b+1) = *(const uint64_t *)box++; 99603b705cfSriastradh b[3] = cmd; *(uint64_t *)(b+4) = *(const uint64_t *)box++; 99703b705cfSriastradh b += 6; 99803b705cfSriastradh } 99903b705cfSriastradh if (nbox_this_time & 1) { 100003b705cfSriastradh b[0] = cmd; *(uint64_t *)(b+1) = *(const uint64_t *)box++; 100103b705cfSriastradh } 100203b705cfSriastradh 100303b705cfSriastradh sna_vertex_lock(&sna->render); 100403b705cfSriastradh sna_vertex_release__locked(&sna->render); 100503b705cfSriastradh if (!nbox) 100603b705cfSriastradh break; 100703b705cfSriastradh 100803b705cfSriastradh sna_vertex_wait__locked(&sna->render); 100903b705cfSriastradh sna_blt_fill_begin(sna, blt); 101003b705cfSriastradh } while (1); 101103b705cfSriastradh sna_vertex_unlock(&sna->render); 101203b705cfSriastradh} 101303b705cfSriastradh 101403b705cfSriastradhfastcall static void blt_composite_fill_box(struct sna *sna, 101503b705cfSriastradh const struct sna_composite_op *op, 101603b705cfSriastradh const BoxRec *box) 101703b705cfSriastradh{ 101803b705cfSriastradh sna_blt_fill_one(sna, &op->u.blt, 101903b705cfSriastradh box->x1 + op->dst.x, 102003b705cfSriastradh box->y1 + op->dst.y, 102103b705cfSriastradh box->x2 - box->x1, 102203b705cfSriastradh box->y2 - box->y1); 102303b705cfSriastradh} 102403b705cfSriastradh 102503b705cfSriastradhstatic void blt_composite_fill_boxes(struct sna *sna, 102603b705cfSriastradh const struct sna_composite_op *op, 102703b705cfSriastradh const BoxRec *box, int n) 102803b705cfSriastradh{ 102903b705cfSriastradh do { 103003b705cfSriastradh sna_blt_fill_one(sna, &op->u.blt, 103103b705cfSriastradh box->x1 + op->dst.x, box->y1 + op->dst.y, 103203b705cfSriastradh box->x2 - box->x1, box->y2 - box->y1); 103303b705cfSriastradh box++; 103403b705cfSriastradh } while (--n); 103503b705cfSriastradh} 103603b705cfSriastradh 103703b705cfSriastradhstatic inline uint64_t add4(const BoxRec *b, int16_t x, int16_t y) 103803b705cfSriastradh{ 103903b705cfSriastradh union { 104003b705cfSriastradh uint64_t v; 104103b705cfSriastradh int16_t i[4]; 104203b705cfSriastradh } vi; 104303b705cfSriastradh vi.v = *(uint64_t *)b; 104403b705cfSriastradh vi.i[0] += x; 104503b705cfSriastradh vi.i[1] += y; 104603b705cfSriastradh vi.i[2] += x; 104703b705cfSriastradh vi.i[3] += y; 104803b705cfSriastradh return vi.v; 104903b705cfSriastradh} 105003b705cfSriastradh 105103b705cfSriastradhstatic void blt_composite_fill_boxes__thread(struct sna *sna, 105203b705cfSriastradh const struct sna_composite_op *op, 105303b705cfSriastradh const BoxRec *box, int nbox) 105403b705cfSriastradh{ 105503b705cfSriastradh struct kgem *kgem = &sna->kgem; 105603b705cfSriastradh const struct sna_blt_state *blt = &op->u.blt; 105703b705cfSriastradh uint32_t cmd = blt->cmd; 105803b705cfSriastradh int16_t dx = op->dst.x; 105903b705cfSriastradh int16_t dy = op->dst.y; 106003b705cfSriastradh 106103b705cfSriastradh DBG(("%s: %08x x %d\n", __FUNCTION__, blt->pixel, nbox)); 106203b705cfSriastradh 106303b705cfSriastradh sna_vertex_lock(&sna->render); 106403b705cfSriastradh if (!kgem_check_batch(kgem, 3)) { 106503b705cfSriastradh sna_vertex_wait__locked(&sna->render); 106603b705cfSriastradh sna_blt_fill_begin(sna, blt); 106703b705cfSriastradh } 106803b705cfSriastradh 106903b705cfSriastradh do { 107003b705cfSriastradh uint32_t *b = kgem->batch + kgem->nbatch; 107103b705cfSriastradh int nbox_this_time; 107203b705cfSriastradh 107303b705cfSriastradh nbox_this_time = nbox; 107403b705cfSriastradh if (3*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) 107503b705cfSriastradh nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 3; 107603b705cfSriastradh assert(nbox_this_time); 107703b705cfSriastradh nbox -= nbox_this_time; 107803b705cfSriastradh 107903b705cfSriastradh kgem->nbatch += 3 * nbox_this_time; 108003b705cfSriastradh assert(kgem->nbatch < kgem->surface); 108103b705cfSriastradh sna_vertex_acquire__locked(&sna->render); 108203b705cfSriastradh sna_vertex_unlock(&sna->render); 108303b705cfSriastradh 108403b705cfSriastradh while (nbox_this_time >= 8) { 108503b705cfSriastradh b[0] = cmd; *(uint64_t *)(b+1) = add4(box++, dx, dy); 108603b705cfSriastradh b[3] = cmd; *(uint64_t *)(b+4) = add4(box++, dx, dy); 108703b705cfSriastradh b[6] = cmd; *(uint64_t *)(b+7) = add4(box++, dx, dy); 108803b705cfSriastradh b[9] = cmd; *(uint64_t *)(b+10) = add4(box++, dx, dy); 108903b705cfSriastradh b[12] = cmd; *(uint64_t *)(b+13) = add4(box++, dx, dy); 109003b705cfSriastradh b[15] = cmd; *(uint64_t *)(b+16) = add4(box++, dx, dy); 109103b705cfSriastradh b[18] = cmd; *(uint64_t *)(b+19) = add4(box++, dx, dy); 109203b705cfSriastradh b[21] = cmd; *(uint64_t *)(b+22) = add4(box++, dx, dy); 109303b705cfSriastradh b += 24; 109403b705cfSriastradh nbox_this_time -= 8; 109503b705cfSriastradh } 109603b705cfSriastradh if (nbox_this_time & 4) { 109703b705cfSriastradh b[0] = cmd; *(uint64_t *)(b+1) = add4(box++, dx, dy); 109803b705cfSriastradh b[3] = cmd; *(uint64_t *)(b+4) = add4(box++, dx, dy); 109903b705cfSriastradh b[6] = cmd; *(uint64_t *)(b+7) = add4(box++, dx, dy); 110003b705cfSriastradh b[9] = cmd; *(uint64_t *)(b+10) = add4(box++, dx, dy); 110103b705cfSriastradh b += 12; 110203b705cfSriastradh } 110303b705cfSriastradh if (nbox_this_time & 2) { 110403b705cfSriastradh b[0] = cmd; *(uint64_t *)(b+1) = add4(box++, dx, dy); 110503b705cfSriastradh b[3] = cmd; *(uint64_t *)(b+4) = add4(box++, dx, dy); 110603b705cfSriastradh b += 6; 110703b705cfSriastradh } 110803b705cfSriastradh if (nbox_this_time & 1) { 110903b705cfSriastradh b[0] = cmd; *(uint64_t *)(b+1) = add4(box++, dx, dy); 111003b705cfSriastradh } 111103b705cfSriastradh 111203b705cfSriastradh sna_vertex_lock(&sna->render); 111303b705cfSriastradh sna_vertex_release__locked(&sna->render); 111403b705cfSriastradh if (!nbox) 111503b705cfSriastradh break; 111603b705cfSriastradh 111703b705cfSriastradh sna_vertex_wait__locked(&sna->render); 111803b705cfSriastradh sna_blt_fill_begin(sna, blt); 111903b705cfSriastradh } while (1); 112003b705cfSriastradh sna_vertex_unlock(&sna->render); 112103b705cfSriastradh} 112203b705cfSriastradh 112303b705cfSriastradhfastcall 112403b705cfSriastradhstatic void blt_composite_nop(struct sna *sna, 112503b705cfSriastradh const struct sna_composite_op *op, 112603b705cfSriastradh const struct sna_composite_rectangles *r) 112703b705cfSriastradh{ 112803b705cfSriastradh} 112903b705cfSriastradh 113003b705cfSriastradhfastcall static void blt_composite_nop_box(struct sna *sna, 113103b705cfSriastradh const struct sna_composite_op *op, 113203b705cfSriastradh const BoxRec *box) 113303b705cfSriastradh{ 113403b705cfSriastradh} 113503b705cfSriastradh 113603b705cfSriastradhstatic void blt_composite_nop_boxes(struct sna *sna, 113703b705cfSriastradh const struct sna_composite_op *op, 113803b705cfSriastradh const BoxRec *box, int n) 113903b705cfSriastradh{ 114003b705cfSriastradh} 114103b705cfSriastradh 114203b705cfSriastradhstatic bool 114303b705cfSriastradhbegin_blt(struct sna *sna, 114403b705cfSriastradh struct sna_composite_op *op) 114503b705cfSriastradh{ 114603b705cfSriastradh if (!kgem_check_bo_fenced(&sna->kgem, op->dst.bo)) { 114703b705cfSriastradh kgem_submit(&sna->kgem); 114803b705cfSriastradh if (!kgem_check_bo_fenced(&sna->kgem, op->dst.bo)) 114903b705cfSriastradh return false; 115003b705cfSriastradh 115103b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_BLT); 115203b705cfSriastradh } 115303b705cfSriastradh 115403b705cfSriastradh return true; 115503b705cfSriastradh} 115603b705cfSriastradh 115703b705cfSriastradhstatic bool 115803b705cfSriastradhprepare_blt_nop(struct sna *sna, 115903b705cfSriastradh struct sna_composite_op *op) 116003b705cfSriastradh{ 116103b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 116203b705cfSriastradh 116303b705cfSriastradh op->blt = blt_composite_nop; 116403b705cfSriastradh op->box = blt_composite_nop_box; 116503b705cfSriastradh op->boxes = blt_composite_nop_boxes; 116603b705cfSriastradh op->done = nop_done; 116703b705cfSriastradh return true; 116803b705cfSriastradh} 116903b705cfSriastradh 117003b705cfSriastradhstatic bool 117103b705cfSriastradhprepare_blt_clear(struct sna *sna, 117203b705cfSriastradh struct sna_composite_op *op) 117303b705cfSriastradh{ 117403b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 117503b705cfSriastradh 117603b705cfSriastradh if (op->dst.bo == NULL) { 117703b705cfSriastradh op->blt = blt_composite_fill__cpu; 117803b705cfSriastradh op->box = blt_composite_fill_box__cpu; 117903b705cfSriastradh op->boxes = blt_composite_fill_boxes__cpu; 118003b705cfSriastradh op->thread_boxes = blt_composite_fill_boxes__cpu; 118103b705cfSriastradh op->done = nop_done; 118203b705cfSriastradh op->u.blt.pixel = 0; 118303b705cfSriastradh return true; 118403b705cfSriastradh } 118503b705cfSriastradh 118603b705cfSriastradh op->blt = blt_composite_fill; 118703b705cfSriastradh if (op->dst.x|op->dst.y) { 118803b705cfSriastradh op->box = blt_composite_fill_box; 118903b705cfSriastradh op->boxes = blt_composite_fill_boxes; 119003b705cfSriastradh op->thread_boxes = blt_composite_fill_boxes__thread; 119103b705cfSriastradh } else { 119203b705cfSriastradh op->box = blt_composite_fill_box_no_offset; 119303b705cfSriastradh op->boxes = blt_composite_fill_boxes_no_offset; 119403b705cfSriastradh op->thread_boxes = blt_composite_fill_boxes_no_offset__thread; 119503b705cfSriastradh } 119603b705cfSriastradh op->done = nop_done; 119703b705cfSriastradh 119803b705cfSriastradh if (!sna_blt_fill_init(sna, &op->u.blt, 119903b705cfSriastradh op->dst.bo, 120003b705cfSriastradh op->dst.pixmap->drawable.bitsPerPixel, 120103b705cfSriastradh GXclear, 0)) 120203b705cfSriastradh return false; 120303b705cfSriastradh 120403b705cfSriastradh return begin_blt(sna, op); 120503b705cfSriastradh} 120603b705cfSriastradh 120703b705cfSriastradhstatic bool 120803b705cfSriastradhprepare_blt_fill(struct sna *sna, 120903b705cfSriastradh struct sna_composite_op *op, 121003b705cfSriastradh uint32_t pixel) 121103b705cfSriastradh{ 121203b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 121303b705cfSriastradh 121403b705cfSriastradh if (op->dst.bo == NULL) { 121503b705cfSriastradh op->u.blt.pixel = pixel; 121603b705cfSriastradh op->blt = blt_composite_fill__cpu; 121703b705cfSriastradh op->box = blt_composite_fill_box__cpu; 121803b705cfSriastradh op->boxes = blt_composite_fill_boxes__cpu; 121903b705cfSriastradh op->thread_boxes = blt_composite_fill_boxes__cpu; 122003b705cfSriastradh op->done = nop_done; 122103b705cfSriastradh return true; 122203b705cfSriastradh } 122303b705cfSriastradh 122403b705cfSriastradh op->blt = blt_composite_fill; 122503b705cfSriastradh if (op->dst.x|op->dst.y) { 122603b705cfSriastradh op->box = blt_composite_fill_box; 122703b705cfSriastradh op->boxes = blt_composite_fill_boxes; 122803b705cfSriastradh op->thread_boxes = blt_composite_fill_boxes__thread; 122903b705cfSriastradh } else { 123003b705cfSriastradh op->box = blt_composite_fill_box_no_offset; 123103b705cfSriastradh op->boxes = blt_composite_fill_boxes_no_offset; 123203b705cfSriastradh op->thread_boxes = blt_composite_fill_boxes_no_offset__thread; 123303b705cfSriastradh } 123403b705cfSriastradh op->done = nop_done; 123503b705cfSriastradh 123603b705cfSriastradh if (!sna_blt_fill_init(sna, &op->u.blt, op->dst.bo, 123703b705cfSriastradh op->dst.pixmap->drawable.bitsPerPixel, 123803b705cfSriastradh GXcopy, pixel)) 123903b705cfSriastradh return false; 124003b705cfSriastradh 124103b705cfSriastradh return begin_blt(sna, op); 124203b705cfSriastradh} 124303b705cfSriastradh 124403b705cfSriastradhfastcall static void 124503b705cfSriastradhblt_composite_copy(struct sna *sna, 124603b705cfSriastradh const struct sna_composite_op *op, 124703b705cfSriastradh const struct sna_composite_rectangles *r) 124803b705cfSriastradh{ 124903b705cfSriastradh int x1, x2, y1, y2; 125003b705cfSriastradh int src_x, src_y; 125103b705cfSriastradh 125203b705cfSriastradh DBG(("%s: src=(%d, %d), dst=(%d, %d), size=(%d, %d)\n", 125303b705cfSriastradh __FUNCTION__, 125403b705cfSriastradh r->src.x, r->src.y, 125503b705cfSriastradh r->dst.x, r->dst.y, 125603b705cfSriastradh r->width, r->height)); 125703b705cfSriastradh 125803b705cfSriastradh /* XXX higher layer should have clipped? */ 125903b705cfSriastradh 126003b705cfSriastradh x1 = r->dst.x + op->dst.x; 126103b705cfSriastradh y1 = r->dst.y + op->dst.y; 126203b705cfSriastradh x2 = x1 + r->width; 126303b705cfSriastradh y2 = y1 + r->height; 126403b705cfSriastradh 126503b705cfSriastradh src_x = r->src.x - x1; 126603b705cfSriastradh src_y = r->src.y - y1; 126703b705cfSriastradh 126803b705cfSriastradh /* clip against dst */ 126903b705cfSriastradh if (x1 < 0) 127003b705cfSriastradh x1 = 0; 127103b705cfSriastradh if (y1 < 0) 127203b705cfSriastradh y1 = 0; 127303b705cfSriastradh 127403b705cfSriastradh if (x2 > op->dst.width) 127503b705cfSriastradh x2 = op->dst.width; 127603b705cfSriastradh 127703b705cfSriastradh if (y2 > op->dst.height) 127803b705cfSriastradh y2 = op->dst.height; 127903b705cfSriastradh 128003b705cfSriastradh DBG(("%s: box=(%d, %d), (%d, %d)\n", __FUNCTION__, x1, y1, x2, y2)); 128103b705cfSriastradh 128203b705cfSriastradh if (x2 <= x1 || y2 <= y1) 128303b705cfSriastradh return; 128403b705cfSriastradh 128503b705cfSriastradh sna_blt_copy_one(sna, &op->u.blt, 128603b705cfSriastradh x1 + src_x, y1 + src_y, 128703b705cfSriastradh x2 - x1, y2 - y1, 128803b705cfSriastradh x1, y1); 128903b705cfSriastradh} 129003b705cfSriastradh 129103b705cfSriastradhfastcall static void blt_composite_copy_box(struct sna *sna, 129203b705cfSriastradh const struct sna_composite_op *op, 129303b705cfSriastradh const BoxRec *box) 129403b705cfSriastradh{ 129503b705cfSriastradh DBG(("%s: box (%d, %d), (%d, %d)\n", 129603b705cfSriastradh __FUNCTION__, box->x1, box->y1, box->x2, box->y2)); 129703b705cfSriastradh sna_blt_copy_one(sna, &op->u.blt, 129803b705cfSriastradh box->x1 + op->u.blt.sx, 129903b705cfSriastradh box->y1 + op->u.blt.sy, 130003b705cfSriastradh box->x2 - box->x1, 130103b705cfSriastradh box->y2 - box->y1, 130203b705cfSriastradh box->x1 + op->dst.x, 130303b705cfSriastradh box->y1 + op->dst.y); 130403b705cfSriastradh} 130503b705cfSriastradh 130603b705cfSriastradhstatic void blt_composite_copy_boxes(struct sna *sna, 130703b705cfSriastradh const struct sna_composite_op *op, 130803b705cfSriastradh const BoxRec *box, int nbox) 130903b705cfSriastradh{ 131003b705cfSriastradh DBG(("%s: nbox=%d\n", __FUNCTION__, nbox)); 131103b705cfSriastradh do { 131203b705cfSriastradh DBG(("%s: box (%d, %d), (%d, %d)\n", 131303b705cfSriastradh __FUNCTION__, box->x1, box->y1, box->x2, box->y2)); 131403b705cfSriastradh sna_blt_copy_one(sna, &op->u.blt, 131503b705cfSriastradh box->x1 + op->u.blt.sx, box->y1 + op->u.blt.sy, 131603b705cfSriastradh box->x2 - box->x1, box->y2 - box->y1, 131703b705cfSriastradh box->x1 + op->dst.x, box->y1 + op->dst.y); 131803b705cfSriastradh box++; 131903b705cfSriastradh } while(--nbox); 132003b705cfSriastradh} 132103b705cfSriastradh 132203b705cfSriastradhstatic inline uint32_t add2(uint32_t v, int16_t x, int16_t y) 132303b705cfSriastradh{ 132403b705cfSriastradh x += v & 0xffff; 132503b705cfSriastradh y += v >> 16; 132603b705cfSriastradh return (uint16_t)y << 16 | x; 132703b705cfSriastradh} 132803b705cfSriastradh 132903b705cfSriastradhstatic void blt_composite_copy_boxes__thread(struct sna *sna, 133003b705cfSriastradh const struct sna_composite_op *op, 133103b705cfSriastradh const BoxRec *box, int nbox) 133203b705cfSriastradh{ 133303b705cfSriastradh struct kgem *kgem = &sna->kgem; 133403b705cfSriastradh int dst_dx = op->dst.x; 133503b705cfSriastradh int dst_dy = op->dst.y; 133603b705cfSriastradh int src_dx = op->src.offset[0]; 133703b705cfSriastradh int src_dy = op->src.offset[1]; 133803b705cfSriastradh uint32_t cmd = op->u.blt.cmd; 133903b705cfSriastradh uint32_t br13 = op->u.blt.br13; 134003b705cfSriastradh struct kgem_bo *src_bo = op->u.blt.bo[0]; 134103b705cfSriastradh struct kgem_bo *dst_bo = op->u.blt.bo[1]; 134203b705cfSriastradh int src_pitch = op->u.blt.pitch[0]; 134303b705cfSriastradh 134403b705cfSriastradh DBG(("%s: nbox=%d\n", __FUNCTION__, nbox)); 134503b705cfSriastradh 134603b705cfSriastradh sna_vertex_lock(&sna->render); 134703b705cfSriastradh 134803b705cfSriastradh if ((dst_dx | dst_dy) == 0) { 134903b705cfSriastradh uint64_t hdr = (uint64_t)br13 << 32 | cmd; 135003b705cfSriastradh do { 135103b705cfSriastradh int nbox_this_time; 135203b705cfSriastradh 135303b705cfSriastradh nbox_this_time = nbox; 135403b705cfSriastradh if (8*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) 135503b705cfSriastradh nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; 135603b705cfSriastradh if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) 135703b705cfSriastradh nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc)/2; 135803b705cfSriastradh assert(nbox_this_time); 135903b705cfSriastradh nbox -= nbox_this_time; 136003b705cfSriastradh 136103b705cfSriastradh do { 136203b705cfSriastradh uint32_t *b = kgem->batch + kgem->nbatch; 136303b705cfSriastradh 136403b705cfSriastradh DBG((" %s: box=(%d, %d)x(%d, %d)\n", 136503b705cfSriastradh __FUNCTION__, 136603b705cfSriastradh box->x1, box->y1, 136703b705cfSriastradh box->x2 - box->x1, box->y2 - box->y1)); 136803b705cfSriastradh 136903b705cfSriastradh assert(box->x1 + src_dx >= 0); 137003b705cfSriastradh assert(box->y1 + src_dy >= 0); 137103b705cfSriastradh assert(box->x1 + src_dx <= INT16_MAX); 137203b705cfSriastradh assert(box->y1 + src_dy <= INT16_MAX); 137303b705cfSriastradh 137403b705cfSriastradh assert(box->x1 >= 0); 137503b705cfSriastradh assert(box->y1 >= 0); 137603b705cfSriastradh 137703b705cfSriastradh *(uint64_t *)&b[0] = hdr; 137803b705cfSriastradh *(uint64_t *)&b[2] = *(const uint64_t *)box; 137903b705cfSriastradh b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, dst_bo, 138003b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 138103b705cfSriastradh I915_GEM_DOMAIN_RENDER | 138203b705cfSriastradh KGEM_RELOC_FENCED, 138303b705cfSriastradh 0); 138403b705cfSriastradh b[5] = add2(b[2], src_dx, src_dy); 138503b705cfSriastradh b[6] = src_pitch; 138603b705cfSriastradh b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7, src_bo, 138703b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 138803b705cfSriastradh KGEM_RELOC_FENCED, 138903b705cfSriastradh 0); 139003b705cfSriastradh kgem->nbatch += 8; 139103b705cfSriastradh assert(kgem->nbatch < kgem->surface); 139203b705cfSriastradh box++; 139303b705cfSriastradh } while (--nbox_this_time); 139403b705cfSriastradh 139503b705cfSriastradh if (!nbox) 139603b705cfSriastradh break; 139703b705cfSriastradh 139803b705cfSriastradh _kgem_submit(kgem); 139903b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 140003b705cfSriastradh } while (1); 140103b705cfSriastradh } else { 140203b705cfSriastradh do { 140303b705cfSriastradh int nbox_this_time; 140403b705cfSriastradh 140503b705cfSriastradh nbox_this_time = nbox; 140603b705cfSriastradh if (8*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) 140703b705cfSriastradh nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; 140803b705cfSriastradh if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) 140903b705cfSriastradh nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc)/2; 141003b705cfSriastradh assert(nbox_this_time); 141103b705cfSriastradh nbox -= nbox_this_time; 141203b705cfSriastradh 141303b705cfSriastradh do { 141403b705cfSriastradh uint32_t *b = kgem->batch + kgem->nbatch; 141503b705cfSriastradh 141603b705cfSriastradh DBG((" %s: box=(%d, %d)x(%d, %d)\n", 141703b705cfSriastradh __FUNCTION__, 141803b705cfSriastradh box->x1, box->y1, 141903b705cfSriastradh box->x2 - box->x1, box->y2 - box->y1)); 142003b705cfSriastradh 142103b705cfSriastradh assert(box->x1 + src_dx >= 0); 142203b705cfSriastradh assert(box->y1 + src_dy >= 0); 142303b705cfSriastradh 142403b705cfSriastradh assert(box->x1 + dst_dx >= 0); 142503b705cfSriastradh assert(box->y1 + dst_dy >= 0); 142603b705cfSriastradh 142703b705cfSriastradh b[0] = cmd; 142803b705cfSriastradh b[1] = br13; 142903b705cfSriastradh b[2] = ((box->y1 + dst_dy) << 16) | (box->x1 + dst_dx); 143003b705cfSriastradh b[3] = ((box->y2 + dst_dy) << 16) | (box->x2 + dst_dx); 143103b705cfSriastradh b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, dst_bo, 143203b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 143303b705cfSriastradh I915_GEM_DOMAIN_RENDER | 143403b705cfSriastradh KGEM_RELOC_FENCED, 143503b705cfSriastradh 0); 143603b705cfSriastradh b[5] = ((box->y1 + src_dy) << 16) | (box->x1 + src_dx); 143703b705cfSriastradh b[6] = src_pitch; 143803b705cfSriastradh b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7, src_bo, 143903b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 144003b705cfSriastradh KGEM_RELOC_FENCED, 144103b705cfSriastradh 0); 144203b705cfSriastradh kgem->nbatch += 8; 144303b705cfSriastradh assert(kgem->nbatch < kgem->surface); 144403b705cfSriastradh box++; 144503b705cfSriastradh } while (--nbox_this_time); 144603b705cfSriastradh 144703b705cfSriastradh if (!nbox) 144803b705cfSriastradh break; 144903b705cfSriastradh 145003b705cfSriastradh _kgem_submit(kgem); 145103b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 145203b705cfSriastradh } while (1); 145303b705cfSriastradh } 145403b705cfSriastradh sna_vertex_unlock(&sna->render); 145503b705cfSriastradh} 145603b705cfSriastradh 145703b705cfSriastradhfastcall static void 145803b705cfSriastradhblt_composite_copy_with_alpha(struct sna *sna, 145903b705cfSriastradh const struct sna_composite_op *op, 146003b705cfSriastradh const struct sna_composite_rectangles *r) 146103b705cfSriastradh{ 146203b705cfSriastradh int x1, x2, y1, y2; 146303b705cfSriastradh int src_x, src_y; 146403b705cfSriastradh 146503b705cfSriastradh DBG(("%s: src=(%d, %d), dst=(%d, %d), size=(%d, %d)\n", 146603b705cfSriastradh __FUNCTION__, 146703b705cfSriastradh r->src.x, r->src.y, 146803b705cfSriastradh r->dst.x, r->dst.y, 146903b705cfSriastradh r->width, r->height)); 147003b705cfSriastradh 147103b705cfSriastradh /* XXX higher layer should have clipped? */ 147203b705cfSriastradh 147303b705cfSriastradh x1 = r->dst.x + op->dst.x; 147403b705cfSriastradh y1 = r->dst.y + op->dst.y; 147503b705cfSriastradh x2 = x1 + r->width; 147603b705cfSriastradh y2 = y1 + r->height; 147703b705cfSriastradh 147803b705cfSriastradh src_x = r->src.x - x1; 147903b705cfSriastradh src_y = r->src.y - y1; 148003b705cfSriastradh 148103b705cfSriastradh /* clip against dst */ 148203b705cfSriastradh if (x1 < 0) 148303b705cfSriastradh x1 = 0; 148403b705cfSriastradh if (y1 < 0) 148503b705cfSriastradh y1 = 0; 148603b705cfSriastradh 148703b705cfSriastradh if (x2 > op->dst.width) 148803b705cfSriastradh x2 = op->dst.width; 148903b705cfSriastradh 149003b705cfSriastradh if (y2 > op->dst.height) 149103b705cfSriastradh y2 = op->dst.height; 149203b705cfSriastradh 149303b705cfSriastradh DBG(("%s: box=(%d, %d), (%d, %d)\n", __FUNCTION__, x1, y1, x2, y2)); 149403b705cfSriastradh 149503b705cfSriastradh if (x2 <= x1 || y2 <= y1) 149603b705cfSriastradh return; 149703b705cfSriastradh 149803b705cfSriastradh sna_blt_alpha_fixup_one(sna, &op->u.blt, 149903b705cfSriastradh x1 + src_x, y1 + src_y, 150003b705cfSriastradh x2 - x1, y2 - y1, 150103b705cfSriastradh x1, y1); 150203b705cfSriastradh} 150303b705cfSriastradh 150403b705cfSriastradhfastcall static void 150503b705cfSriastradhblt_composite_copy_box_with_alpha(struct sna *sna, 150603b705cfSriastradh const struct sna_composite_op *op, 150703b705cfSriastradh const BoxRec *box) 150803b705cfSriastradh{ 150903b705cfSriastradh DBG(("%s: box (%d, %d), (%d, %d)\n", 151003b705cfSriastradh __FUNCTION__, box->x1, box->y1, box->x2, box->y2)); 151103b705cfSriastradh sna_blt_alpha_fixup_one(sna, &op->u.blt, 151203b705cfSriastradh box->x1 + op->u.blt.sx, 151303b705cfSriastradh box->y1 + op->u.blt.sy, 151403b705cfSriastradh box->x2 - box->x1, 151503b705cfSriastradh box->y2 - box->y1, 151603b705cfSriastradh box->x1 + op->dst.x, 151703b705cfSriastradh box->y1 + op->dst.y); 151803b705cfSriastradh} 151903b705cfSriastradh 152003b705cfSriastradhstatic void 152103b705cfSriastradhblt_composite_copy_boxes_with_alpha(struct sna *sna, 152203b705cfSriastradh const struct sna_composite_op *op, 152303b705cfSriastradh const BoxRec *box, int nbox) 152403b705cfSriastradh{ 152503b705cfSriastradh DBG(("%s: nbox=%d\n", __FUNCTION__, nbox)); 152603b705cfSriastradh do { 152703b705cfSriastradh DBG(("%s: box (%d, %d), (%d, %d)\n", 152803b705cfSriastradh __FUNCTION__, box->x1, box->y1, box->x2, box->y2)); 152903b705cfSriastradh sna_blt_alpha_fixup_one(sna, &op->u.blt, 153003b705cfSriastradh box->x1 + op->u.blt.sx, box->y1 + op->u.blt.sy, 153103b705cfSriastradh box->x2 - box->x1, box->y2 - box->y1, 153203b705cfSriastradh box->x1 + op->dst.x, box->y1 + op->dst.y); 153303b705cfSriastradh box++; 153403b705cfSriastradh } while(--nbox); 153503b705cfSriastradh} 153603b705cfSriastradh 153703b705cfSriastradhstatic bool 153803b705cfSriastradhprepare_blt_copy(struct sna *sna, 153903b705cfSriastradh struct sna_composite_op *op, 154003b705cfSriastradh struct kgem_bo *bo, 154103b705cfSriastradh uint32_t alpha_fixup) 154203b705cfSriastradh{ 154303b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 154403b705cfSriastradh 154503b705cfSriastradh assert(op->dst.bo); 154603b705cfSriastradh assert(kgem_bo_can_blt(&sna->kgem, op->dst.bo)); 154703b705cfSriastradh assert(kgem_bo_can_blt(&sna->kgem, bo)); 154803b705cfSriastradh 154903b705cfSriastradh if (!kgem_check_many_bo_fenced(&sna->kgem, op->dst.bo, bo, NULL)) { 155003b705cfSriastradh kgem_submit(&sna->kgem); 155103b705cfSriastradh if (!kgem_check_many_bo_fenced(&sna->kgem, 155203b705cfSriastradh op->dst.bo, bo, NULL)) { 155303b705cfSriastradh DBG(("%s: fallback -- no room in aperture\n", __FUNCTION__)); 155403b705cfSriastradh return false; 155503b705cfSriastradh } 155603b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_BLT); 155703b705cfSriastradh } 155803b705cfSriastradh 155903b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 156003b705cfSriastradh 156103b705cfSriastradh if (sna->kgem.gen >= 060 && op->dst.bo == bo) 156203b705cfSriastradh op->done = gen6_blt_copy_done; 156303b705cfSriastradh else 156403b705cfSriastradh op->done = nop_done; 156503b705cfSriastradh 156603b705cfSriastradh if (alpha_fixup) { 156703b705cfSriastradh op->blt = blt_composite_copy_with_alpha; 156803b705cfSriastradh op->box = blt_composite_copy_box_with_alpha; 156903b705cfSriastradh op->boxes = blt_composite_copy_boxes_with_alpha; 157003b705cfSriastradh 157103b705cfSriastradh if (!sna_blt_alpha_fixup_init(sna, &op->u.blt, bo, op->dst.bo, 157203b705cfSriastradh src->drawable.bitsPerPixel, 157303b705cfSriastradh alpha_fixup)) 157403b705cfSriastradh return false; 157503b705cfSriastradh } else { 157603b705cfSriastradh op->blt = blt_composite_copy; 157703b705cfSriastradh op->box = blt_composite_copy_box; 157803b705cfSriastradh op->boxes = blt_composite_copy_boxes; 157903b705cfSriastradh op->thread_boxes = blt_composite_copy_boxes__thread; 158003b705cfSriastradh 158103b705cfSriastradh if (!sna_blt_copy_init(sna, &op->u.blt, bo, op->dst.bo, 158203b705cfSriastradh src->drawable.bitsPerPixel, 158303b705cfSriastradh GXcopy)) 158403b705cfSriastradh return false; 158503b705cfSriastradh } 158603b705cfSriastradh 158703b705cfSriastradh return true; 158803b705cfSriastradh} 158903b705cfSriastradh 159003b705cfSriastradhfastcall static void 159103b705cfSriastradhblt_put_composite__cpu(struct sna *sna, 159203b705cfSriastradh const struct sna_composite_op *op, 159303b705cfSriastradh const struct sna_composite_rectangles *r) 159403b705cfSriastradh{ 159503b705cfSriastradh PixmapPtr dst = op->dst.pixmap; 159603b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 159703b705cfSriastradh memcpy_blt(src->devPrivate.ptr, dst->devPrivate.ptr, 159803b705cfSriastradh src->drawable.bitsPerPixel, src->devKind, dst->devKind, 159903b705cfSriastradh r->src.x + op->u.blt.sx, r->src.y + op->u.blt.sy, 160003b705cfSriastradh r->dst.x + op->dst.x, r->dst.y + op->dst.y, 160103b705cfSriastradh r->width, r->height); 160203b705cfSriastradh} 160303b705cfSriastradh 160403b705cfSriastradhfastcall static void 160503b705cfSriastradhblt_put_composite_box__cpu(struct sna *sna, 160603b705cfSriastradh const struct sna_composite_op *op, 160703b705cfSriastradh const BoxRec *box) 160803b705cfSriastradh{ 160903b705cfSriastradh PixmapPtr dst = op->dst.pixmap; 161003b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 161103b705cfSriastradh memcpy_blt(src->devPrivate.ptr, dst->devPrivate.ptr, 161203b705cfSriastradh src->drawable.bitsPerPixel, src->devKind, dst->devKind, 161303b705cfSriastradh box->x1 + op->u.blt.sx, box->y1 + op->u.blt.sy, 161403b705cfSriastradh box->x1 + op->dst.x, box->y1 + op->dst.y, 161503b705cfSriastradh box->x2-box->x1, box->y2-box->y1); 161603b705cfSriastradh} 161703b705cfSriastradh 161803b705cfSriastradhstatic void 161903b705cfSriastradhblt_put_composite_boxes__cpu(struct sna *sna, 162003b705cfSriastradh const struct sna_composite_op *op, 162103b705cfSriastradh const BoxRec *box, int n) 162203b705cfSriastradh{ 162303b705cfSriastradh PixmapPtr dst = op->dst.pixmap; 162403b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 162503b705cfSriastradh do { 162603b705cfSriastradh memcpy_blt(src->devPrivate.ptr, dst->devPrivate.ptr, 162703b705cfSriastradh src->drawable.bitsPerPixel, src->devKind, dst->devKind, 162803b705cfSriastradh box->x1 + op->u.blt.sx, box->y1 + op->u.blt.sy, 162903b705cfSriastradh box->x1 + op->dst.x, box->y1 + op->dst.y, 163003b705cfSriastradh box->x2-box->x1, box->y2-box->y1); 163103b705cfSriastradh box++; 163203b705cfSriastradh } while (--n); 163303b705cfSriastradh} 163403b705cfSriastradh 163503b705cfSriastradhfastcall static void 163603b705cfSriastradhblt_put_composite_with_alpha__cpu(struct sna *sna, 163703b705cfSriastradh const struct sna_composite_op *op, 163803b705cfSriastradh const struct sna_composite_rectangles *r) 163903b705cfSriastradh{ 164003b705cfSriastradh PixmapPtr dst = op->dst.pixmap; 164103b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 164203b705cfSriastradh memcpy_xor(src->devPrivate.ptr, dst->devPrivate.ptr, 164303b705cfSriastradh src->drawable.bitsPerPixel, src->devKind, dst->devKind, 164403b705cfSriastradh r->src.x + op->u.blt.sx, r->src.y + op->u.blt.sy, 164503b705cfSriastradh r->dst.x + op->dst.x, r->dst.y + op->dst.y, 164603b705cfSriastradh r->width, r->height, 164703b705cfSriastradh 0xffffffff, op->u.blt.pixel); 164803b705cfSriastradh 164903b705cfSriastradh} 165003b705cfSriastradh 165103b705cfSriastradhfastcall static void 165203b705cfSriastradhblt_put_composite_box_with_alpha__cpu(struct sna *sna, 165303b705cfSriastradh const struct sna_composite_op *op, 165403b705cfSriastradh const BoxRec *box) 165503b705cfSriastradh{ 165603b705cfSriastradh PixmapPtr dst = op->dst.pixmap; 165703b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 165803b705cfSriastradh memcpy_xor(src->devPrivate.ptr, dst->devPrivate.ptr, 165903b705cfSriastradh src->drawable.bitsPerPixel, src->devKind, dst->devKind, 166003b705cfSriastradh box->x1 + op->u.blt.sx, box->y1 + op->u.blt.sy, 166103b705cfSriastradh box->x1 + op->dst.x, box->y1 + op->dst.y, 166203b705cfSriastradh box->x2-box->x1, box->y2-box->y1, 166303b705cfSriastradh 0xffffffff, op->u.blt.pixel); 166403b705cfSriastradh} 166503b705cfSriastradh 166603b705cfSriastradhstatic void 166703b705cfSriastradhblt_put_composite_boxes_with_alpha__cpu(struct sna *sna, 166803b705cfSriastradh const struct sna_composite_op *op, 166903b705cfSriastradh const BoxRec *box, int n) 167003b705cfSriastradh{ 167103b705cfSriastradh PixmapPtr dst = op->dst.pixmap; 167203b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 167303b705cfSriastradh do { 167403b705cfSriastradh memcpy_xor(src->devPrivate.ptr, dst->devPrivate.ptr, 167503b705cfSriastradh src->drawable.bitsPerPixel, src->devKind, dst->devKind, 167603b705cfSriastradh box->x1 + op->u.blt.sx, box->y1 + op->u.blt.sy, 167703b705cfSriastradh box->x1 + op->dst.x, box->y1 + op->dst.y, 167803b705cfSriastradh box->x2-box->x1, box->y2-box->y1, 167903b705cfSriastradh 0xffffffff, op->u.blt.pixel); 168003b705cfSriastradh box++; 168103b705cfSriastradh } while (--n); 168203b705cfSriastradh} 168303b705cfSriastradh 168403b705cfSriastradhfastcall static void 168503b705cfSriastradhblt_put_composite(struct sna *sna, 168603b705cfSriastradh const struct sna_composite_op *op, 168703b705cfSriastradh const struct sna_composite_rectangles *r) 168803b705cfSriastradh{ 168903b705cfSriastradh PixmapPtr dst = op->dst.pixmap; 169003b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 169103b705cfSriastradh struct sna_pixmap *dst_priv = sna_pixmap(dst); 169203b705cfSriastradh int pitch = src->devKind; 169303b705cfSriastradh char *data = src->devPrivate.ptr; 169403b705cfSriastradh int bpp = src->drawable.bitsPerPixel; 169503b705cfSriastradh 169603b705cfSriastradh int16_t dst_x = r->dst.x + op->dst.x; 169703b705cfSriastradh int16_t dst_y = r->dst.y + op->dst.y; 169803b705cfSriastradh int16_t src_x = r->src.x + op->u.blt.sx; 169903b705cfSriastradh int16_t src_y = r->src.y + op->u.blt.sy; 170003b705cfSriastradh 170103b705cfSriastradh if (!dst_priv->pinned && 170203b705cfSriastradh dst_x <= 0 && dst_y <= 0 && 170303b705cfSriastradh dst_x + r->width >= op->dst.width && 170403b705cfSriastradh dst_y + r->height >= op->dst.height) { 170503b705cfSriastradh data += (src_x - dst_x) * bpp / 8; 170603b705cfSriastradh data += (src_y - dst_y) * pitch; 170703b705cfSriastradh 170803b705cfSriastradh sna_replace(sna, op->dst.pixmap, &dst_priv->gpu_bo, 170903b705cfSriastradh data, pitch); 171003b705cfSriastradh } else { 171103b705cfSriastradh BoxRec box; 171203b705cfSriastradh bool ok; 171303b705cfSriastradh 171403b705cfSriastradh box.x1 = dst_x; 171503b705cfSriastradh box.y1 = dst_y; 171603b705cfSriastradh box.x2 = dst_x + r->width; 171703b705cfSriastradh box.y2 = dst_y + r->height; 171803b705cfSriastradh 171903b705cfSriastradh ok = sna_write_boxes(sna, dst, 172003b705cfSriastradh dst_priv->gpu_bo, 0, 0, 172103b705cfSriastradh data, pitch, src_x, src_y, 172203b705cfSriastradh &box, 1); 172303b705cfSriastradh assert(ok); 172403b705cfSriastradh (void)ok; 172503b705cfSriastradh } 172603b705cfSriastradh} 172703b705cfSriastradh 172803b705cfSriastradhfastcall static void blt_put_composite_box(struct sna *sna, 172903b705cfSriastradh const struct sna_composite_op *op, 173003b705cfSriastradh const BoxRec *box) 173103b705cfSriastradh{ 173203b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 173303b705cfSriastradh struct sna_pixmap *dst_priv = sna_pixmap(op->dst.pixmap); 173403b705cfSriastradh 173503b705cfSriastradh DBG(("%s: src=(%d, %d), dst=(%d, %d)\n", __FUNCTION__, 173603b705cfSriastradh op->u.blt.sx, op->u.blt.sy, 173703b705cfSriastradh op->dst.x, op->dst.y)); 173803b705cfSriastradh 173903b705cfSriastradh if (!dst_priv->pinned && 174003b705cfSriastradh box->x2 - box->x1 == op->dst.width && 174103b705cfSriastradh box->y2 - box->y1 == op->dst.height) { 174203b705cfSriastradh int pitch = src->devKind; 174303b705cfSriastradh int bpp = src->drawable.bitsPerPixel / 8; 174403b705cfSriastradh char *data = src->devPrivate.ptr; 174503b705cfSriastradh 174603b705cfSriastradh data += (box->y1 + op->u.blt.sy) * pitch; 174703b705cfSriastradh data += (box->x1 + op->u.blt.sx) * bpp; 174803b705cfSriastradh 174903b705cfSriastradh sna_replace(sna, op->dst.pixmap, &dst_priv->gpu_bo, 175003b705cfSriastradh data, pitch); 175103b705cfSriastradh } else { 175203b705cfSriastradh bool ok; 175303b705cfSriastradh 175403b705cfSriastradh ok = sna_write_boxes(sna, op->dst.pixmap, 175503b705cfSriastradh op->dst.bo, op->dst.x, op->dst.y, 175603b705cfSriastradh src->devPrivate.ptr, 175703b705cfSriastradh src->devKind, 175803b705cfSriastradh op->u.blt.sx, op->u.blt.sy, 175903b705cfSriastradh box, 1); 176003b705cfSriastradh assert(ok); 176103b705cfSriastradh (void)ok; 176203b705cfSriastradh } 176303b705cfSriastradh} 176403b705cfSriastradh 176503b705cfSriastradhstatic void blt_put_composite_boxes(struct sna *sna, 176603b705cfSriastradh const struct sna_composite_op *op, 176703b705cfSriastradh const BoxRec *box, int n) 176803b705cfSriastradh{ 176903b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 177003b705cfSriastradh struct sna_pixmap *dst_priv = sna_pixmap(op->dst.pixmap); 177103b705cfSriastradh 177203b705cfSriastradh DBG(("%s: src=(%d, %d), dst=(%d, %d), [(%d, %d), (%d, %d) x %d]\n", __FUNCTION__, 177303b705cfSriastradh op->u.blt.sx, op->u.blt.sy, 177403b705cfSriastradh op->dst.x, op->dst.y, 177503b705cfSriastradh box->x1, box->y1, box->x2, box->y2, n)); 177603b705cfSriastradh 177703b705cfSriastradh if (n == 1 && !dst_priv->pinned && 177803b705cfSriastradh box->x2 - box->x1 == op->dst.width && 177903b705cfSriastradh box->y2 - box->y1 == op->dst.height) { 178003b705cfSriastradh int pitch = src->devKind; 178103b705cfSriastradh int bpp = src->drawable.bitsPerPixel / 8; 178203b705cfSriastradh char *data = src->devPrivate.ptr; 178303b705cfSriastradh 178403b705cfSriastradh data += (box->y1 + op->u.blt.sy) * pitch; 178503b705cfSriastradh data += (box->x1 + op->u.blt.sx) * bpp; 178603b705cfSriastradh 178703b705cfSriastradh sna_replace(sna, op->dst.pixmap, &dst_priv->gpu_bo, 178803b705cfSriastradh data, pitch); 178903b705cfSriastradh } else { 179003b705cfSriastradh bool ok; 179103b705cfSriastradh 179203b705cfSriastradh ok = sna_write_boxes(sna, op->dst.pixmap, 179303b705cfSriastradh op->dst.bo, op->dst.x, op->dst.y, 179403b705cfSriastradh src->devPrivate.ptr, 179503b705cfSriastradh src->devKind, 179603b705cfSriastradh op->u.blt.sx, op->u.blt.sy, 179703b705cfSriastradh box, n); 179803b705cfSriastradh assert(ok); 179903b705cfSriastradh (void)ok; 180003b705cfSriastradh } 180103b705cfSriastradh} 180203b705cfSriastradh 180303b705cfSriastradhfastcall static void 180403b705cfSriastradhblt_put_composite_with_alpha(struct sna *sna, 180503b705cfSriastradh const struct sna_composite_op *op, 180603b705cfSriastradh const struct sna_composite_rectangles *r) 180703b705cfSriastradh{ 180803b705cfSriastradh PixmapPtr dst = op->dst.pixmap; 180903b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 181003b705cfSriastradh struct sna_pixmap *dst_priv = sna_pixmap(dst); 181103b705cfSriastradh int pitch = src->devKind; 181203b705cfSriastradh char *data = src->devPrivate.ptr; 181303b705cfSriastradh 181403b705cfSriastradh int16_t dst_x = r->dst.x + op->dst.x; 181503b705cfSriastradh int16_t dst_y = r->dst.y + op->dst.y; 181603b705cfSriastradh int16_t src_x = r->src.x + op->u.blt.sx; 181703b705cfSriastradh int16_t src_y = r->src.y + op->u.blt.sy; 181803b705cfSriastradh 181903b705cfSriastradh if (!dst_priv->pinned && 182003b705cfSriastradh dst_x <= 0 && dst_y <= 0 && 182103b705cfSriastradh dst_x + r->width >= op->dst.width && 182203b705cfSriastradh dst_y + r->height >= op->dst.height) { 182303b705cfSriastradh int bpp = dst->drawable.bitsPerPixel / 8; 182403b705cfSriastradh 182503b705cfSriastradh data += (src_x - dst_x) * bpp; 182603b705cfSriastradh data += (src_y - dst_y) * pitch; 182703b705cfSriastradh 182803b705cfSriastradh dst_priv->gpu_bo = 182903b705cfSriastradh sna_replace__xor(sna, op->dst.pixmap, dst_priv->gpu_bo, 183003b705cfSriastradh data, pitch, 183103b705cfSriastradh 0xffffffff, op->u.blt.pixel); 183203b705cfSriastradh } else { 183303b705cfSriastradh BoxRec box; 183403b705cfSriastradh 183503b705cfSriastradh box.x1 = dst_x; 183603b705cfSriastradh box.y1 = dst_y; 183703b705cfSriastradh box.x2 = dst_x + r->width; 183803b705cfSriastradh box.y2 = dst_y + r->height; 183903b705cfSriastradh 184003b705cfSriastradh sna_write_boxes__xor(sna, dst, 184103b705cfSriastradh dst_priv->gpu_bo, 0, 0, 184203b705cfSriastradh data, pitch, src_x, src_y, 184303b705cfSriastradh &box, 1, 184403b705cfSriastradh 0xffffffff, op->u.blt.pixel); 184503b705cfSriastradh } 184603b705cfSriastradh} 184703b705cfSriastradh 184803b705cfSriastradhfastcall static void 184903b705cfSriastradhblt_put_composite_box_with_alpha(struct sna *sna, 185003b705cfSriastradh const struct sna_composite_op *op, 185103b705cfSriastradh const BoxRec *box) 185203b705cfSriastradh{ 185303b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 185403b705cfSriastradh struct sna_pixmap *dst_priv = sna_pixmap(op->dst.pixmap); 185503b705cfSriastradh 185603b705cfSriastradh DBG(("%s: src=(%d, %d), dst=(%d, %d)\n", __FUNCTION__, 185703b705cfSriastradh op->u.blt.sx, op->u.blt.sy, 185803b705cfSriastradh op->dst.x, op->dst.y)); 185903b705cfSriastradh 186003b705cfSriastradh if (!dst_priv->pinned && 186103b705cfSriastradh box->x2 - box->x1 == op->dst.width && 186203b705cfSriastradh box->y2 - box->y1 == op->dst.height) { 186303b705cfSriastradh int pitch = src->devKind; 186403b705cfSriastradh int bpp = src->drawable.bitsPerPixel / 8; 186503b705cfSriastradh char *data = src->devPrivate.ptr; 186603b705cfSriastradh 186703b705cfSriastradh data += (box->y1 + op->u.blt.sy) * pitch; 186803b705cfSriastradh data += (box->x1 + op->u.blt.sx) * bpp; 186903b705cfSriastradh 187003b705cfSriastradh dst_priv->gpu_bo = 187103b705cfSriastradh sna_replace__xor(sna, op->dst.pixmap, op->dst.bo, 187203b705cfSriastradh data, pitch, 187303b705cfSriastradh 0xffffffff, op->u.blt.pixel); 187403b705cfSriastradh } else { 187503b705cfSriastradh sna_write_boxes__xor(sna, op->dst.pixmap, 187603b705cfSriastradh op->dst.bo, op->dst.x, op->dst.y, 187703b705cfSriastradh src->devPrivate.ptr, 187803b705cfSriastradh src->devKind, 187903b705cfSriastradh op->u.blt.sx, op->u.blt.sy, 188003b705cfSriastradh box, 1, 188103b705cfSriastradh 0xffffffff, op->u.blt.pixel); 188203b705cfSriastradh } 188303b705cfSriastradh} 188403b705cfSriastradh 188503b705cfSriastradhstatic void 188603b705cfSriastradhblt_put_composite_boxes_with_alpha(struct sna *sna, 188703b705cfSriastradh const struct sna_composite_op *op, 188803b705cfSriastradh const BoxRec *box, int n) 188903b705cfSriastradh{ 189003b705cfSriastradh PixmapPtr src = op->u.blt.src_pixmap; 189103b705cfSriastradh struct sna_pixmap *dst_priv = sna_pixmap(op->dst.pixmap); 189203b705cfSriastradh 189303b705cfSriastradh DBG(("%s: src=(%d, %d), dst=(%d, %d), [(%d, %d), (%d, %d) x %d]\n", __FUNCTION__, 189403b705cfSriastradh op->u.blt.sx, op->u.blt.sy, 189503b705cfSriastradh op->dst.x, op->dst.y, 189603b705cfSriastradh box->x1, box->y1, box->x2, box->y2, n)); 189703b705cfSriastradh 189803b705cfSriastradh if (n == 1 && !dst_priv->pinned && 189903b705cfSriastradh box->x2 - box->x1 == op->dst.width && 190003b705cfSriastradh box->y2 - box->y1 == op->dst.height) { 190103b705cfSriastradh int pitch = src->devKind; 190203b705cfSriastradh int bpp = src->drawable.bitsPerPixel / 8; 190303b705cfSriastradh char *data = src->devPrivate.ptr; 190403b705cfSriastradh 190503b705cfSriastradh data += (box->y1 + op->u.blt.sy) * pitch; 190603b705cfSriastradh data += (box->x1 + op->u.blt.sx) * bpp; 190703b705cfSriastradh 190803b705cfSriastradh dst_priv->gpu_bo = 190903b705cfSriastradh sna_replace__xor(sna, op->dst.pixmap, op->dst.bo, 191003b705cfSriastradh data, pitch, 191103b705cfSriastradh 0xffffffff, op->u.blt.pixel); 191203b705cfSriastradh } else { 191303b705cfSriastradh sna_write_boxes__xor(sna, op->dst.pixmap, 191403b705cfSriastradh op->dst.bo, op->dst.x, op->dst.y, 191503b705cfSriastradh src->devPrivate.ptr, 191603b705cfSriastradh src->devKind, 191703b705cfSriastradh op->u.blt.sx, op->u.blt.sy, 191803b705cfSriastradh box, n, 191903b705cfSriastradh 0xffffffff, op->u.blt.pixel); 192003b705cfSriastradh } 192103b705cfSriastradh} 192203b705cfSriastradh 192303b705cfSriastradhstatic bool 192403b705cfSriastradhprepare_blt_put(struct sna *sna, 192503b705cfSriastradh struct sna_composite_op *op, 192603b705cfSriastradh uint32_t alpha_fixup) 192703b705cfSriastradh{ 192803b705cfSriastradh DBG(("%s\n", __FUNCTION__)); 192903b705cfSriastradh 193003b705cfSriastradh if (op->dst.bo) { 193103b705cfSriastradh assert(op->dst.bo == sna_pixmap(op->dst.pixmap)->gpu_bo); 193203b705cfSriastradh if (alpha_fixup) { 193303b705cfSriastradh op->u.blt.pixel = alpha_fixup; 193403b705cfSriastradh op->blt = blt_put_composite_with_alpha; 193503b705cfSriastradh op->box = blt_put_composite_box_with_alpha; 193603b705cfSriastradh op->boxes = blt_put_composite_boxes_with_alpha; 193703b705cfSriastradh } else { 193803b705cfSriastradh op->blt = blt_put_composite; 193903b705cfSriastradh op->box = blt_put_composite_box; 194003b705cfSriastradh op->boxes = blt_put_composite_boxes; 194103b705cfSriastradh } 194203b705cfSriastradh } else { 194303b705cfSriastradh if (alpha_fixup) { 194403b705cfSriastradh op->u.blt.pixel = alpha_fixup; 194503b705cfSriastradh op->blt = blt_put_composite_with_alpha__cpu; 194603b705cfSriastradh op->box = blt_put_composite_box_with_alpha__cpu; 194703b705cfSriastradh op->boxes = blt_put_composite_boxes_with_alpha__cpu; 194803b705cfSriastradh } else { 194903b705cfSriastradh op->blt = blt_put_composite__cpu; 195003b705cfSriastradh op->box = blt_put_composite_box__cpu; 195103b705cfSriastradh op->boxes = blt_put_composite_boxes__cpu; 195203b705cfSriastradh } 195303b705cfSriastradh } 195403b705cfSriastradh op->done = nop_done; 195503b705cfSriastradh 195603b705cfSriastradh return true; 195703b705cfSriastradh} 195803b705cfSriastradh 195903b705cfSriastradhstatic bool 196003b705cfSriastradhis_clear(PixmapPtr pixmap) 196103b705cfSriastradh{ 196203b705cfSriastradh struct sna_pixmap *priv = sna_pixmap(pixmap); 196303b705cfSriastradh return priv && priv->clear; 196403b705cfSriastradh} 196503b705cfSriastradh 196603b705cfSriastradhbool 196703b705cfSriastradhsna_blt_composite(struct sna *sna, 196803b705cfSriastradh uint32_t op, 196903b705cfSriastradh PicturePtr src, 197003b705cfSriastradh PicturePtr dst, 197103b705cfSriastradh int16_t x, int16_t y, 197203b705cfSriastradh int16_t dst_x, int16_t dst_y, 197303b705cfSriastradh int16_t width, int16_t height, 197403b705cfSriastradh struct sna_composite_op *tmp, 197503b705cfSriastradh bool fallback) 197603b705cfSriastradh{ 197703b705cfSriastradh PictFormat src_format = src->format; 197803b705cfSriastradh PixmapPtr src_pixmap; 197903b705cfSriastradh struct kgem_bo *bo; 198003b705cfSriastradh int16_t tx, ty; 198103b705cfSriastradh BoxRec dst_box, src_box; 198203b705cfSriastradh uint32_t alpha_fixup; 198303b705cfSriastradh uint32_t color, hint; 198403b705cfSriastradh bool was_clear; 198503b705cfSriastradh bool ret; 198603b705cfSriastradh 198703b705cfSriastradh#if DEBUG_NO_BLT || NO_BLT_COMPOSITE 198803b705cfSriastradh return false; 198903b705cfSriastradh#endif 199003b705cfSriastradh 199103b705cfSriastradh DBG(("%s (%d, %d), (%d, %d), %dx%d\n", 199203b705cfSriastradh __FUNCTION__, x, y, dst_x, dst_y, width, height)); 199303b705cfSriastradh 199403b705cfSriastradh switch (dst->pDrawable->bitsPerPixel) { 199503b705cfSriastradh case 8: 199603b705cfSriastradh case 16: 199703b705cfSriastradh case 32: 199803b705cfSriastradh break; 199903b705cfSriastradh default: 200003b705cfSriastradh DBG(("%s: unhandled bpp: %d\n", __FUNCTION__, 200103b705cfSriastradh dst->pDrawable->bitsPerPixel)); 200203b705cfSriastradh return false; 200303b705cfSriastradh } 200403b705cfSriastradh 200503b705cfSriastradh was_clear = sna_drawable_is_clear(dst->pDrawable); 200603b705cfSriastradh tmp->dst.pixmap = get_drawable_pixmap(dst->pDrawable); 200703b705cfSriastradh 200803b705cfSriastradh if (width | height) { 200903b705cfSriastradh dst_box.x1 = dst_x; 201003b705cfSriastradh dst_box.x2 = bound(dst_x, width); 201103b705cfSriastradh dst_box.y1 = dst_y; 201203b705cfSriastradh dst_box.y2 = bound(dst_y, height); 201303b705cfSriastradh } else 201403b705cfSriastradh sna_render_picture_extents(dst, &dst_box); 201503b705cfSriastradh 201603b705cfSriastradh tmp->dst.format = dst->format; 201703b705cfSriastradh tmp->dst.width = tmp->dst.pixmap->drawable.width; 201803b705cfSriastradh tmp->dst.height = tmp->dst.pixmap->drawable.height; 201903b705cfSriastradh get_drawable_deltas(dst->pDrawable, tmp->dst.pixmap, 202003b705cfSriastradh &tmp->dst.x, &tmp->dst.y); 202103b705cfSriastradh 202203b705cfSriastradh if (op == PictOpClear) { 202303b705cfSriastradhclear: 202403b705cfSriastradh if (was_clear) 202503b705cfSriastradh return prepare_blt_nop(sna, tmp); 202603b705cfSriastradh 202703b705cfSriastradh hint = 0; 202803b705cfSriastradh if (can_render(sna)) { 202903b705cfSriastradh hint |= PREFER_GPU; 203003b705cfSriastradh if (dst->pCompositeClip->data == NULL && (width | height)) { 203103b705cfSriastradh hint |= IGNORE_CPU; 203203b705cfSriastradh if (width == tmp->dst.pixmap->drawable.width && 203303b705cfSriastradh height == tmp->dst.pixmap->drawable.height) 203403b705cfSriastradh hint |= REPLACES; 203503b705cfSriastradh } 203603b705cfSriastradh } 203703b705cfSriastradh tmp->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint, 203803b705cfSriastradh &dst_box, &tmp->damage); 203903b705cfSriastradh if (tmp->dst.bo && !kgem_bo_can_blt(&sna->kgem, tmp->dst.bo)) { 204003b705cfSriastradh DBG(("%s: can not blit to dst, tiling? %d, pitch? %d\n", 204103b705cfSriastradh __FUNCTION__, tmp->dst.bo->tiling, tmp->dst.bo->pitch)); 204203b705cfSriastradh return false; 204303b705cfSriastradh } 204403b705cfSriastradh 204503b705cfSriastradh if (!tmp->dst.bo) { 204603b705cfSriastradh RegionRec region; 204703b705cfSriastradh 204803b705cfSriastradh region.extents = dst_box; 204903b705cfSriastradh region.data = NULL; 205003b705cfSriastradh 205103b705cfSriastradh if (!sna_drawable_move_region_to_cpu(dst->pDrawable, ®ion, 205203b705cfSriastradh MOVE_INPLACE_HINT | MOVE_WRITE)) 205303b705cfSriastradh return false; 205403b705cfSriastradh } else if (hint & REPLACES) 205503b705cfSriastradh kgem_bo_undo(&sna->kgem, tmp->dst.bo); 205603b705cfSriastradh 205703b705cfSriastradh return prepare_blt_clear(sna, tmp); 205803b705cfSriastradh } 205903b705cfSriastradh 206003b705cfSriastradh if (is_solid(src)) { 206103b705cfSriastradh if (op == PictOpOver && is_opaque_solid(src)) 206203b705cfSriastradh op = PictOpSrc; 206303b705cfSriastradh if (op == PictOpAdd && is_white(src)) 206403b705cfSriastradh op = PictOpSrc; 206503b705cfSriastradh if (was_clear && (op == PictOpAdd || op == PictOpOver)) 206603b705cfSriastradh op = PictOpSrc; 206703b705cfSriastradh if (op == PictOpOutReverse && is_opaque_solid(src)) 206803b705cfSriastradh goto clear; 206903b705cfSriastradh 207003b705cfSriastradh if (op != PictOpSrc) { 207103b705cfSriastradh DBG(("%s: unsupported op [%d] for blitting\n", 207203b705cfSriastradh __FUNCTION__, op)); 207303b705cfSriastradh return false; 207403b705cfSriastradh } 207503b705cfSriastradh 207603b705cfSriastradh color = get_solid_color(src, tmp->dst.format); 207703b705cfSriastradhfill: 207803b705cfSriastradh if (color == 0) 207903b705cfSriastradh goto clear; 208003b705cfSriastradh 208103b705cfSriastradh hint = 0; 208203b705cfSriastradh if (can_render(sna)) { 208303b705cfSriastradh hint |= PREFER_GPU; 208403b705cfSriastradh if (dst->pCompositeClip->data == NULL && (width | height)) 208503b705cfSriastradh hint |= IGNORE_CPU; 208603b705cfSriastradh if (width == tmp->dst.pixmap->drawable.width && 208703b705cfSriastradh height == tmp->dst.pixmap->drawable.height) 208803b705cfSriastradh hint |= REPLACES; 208903b705cfSriastradh } 209003b705cfSriastradh tmp->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint, 209103b705cfSriastradh &dst_box, &tmp->damage); 209203b705cfSriastradh if (tmp->dst.bo && !kgem_bo_can_blt(&sna->kgem, tmp->dst.bo)) { 209303b705cfSriastradh DBG(("%s: can not blit to dst, tiling? %d, pitch? %d\n", 209403b705cfSriastradh __FUNCTION__, tmp->dst.bo->tiling, tmp->dst.bo->pitch)); 209503b705cfSriastradh return false; 209603b705cfSriastradh } 209703b705cfSriastradh 209803b705cfSriastradh if (!tmp->dst.bo) { 209903b705cfSriastradh RegionRec region; 210003b705cfSriastradh 210103b705cfSriastradh region.extents = dst_box; 210203b705cfSriastradh region.data = NULL; 210303b705cfSriastradh 210403b705cfSriastradh if (!sna_drawable_move_region_to_cpu(dst->pDrawable, ®ion, 210503b705cfSriastradh MOVE_INPLACE_HINT | MOVE_WRITE)) 210603b705cfSriastradh return false; 210703b705cfSriastradh } else if (hint & REPLACES) 210803b705cfSriastradh kgem_bo_undo(&sna->kgem, tmp->dst.bo); 210903b705cfSriastradh 211003b705cfSriastradh return prepare_blt_fill(sna, tmp, color); 211103b705cfSriastradh } 211203b705cfSriastradh 211303b705cfSriastradh if (!src->pDrawable) { 211403b705cfSriastradh DBG(("%s: unsupported procedural source\n", 211503b705cfSriastradh __FUNCTION__)); 211603b705cfSriastradh return false; 211703b705cfSriastradh } 211803b705cfSriastradh 211903b705cfSriastradh if (src->filter == PictFilterConvolution) { 212003b705cfSriastradh DBG(("%s: convolutions filters not handled\n", 212103b705cfSriastradh __FUNCTION__)); 212203b705cfSriastradh return false; 212303b705cfSriastradh } 212403b705cfSriastradh 212503b705cfSriastradh if (op == PictOpOver && PICT_FORMAT_A(src_format) == 0) 212603b705cfSriastradh op = PictOpSrc; 212703b705cfSriastradh 212803b705cfSriastradh if (op != PictOpSrc) { 212903b705cfSriastradh DBG(("%s: unsupported op [%d] for blitting\n", 213003b705cfSriastradh __FUNCTION__, op)); 213103b705cfSriastradh return false; 213203b705cfSriastradh } 213303b705cfSriastradh 213403b705cfSriastradh if (!sna_transform_is_integer_translation(src->transform, &tx, &ty)) { 213503b705cfSriastradh DBG(("%s: source transform is not an integer translation\n", 213603b705cfSriastradh __FUNCTION__)); 213703b705cfSriastradh return false; 213803b705cfSriastradh } 213903b705cfSriastradh x += tx; 214003b705cfSriastradh y += ty; 214103b705cfSriastradh 214203b705cfSriastradh if ((x >= src->pDrawable->width || 214303b705cfSriastradh y >= src->pDrawable->height || 214403b705cfSriastradh x + width <= 0 || 214503b705cfSriastradh y + height <= 0) && 214603b705cfSriastradh (!src->repeat || src->repeatType == RepeatNone)) { 214703b705cfSriastradh DBG(("%s: source is outside of valid area, converting to clear\n", 214803b705cfSriastradh __FUNCTION__)); 214903b705cfSriastradh goto clear; 215003b705cfSriastradh } 215103b705cfSriastradh 215203b705cfSriastradh src_pixmap = get_drawable_pixmap(src->pDrawable); 215303b705cfSriastradh if (is_clear(src_pixmap)) { 215403b705cfSriastradh color = color_convert(sna_pixmap(src_pixmap)->clear_color, 215503b705cfSriastradh src->format, tmp->dst.format); 215603b705cfSriastradh goto fill; 215703b705cfSriastradh } 215803b705cfSriastradh 215903b705cfSriastradh alpha_fixup = 0; 216003b705cfSriastradh if (!(dst->format == src_format || 216103b705cfSriastradh dst->format == alphaless(src_format) || 216203b705cfSriastradh (alphaless(dst->format) == alphaless(src_format) && 216303b705cfSriastradh sna_get_pixel_from_rgba(&alpha_fixup, 216403b705cfSriastradh 0, 0, 0, 0xffff, 216503b705cfSriastradh dst->format)))) { 216603b705cfSriastradh DBG(("%s: incompatible src/dst formats src=%08x, dst=%08x\n", 216703b705cfSriastradh __FUNCTION__, (unsigned)src_format, dst->format)); 216803b705cfSriastradh return false; 216903b705cfSriastradh } 217003b705cfSriastradh 217103b705cfSriastradh /* XXX tiling? fixup extend none? */ 217203b705cfSriastradh if (x < 0 || y < 0 || 217303b705cfSriastradh x + width > src->pDrawable->width || 217403b705cfSriastradh y + height > src->pDrawable->height) { 217503b705cfSriastradh DBG(("%s: source extends outside (%d, %d), (%d, %d) of valid drawable %dx%d, repeat=%d\n", 217603b705cfSriastradh __FUNCTION__, 217703b705cfSriastradh x, y, x+width, y+width, src->pDrawable->width, src->pDrawable->height, src->repeatType)); 217803b705cfSriastradh if (src->repeat && src->repeatType == RepeatNormal) { 217903b705cfSriastradh x = x % src->pDrawable->width; 218003b705cfSriastradh y = y % src->pDrawable->height; 218103b705cfSriastradh if (x < 0) 218203b705cfSriastradh x += src->pDrawable->width; 218303b705cfSriastradh if (y < 0) 218403b705cfSriastradh y += src->pDrawable->height; 218503b705cfSriastradh if (x + width > src->pDrawable->width || 218603b705cfSriastradh y + height > src->pDrawable->height) 218703b705cfSriastradh return false; 218803b705cfSriastradh } else 218903b705cfSriastradh return false; 219003b705cfSriastradh } 219103b705cfSriastradh 219203b705cfSriastradh get_drawable_deltas(src->pDrawable, src_pixmap, &tx, &ty); 219303b705cfSriastradh x += tx + src->pDrawable->x; 219403b705cfSriastradh y += ty + src->pDrawable->y; 219503b705cfSriastradh if (x < 0 || y < 0 || 219603b705cfSriastradh x + width > src_pixmap->drawable.width || 219703b705cfSriastradh y + height > src_pixmap->drawable.height) { 219803b705cfSriastradh DBG(("%s: source extends outside (%d, %d), (%d, %d) of valid pixmap %dx%d\n", 219903b705cfSriastradh __FUNCTION__, 220003b705cfSriastradh x, y, x+width, y+width, src_pixmap->drawable.width, src_pixmap->drawable.height)); 220103b705cfSriastradh return false; 220203b705cfSriastradh } 220303b705cfSriastradh 220403b705cfSriastradh tmp->u.blt.src_pixmap = src_pixmap; 220503b705cfSriastradh tmp->u.blt.sx = x - dst_x; 220603b705cfSriastradh tmp->u.blt.sy = y - dst_y; 220703b705cfSriastradh DBG(("%s: blt dst offset (%d, %d), source offset (%d, %d), with alpha fixup? %x\n", 220803b705cfSriastradh __FUNCTION__, 220903b705cfSriastradh tmp->dst.x, tmp->dst.y, tmp->u.blt.sx, tmp->u.blt.sy, alpha_fixup)); 221003b705cfSriastradh 221103b705cfSriastradh src_box.x1 = x; 221203b705cfSriastradh src_box.y1 = y; 221303b705cfSriastradh src_box.x2 = x + width; 221403b705cfSriastradh src_box.y2 = y + height; 221503b705cfSriastradh bo = __sna_render_pixmap_bo(sna, src_pixmap, &src_box, true); 221603b705cfSriastradh if (bo && !kgem_bo_can_blt(&sna->kgem, bo)) { 221703b705cfSriastradh DBG(("%s: can not blit from src size=%dx%d, tiling? %d, pitch? %d\n", 221803b705cfSriastradh __FUNCTION__, 221903b705cfSriastradh src_pixmap->drawable.width < sna->render.max_3d_size, 222003b705cfSriastradh src_pixmap->drawable.height < sna->render.max_3d_size, 222103b705cfSriastradh bo->tiling, bo->pitch)); 222203b705cfSriastradh 222303b705cfSriastradh if (src_pixmap->drawable.width <= sna->render.max_3d_size && 222403b705cfSriastradh src_pixmap->drawable.height <= sna->render.max_3d_size && 222503b705cfSriastradh bo->pitch <= sna->render.max_3d_pitch && 222603b705cfSriastradh !fallback) 222703b705cfSriastradh { 222803b705cfSriastradh return false; 222903b705cfSriastradh } 223003b705cfSriastradh 223103b705cfSriastradh bo = NULL; 223203b705cfSriastradh } 223303b705cfSriastradh 223403b705cfSriastradh hint = 0; 223503b705cfSriastradh if (bo || can_render(sna)) { 223603b705cfSriastradh hint |= PREFER_GPU; 223703b705cfSriastradh if (dst->pCompositeClip->data == NULL && (width | height)) { 223803b705cfSriastradh hint |= IGNORE_CPU; 223903b705cfSriastradh if (width == tmp->dst.pixmap->drawable.width && 224003b705cfSriastradh height == tmp->dst.pixmap->drawable.height) 224103b705cfSriastradh hint |= REPLACES; 224203b705cfSriastradh } 224303b705cfSriastradh if (bo) 224403b705cfSriastradh hint |= FORCE_GPU; 224503b705cfSriastradh } 224603b705cfSriastradh tmp->dst.bo = sna_drawable_use_bo(dst->pDrawable, hint, 224703b705cfSriastradh &dst_box, &tmp->damage); 224803b705cfSriastradh 224903b705cfSriastradh if (hint & REPLACES) 225003b705cfSriastradh kgem_bo_undo(&sna->kgem, tmp->dst.bo); 225103b705cfSriastradh 225203b705cfSriastradh ret = false; 225303b705cfSriastradh if (bo) { 225403b705cfSriastradh if (!tmp->dst.bo) { 225503b705cfSriastradh DBG(("%s: fallback -- unaccelerated read back\n", 225603b705cfSriastradh __FUNCTION__)); 225703b705cfSriastradh if (fallback || !kgem_bo_is_busy(bo)) 225803b705cfSriastradh goto put; 225903b705cfSriastradh } else if (bo->snoop && tmp->dst.bo->snoop) { 226003b705cfSriastradh DBG(("%s: fallback -- can not copy between snooped bo\n", 226103b705cfSriastradh __FUNCTION__)); 226203b705cfSriastradh goto put; 226303b705cfSriastradh } else if (!kgem_bo_can_blt(&sna->kgem, tmp->dst.bo)) { 226403b705cfSriastradh DBG(("%s: fallback -- unaccelerated upload\n", 226503b705cfSriastradh __FUNCTION__)); 226603b705cfSriastradh if (fallback || !kgem_bo_is_busy(bo)) 226703b705cfSriastradh goto put; 226803b705cfSriastradh } else { 226903b705cfSriastradh ret = prepare_blt_copy(sna, tmp, bo, alpha_fixup); 227003b705cfSriastradh if (fallback && !ret) 227103b705cfSriastradh goto put; 227203b705cfSriastradh } 227303b705cfSriastradh } else { 227403b705cfSriastradh RegionRec region; 227503b705cfSriastradh 227603b705cfSriastradhput: 227703b705cfSriastradh if (tmp->dst.bo == sna_pixmap(tmp->dst.pixmap)->cpu_bo) { 227803b705cfSriastradh tmp->dst.bo = NULL; 227903b705cfSriastradh tmp->damage = NULL; 228003b705cfSriastradh } 228103b705cfSriastradh 228203b705cfSriastradh if (tmp->dst.bo == NULL) { 228303b705cfSriastradh hint = MOVE_INPLACE_HINT | MOVE_WRITE; 228403b705cfSriastradh if (dst->pCompositeClip->data) 228503b705cfSriastradh hint |= MOVE_READ; 228603b705cfSriastradh 228703b705cfSriastradh region.extents = dst_box; 228803b705cfSriastradh region.data = NULL; 228903b705cfSriastradh if (!sna_drawable_move_region_to_cpu(dst->pDrawable, 229003b705cfSriastradh ®ion, hint)) 229103b705cfSriastradh return false; 229203b705cfSriastradh 229303b705cfSriastradh assert(tmp->damage == NULL); 229403b705cfSriastradh } 229503b705cfSriastradh 229603b705cfSriastradh region.extents = src_box; 229703b705cfSriastradh region.data = NULL; 229803b705cfSriastradh if (!sna_drawable_move_region_to_cpu(&src_pixmap->drawable, 229903b705cfSriastradh ®ion, MOVE_READ)) 230003b705cfSriastradh return false; 230103b705cfSriastradh 230203b705cfSriastradh ret = prepare_blt_put(sna, tmp, alpha_fixup); 230303b705cfSriastradh } 230403b705cfSriastradh 230503b705cfSriastradh return ret; 230603b705cfSriastradh} 230703b705cfSriastradh 230803b705cfSriastradhstatic void convert_done(struct sna *sna, const struct sna_composite_op *op) 230903b705cfSriastradh{ 231003b705cfSriastradh struct kgem *kgem = &sna->kgem; 231103b705cfSriastradh 231203b705cfSriastradh assert(kgem->nbatch <= KGEM_BATCH_SIZE(kgem)); 231303b705cfSriastradh if (kgem->nexec > 1 && __kgem_ring_empty(kgem)) 231403b705cfSriastradh _kgem_submit(kgem); 231503b705cfSriastradh 231603b705cfSriastradh kgem_bo_destroy(kgem, op->src.bo); 231703b705cfSriastradh sna_render_composite_redirect_done(sna, op); 231803b705cfSriastradh} 231903b705cfSriastradh 232003b705cfSriastradhstatic void gen6_convert_done(struct sna *sna, const struct sna_composite_op *op) 232103b705cfSriastradh{ 232203b705cfSriastradh struct kgem *kgem = &sna->kgem; 232303b705cfSriastradh 232403b705cfSriastradh if (kgem_check_batch(kgem, 3)) { 232503b705cfSriastradh uint32_t *b = kgem->batch + kgem->nbatch; 232603b705cfSriastradh b[0] = XY_SETUP_CLIP; 232703b705cfSriastradh b[1] = b[2] = 0; 232803b705cfSriastradh kgem->nbatch += 3; 232903b705cfSriastradh assert(kgem->nbatch < kgem->surface); 233003b705cfSriastradh } 233103b705cfSriastradh 233203b705cfSriastradh convert_done(sna, op); 233303b705cfSriastradh} 233403b705cfSriastradh 233503b705cfSriastradhbool 233603b705cfSriastradhsna_blt_composite__convert(struct sna *sna, 233703b705cfSriastradh int x, int y, 233803b705cfSriastradh int width, int height, 233903b705cfSriastradh struct sna_composite_op *tmp) 234003b705cfSriastradh{ 234103b705cfSriastradh uint32_t alpha_fixup; 234203b705cfSriastradh int sx, sy; 234303b705cfSriastradh uint8_t op; 234403b705cfSriastradh 234503b705cfSriastradh#if DEBUG_NO_BLT || NO_BLT_COMPOSITE 234603b705cfSriastradh return false; 234703b705cfSriastradh#endif 234803b705cfSriastradh 234903b705cfSriastradh DBG(("%s src=%d, dst=%d (redirect? %d)\n", __FUNCTION__, 235003b705cfSriastradh tmp->src.bo->handle, tmp->dst.bo->handle, 235103b705cfSriastradh tmp->redirect.real_bo ? tmp->redirect.real_bo->handle : 0)); 235203b705cfSriastradh 235303b705cfSriastradh if (!kgem_bo_can_blt(&sna->kgem, tmp->dst.bo) || 235403b705cfSriastradh !kgem_bo_can_blt(&sna->kgem, tmp->src.bo)) { 235503b705cfSriastradh DBG(("%s: cannot blt from src or to dst\n", __FUNCTION__)); 235603b705cfSriastradh return false; 235703b705cfSriastradh } 235803b705cfSriastradh 235903b705cfSriastradh if (tmp->src.transform) { 236003b705cfSriastradh DBG(("%s: transforms not handled by the BLT\n", __FUNCTION__)); 236103b705cfSriastradh return false; 236203b705cfSriastradh } 236303b705cfSriastradh 236403b705cfSriastradh if (tmp->src.filter == PictFilterConvolution) { 236503b705cfSriastradh DBG(("%s: convolutions filters not handled\n", 236603b705cfSriastradh __FUNCTION__)); 236703b705cfSriastradh return false; 236803b705cfSriastradh } 236903b705cfSriastradh 237003b705cfSriastradh op = tmp->op; 237103b705cfSriastradh if (op == PictOpOver && PICT_FORMAT_A(tmp->src.pict_format) == 0) 237203b705cfSriastradh op = PictOpSrc; 237303b705cfSriastradh if (op != PictOpSrc) { 237403b705cfSriastradh DBG(("%s: unsupported op [%d] for blitting\n", 237503b705cfSriastradh __FUNCTION__, op)); 237603b705cfSriastradh return false; 237703b705cfSriastradh } 237803b705cfSriastradh 237903b705cfSriastradh alpha_fixup = 0; 238003b705cfSriastradh if (!(tmp->dst.format == tmp->src.pict_format || 238103b705cfSriastradh tmp->dst.format == alphaless(tmp->src.pict_format) || 238203b705cfSriastradh (alphaless(tmp->dst.format) == alphaless(tmp->src.pict_format) && 238303b705cfSriastradh sna_get_pixel_from_rgba(&alpha_fixup, 238403b705cfSriastradh 0, 0, 0, 0xffff, 238503b705cfSriastradh tmp->dst.format)))) { 238603b705cfSriastradh DBG(("%s: incompatible src/dst formats src=%08x, dst=%08x\n", 238703b705cfSriastradh __FUNCTION__, 238803b705cfSriastradh (unsigned)tmp->src.pict_format, 238903b705cfSriastradh (unsigned)tmp->dst.format)); 239003b705cfSriastradh return false; 239103b705cfSriastradh } 239203b705cfSriastradh 239303b705cfSriastradh sx = tmp->src.offset[0]; 239403b705cfSriastradh sy = tmp->src.offset[1]; 239503b705cfSriastradh 239603b705cfSriastradh x += sx; 239703b705cfSriastradh y += sy; 239803b705cfSriastradh if (x < 0 || y < 0 || 239903b705cfSriastradh x + width > tmp->src.width || 240003b705cfSriastradh y + height > tmp->src.height) { 240103b705cfSriastradh DBG(("%s: source extends outside (%d, %d), (%d, %d) of valid drawable %dx%d\n", 240203b705cfSriastradh __FUNCTION__, 240303b705cfSriastradh x, y, x+width, y+width, tmp->src.width, tmp->src.height)); 240403b705cfSriastradh if (tmp->src.repeat == RepeatNormal) { 240503b705cfSriastradh int xx = x % tmp->src.width; 240603b705cfSriastradh int yy = y % tmp->src.height; 240703b705cfSriastradh if (xx < 0) 240803b705cfSriastradh xx += tmp->src.width; 240903b705cfSriastradh if (yy < 0) 241003b705cfSriastradh yy += tmp->src.height; 241103b705cfSriastradh if (xx + width > tmp->src.width || 241203b705cfSriastradh yy + height > tmp->src.height) 241303b705cfSriastradh return false; 241403b705cfSriastradh 241503b705cfSriastradh sx += xx - x; 241603b705cfSriastradh sy += yy - y; 241703b705cfSriastradh } else 241803b705cfSriastradh return false; 241903b705cfSriastradh } 242003b705cfSriastradh 242103b705cfSriastradh if (!kgem_check_many_bo_fenced(&sna->kgem, tmp->dst.bo, tmp->src.bo, NULL)) { 242203b705cfSriastradh kgem_submit(&sna->kgem); 242303b705cfSriastradh if (!kgem_check_many_bo_fenced(&sna->kgem, 242403b705cfSriastradh tmp->dst.bo, tmp->src.bo, NULL)) { 242503b705cfSriastradh DBG(("%s: fallback -- no room in aperture\n", __FUNCTION__)); 242603b705cfSriastradh return false; 242703b705cfSriastradh } 242803b705cfSriastradh _kgem_set_mode(&sna->kgem, KGEM_BLT); 242903b705cfSriastradh } 243003b705cfSriastradh 243103b705cfSriastradh DBG(("%s: blt dst offset (%d, %d), source offset (%d, %d), with alpha fixup? %x\n", 243203b705cfSriastradh __FUNCTION__, 243303b705cfSriastradh tmp->dst.x, tmp->dst.y, tmp->u.blt.sx, tmp->u.blt.sy, alpha_fixup)); 243403b705cfSriastradh 243503b705cfSriastradh tmp->u.blt.src_pixmap = NULL; 243603b705cfSriastradh tmp->u.blt.sx = sx; 243703b705cfSriastradh tmp->u.blt.sy = sy; 243803b705cfSriastradh 243903b705cfSriastradh if (alpha_fixup) { 244003b705cfSriastradh tmp->blt = blt_composite_copy_with_alpha; 244103b705cfSriastradh tmp->box = blt_composite_copy_box_with_alpha; 244203b705cfSriastradh tmp->boxes = blt_composite_copy_boxes_with_alpha; 244303b705cfSriastradh 244403b705cfSriastradh if (!sna_blt_alpha_fixup_init(sna, &tmp->u.blt, 244503b705cfSriastradh tmp->src.bo, tmp->dst.bo, 244603b705cfSriastradh PICT_FORMAT_BPP(tmp->src.pict_format), 244703b705cfSriastradh alpha_fixup)) 244803b705cfSriastradh return false; 244903b705cfSriastradh } else { 245003b705cfSriastradh tmp->blt = blt_composite_copy; 245103b705cfSriastradh tmp->box = blt_composite_copy_box; 245203b705cfSriastradh tmp->boxes = blt_composite_copy_boxes; 245303b705cfSriastradh tmp->thread_boxes = blt_composite_copy_boxes__thread; 245403b705cfSriastradh 245503b705cfSriastradh if (!sna_blt_copy_init(sna, &tmp->u.blt, 245603b705cfSriastradh tmp->src.bo, tmp->dst.bo, 245703b705cfSriastradh PICT_FORMAT_BPP(tmp->src.pict_format), 245803b705cfSriastradh GXcopy)) 245903b705cfSriastradh return false; 246003b705cfSriastradh } 246103b705cfSriastradh 246203b705cfSriastradh tmp->done = convert_done; 246303b705cfSriastradh if (sna->kgem.gen >= 060 && tmp->src.bo == tmp->dst.bo) 246403b705cfSriastradh tmp->done = gen6_convert_done; 246503b705cfSriastradh 246603b705cfSriastradh return true; 246703b705cfSriastradh} 246803b705cfSriastradh 246903b705cfSriastradhstatic void sna_blt_fill_op_blt(struct sna *sna, 247003b705cfSriastradh const struct sna_fill_op *op, 247103b705cfSriastradh int16_t x, int16_t y, 247203b705cfSriastradh int16_t width, int16_t height) 247303b705cfSriastradh{ 247403b705cfSriastradh sna_blt_fill_one(sna, &op->base.u.blt, x, y, width, height); 247503b705cfSriastradh} 247603b705cfSriastradh 247703b705cfSriastradhfastcall static void sna_blt_fill_op_box(struct sna *sna, 247803b705cfSriastradh const struct sna_fill_op *op, 247903b705cfSriastradh const BoxRec *box) 248003b705cfSriastradh{ 248103b705cfSriastradh _sna_blt_fill_box(sna, &op->base.u.blt, box); 248203b705cfSriastradh} 248303b705cfSriastradh 248403b705cfSriastradhfastcall static void sna_blt_fill_op_boxes(struct sna *sna, 248503b705cfSriastradh const struct sna_fill_op *op, 248603b705cfSriastradh const BoxRec *box, 248703b705cfSriastradh int nbox) 248803b705cfSriastradh{ 248903b705cfSriastradh _sna_blt_fill_boxes(sna, &op->base.u.blt, box, nbox); 249003b705cfSriastradh} 249103b705cfSriastradh 249203b705cfSriastradhbool sna_blt_fill(struct sna *sna, uint8_t alu, 249303b705cfSriastradh struct kgem_bo *bo, int bpp, 249403b705cfSriastradh uint32_t pixel, 249503b705cfSriastradh struct sna_fill_op *fill) 249603b705cfSriastradh{ 249703b705cfSriastradh#if DEBUG_NO_BLT || NO_BLT_FILL 249803b705cfSriastradh return false; 249903b705cfSriastradh#endif 250003b705cfSriastradh 250103b705cfSriastradh DBG(("%s(alu=%d, pixel=%x, bpp=%d)\n", __FUNCTION__, alu, pixel, bpp)); 250203b705cfSriastradh 250303b705cfSriastradh if (!kgem_bo_can_blt(&sna->kgem, bo)) { 250403b705cfSriastradh DBG(("%s: rejected due to incompatible Y-tiling\n", 250503b705cfSriastradh __FUNCTION__)); 250603b705cfSriastradh return false; 250703b705cfSriastradh } 250803b705cfSriastradh 250903b705cfSriastradh if (!sna_blt_fill_init(sna, &fill->base.u.blt, 251003b705cfSriastradh bo, bpp, alu, pixel)) 251103b705cfSriastradh return false; 251203b705cfSriastradh 251303b705cfSriastradh fill->blt = sna_blt_fill_op_blt; 251403b705cfSriastradh fill->box = sna_blt_fill_op_box; 251503b705cfSriastradh fill->boxes = sna_blt_fill_op_boxes; 251603b705cfSriastradh fill->done = 251703b705cfSriastradh (void (*)(struct sna *, const struct sna_fill_op *))nop_done; 251803b705cfSriastradh return true; 251903b705cfSriastradh} 252003b705cfSriastradh 252103b705cfSriastradhstatic void sna_blt_copy_op_blt(struct sna *sna, 252203b705cfSriastradh const struct sna_copy_op *op, 252303b705cfSriastradh int16_t src_x, int16_t src_y, 252403b705cfSriastradh int16_t width, int16_t height, 252503b705cfSriastradh int16_t dst_x, int16_t dst_y) 252603b705cfSriastradh{ 252703b705cfSriastradh sna_blt_copy_one(sna, &op->base.u.blt, 252803b705cfSriastradh src_x, src_y, 252903b705cfSriastradh width, height, 253003b705cfSriastradh dst_x, dst_y); 253103b705cfSriastradh} 253203b705cfSriastradh 253303b705cfSriastradhbool sna_blt_copy(struct sna *sna, uint8_t alu, 253403b705cfSriastradh struct kgem_bo *src, 253503b705cfSriastradh struct kgem_bo *dst, 253603b705cfSriastradh int bpp, 253703b705cfSriastradh struct sna_copy_op *op) 253803b705cfSriastradh{ 253903b705cfSriastradh#if DEBUG_NO_BLT || NO_BLT_COPY 254003b705cfSriastradh return false; 254103b705cfSriastradh#endif 254203b705cfSriastradh 254303b705cfSriastradh if (!kgem_bo_can_blt(&sna->kgem, src)) 254403b705cfSriastradh return false; 254503b705cfSriastradh 254603b705cfSriastradh if (!kgem_bo_can_blt(&sna->kgem, dst)) 254703b705cfSriastradh return false; 254803b705cfSriastradh 254903b705cfSriastradh if (!sna_blt_copy_init(sna, &op->base.u.blt, 255003b705cfSriastradh src, dst, 255103b705cfSriastradh bpp, alu)) 255203b705cfSriastradh return false; 255303b705cfSriastradh 255403b705cfSriastradh op->blt = sna_blt_copy_op_blt; 255503b705cfSriastradh if (sna->kgem.gen >= 060 && src == dst) 255603b705cfSriastradh op->done = (void (*)(struct sna *, const struct sna_copy_op *)) 255703b705cfSriastradh gen6_blt_copy_done; 255803b705cfSriastradh else 255903b705cfSriastradh op->done = (void (*)(struct sna *, const struct sna_copy_op *)) 256003b705cfSriastradh nop_done; 256103b705cfSriastradh return true; 256203b705cfSriastradh} 256303b705cfSriastradh 256403b705cfSriastradhstatic bool sna_blt_fill_box(struct sna *sna, uint8_t alu, 256503b705cfSriastradh struct kgem_bo *bo, int bpp, 256603b705cfSriastradh uint32_t color, 256703b705cfSriastradh const BoxRec *box) 256803b705cfSriastradh{ 256903b705cfSriastradh struct kgem *kgem = &sna->kgem; 257003b705cfSriastradh uint32_t br13, cmd, *b; 257103b705cfSriastradh bool overwrites; 257203b705cfSriastradh 257303b705cfSriastradh assert(kgem_bo_can_blt (kgem, bo)); 257403b705cfSriastradh 257503b705cfSriastradh DBG(("%s: box=((%d, %d), (%d, %d))\n", __FUNCTION__, 257603b705cfSriastradh box->x1, box->y1, box->x2, box->y2)); 257703b705cfSriastradh 257803b705cfSriastradh assert(box->x1 >= 0); 257903b705cfSriastradh assert(box->y1 >= 0); 258003b705cfSriastradh 258103b705cfSriastradh cmd = XY_COLOR_BLT; 258203b705cfSriastradh br13 = bo->pitch; 258303b705cfSriastradh if (kgem->gen >= 040 && bo->tiling) { 258403b705cfSriastradh cmd |= BLT_DST_TILED; 258503b705cfSriastradh br13 >>= 2; 258603b705cfSriastradh } 258703b705cfSriastradh assert(br13 <= MAXSHORT); 258803b705cfSriastradh 258903b705cfSriastradh br13 |= fill_ROP[alu] << 16; 259003b705cfSriastradh switch (bpp) { 259103b705cfSriastradh default: assert(0); 259203b705cfSriastradh case 32: cmd |= BLT_WRITE_ALPHA | BLT_WRITE_RGB; 259303b705cfSriastradh br13 |= 1 << 25; /* RGB8888 */ 259403b705cfSriastradh case 16: br13 |= 1 << 24; /* RGB565 */ 259503b705cfSriastradh case 8: break; 259603b705cfSriastradh } 259703b705cfSriastradh 259803b705cfSriastradh /* All too frequently one blt completely overwrites the previous */ 259903b705cfSriastradh overwrites = alu == GXcopy || alu == GXclear || alu == GXset; 260003b705cfSriastradh if (overwrites && kgem->nbatch >= 6 && 260103b705cfSriastradh kgem->batch[kgem->nbatch-6] == cmd && 260203b705cfSriastradh *(uint64_t *)&kgem->batch[kgem->nbatch-4] == *(const uint64_t *)box && 260303b705cfSriastradh kgem->reloc[kgem->nreloc-1].target_handle == bo->target_handle) { 260403b705cfSriastradh DBG(("%s: replacing last fill\n", __FUNCTION__)); 260503b705cfSriastradh kgem->batch[kgem->nbatch-5] = br13; 260603b705cfSriastradh kgem->batch[kgem->nbatch-1] = color; 260703b705cfSriastradh return true; 260803b705cfSriastradh } 260903b705cfSriastradh if (overwrites && kgem->nbatch >= 8 && 261003b705cfSriastradh (kgem->batch[kgem->nbatch-8] & 0xffc0000f) == XY_SRC_COPY_BLT_CMD && 261103b705cfSriastradh *(uint64_t *)&kgem->batch[kgem->nbatch-6] == *(const uint64_t *)box && 261203b705cfSriastradh kgem->reloc[kgem->nreloc-2].target_handle == bo->target_handle) { 261303b705cfSriastradh DBG(("%s: replacing last copy\n", __FUNCTION__)); 261403b705cfSriastradh kgem->batch[kgem->nbatch-8] = cmd; 261503b705cfSriastradh kgem->batch[kgem->nbatch-7] = br13; 261603b705cfSriastradh kgem->batch[kgem->nbatch-3] = color; 261703b705cfSriastradh /* Keep the src bo as part of the execlist, just remove 261803b705cfSriastradh * its relocation entry. 261903b705cfSriastradh */ 262003b705cfSriastradh kgem->nreloc--; 262103b705cfSriastradh kgem->nbatch -= 2; 262203b705cfSriastradh return true; 262303b705cfSriastradh } 262403b705cfSriastradh 262503b705cfSriastradh /* If we are currently emitting SCANLINES, keep doing so */ 262603b705cfSriastradh if (sna->blt_state.fill_bo == bo->unique_id && 262703b705cfSriastradh sna->blt_state.fill_pixel == color && 262803b705cfSriastradh (sna->blt_state.fill_alu == alu || 262903b705cfSriastradh sna->blt_state.fill_alu == ~alu)) { 263003b705cfSriastradh DBG(("%s: matching last fill, converting to scanlines\n", 263103b705cfSriastradh __FUNCTION__)); 263203b705cfSriastradh return false; 263303b705cfSriastradh } 263403b705cfSriastradh 263503b705cfSriastradh kgem_set_mode(kgem, KGEM_BLT, bo); 263603b705cfSriastradh if (!kgem_check_batch(kgem, 6) || 263703b705cfSriastradh !kgem_check_reloc(kgem, 1) || 263803b705cfSriastradh !kgem_check_bo_fenced(kgem, bo)) { 263903b705cfSriastradh kgem_submit(kgem); 264003b705cfSriastradh assert(kgem_check_bo_fenced(&sna->kgem, bo)); 264103b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 264203b705cfSriastradh } 264303b705cfSriastradh 264403b705cfSriastradh b = kgem->batch + kgem->nbatch; 264503b705cfSriastradh b[0] = cmd; 264603b705cfSriastradh b[1] = br13; 264703b705cfSriastradh *(uint64_t *)(b+2) = *(const uint64_t *)box; 264803b705cfSriastradh b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, bo, 264903b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 265003b705cfSriastradh I915_GEM_DOMAIN_RENDER | 265103b705cfSriastradh KGEM_RELOC_FENCED, 265203b705cfSriastradh 0); 265303b705cfSriastradh b[5] = color; 265403b705cfSriastradh kgem->nbatch += 6; 265503b705cfSriastradh assert(kgem->nbatch < kgem->surface); 265603b705cfSriastradh 265703b705cfSriastradh sna->blt_state.fill_bo = bo->unique_id; 265803b705cfSriastradh sna->blt_state.fill_pixel = color; 265903b705cfSriastradh sna->blt_state.fill_alu = ~alu; 266003b705cfSriastradh return true; 266103b705cfSriastradh} 266203b705cfSriastradh 266303b705cfSriastradhbool sna_blt_fill_boxes(struct sna *sna, uint8_t alu, 266403b705cfSriastradh struct kgem_bo *bo, int bpp, 266503b705cfSriastradh uint32_t pixel, 266603b705cfSriastradh const BoxRec *box, int nbox) 266703b705cfSriastradh{ 266803b705cfSriastradh struct kgem *kgem = &sna->kgem; 266903b705cfSriastradh uint32_t br13, cmd; 267003b705cfSriastradh 267103b705cfSriastradh#if DEBUG_NO_BLT || NO_BLT_FILL_BOXES 267203b705cfSriastradh return false; 267303b705cfSriastradh#endif 267403b705cfSriastradh 267503b705cfSriastradh DBG(("%s (%d, %08x, %d) x %d\n", 267603b705cfSriastradh __FUNCTION__, bpp, pixel, alu, nbox)); 267703b705cfSriastradh 267803b705cfSriastradh if (!kgem_bo_can_blt(kgem, bo)) { 267903b705cfSriastradh DBG(("%s: fallback -- cannot blt to dst\n", __FUNCTION__)); 268003b705cfSriastradh return false; 268103b705cfSriastradh } 268203b705cfSriastradh 268303b705cfSriastradh if (alu == GXclear) 268403b705cfSriastradh pixel = 0; 268503b705cfSriastradh else if (alu == GXcopy) { 268603b705cfSriastradh if (pixel == 0) 268703b705cfSriastradh alu = GXclear; 268803b705cfSriastradh else if (pixel == -1) 268903b705cfSriastradh alu = GXset; 269003b705cfSriastradh } 269103b705cfSriastradh 269203b705cfSriastradh if (nbox == 1 && sna_blt_fill_box(sna, alu, bo, bpp, pixel, box)) 269303b705cfSriastradh return true; 269403b705cfSriastradh 269503b705cfSriastradh br13 = bo->pitch; 269603b705cfSriastradh cmd = XY_SCANLINE_BLT; 269703b705cfSriastradh if (kgem->gen >= 040 && bo->tiling) { 269803b705cfSriastradh cmd |= 1 << 11; 269903b705cfSriastradh br13 >>= 2; 270003b705cfSriastradh } 270103b705cfSriastradh assert(br13 <= MAXSHORT); 270203b705cfSriastradh 270303b705cfSriastradh br13 |= 1<<31 | fill_ROP[alu] << 16; 270403b705cfSriastradh switch (bpp) { 270503b705cfSriastradh default: assert(0); 270603b705cfSriastradh case 32: br13 |= 1 << 25; /* RGB8888 */ 270703b705cfSriastradh case 16: br13 |= 1 << 24; /* RGB565 */ 270803b705cfSriastradh case 8: break; 270903b705cfSriastradh } 271003b705cfSriastradh 271103b705cfSriastradh kgem_set_mode(kgem, KGEM_BLT, bo); 271203b705cfSriastradh if (!kgem_check_batch(kgem, 12) || 271303b705cfSriastradh !kgem_check_bo_fenced(kgem, bo)) { 271403b705cfSriastradh kgem_submit(kgem); 271503b705cfSriastradh if (!kgem_check_bo_fenced(&sna->kgem, bo)) 271603b705cfSriastradh return false; 271703b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 271803b705cfSriastradh } 271903b705cfSriastradh 272003b705cfSriastradh if (sna->blt_state.fill_bo != bo->unique_id || 272103b705cfSriastradh sna->blt_state.fill_pixel != pixel || 272203b705cfSriastradh sna->blt_state.fill_alu != alu) 272303b705cfSriastradh { 272403b705cfSriastradh uint32_t *b; 272503b705cfSriastradh 272603b705cfSriastradh if (!kgem_check_reloc(kgem, 1)) { 272703b705cfSriastradh _kgem_submit(kgem); 272803b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 272903b705cfSriastradh } 273003b705cfSriastradh 273103b705cfSriastradh b = kgem->batch + kgem->nbatch; 273203b705cfSriastradh b[0] = XY_SETUP_MONO_PATTERN_SL_BLT; 273303b705cfSriastradh if (bpp == 32) 273403b705cfSriastradh b[0] |= BLT_WRITE_ALPHA | BLT_WRITE_RGB; 273503b705cfSriastradh b[1] = br13; 273603b705cfSriastradh b[2] = 0; 273703b705cfSriastradh b[3] = 0; 273803b705cfSriastradh b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, bo, 273903b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 274003b705cfSriastradh I915_GEM_DOMAIN_RENDER | 274103b705cfSriastradh KGEM_RELOC_FENCED, 274203b705cfSriastradh 0); 274303b705cfSriastradh b[5] = pixel; 274403b705cfSriastradh b[6] = pixel; 274503b705cfSriastradh b[7] = 0; 274603b705cfSriastradh b[8] = 0; 274703b705cfSriastradh kgem->nbatch += 9; 274803b705cfSriastradh assert(kgem->nbatch < kgem->surface); 274903b705cfSriastradh 275003b705cfSriastradh sna->blt_state.fill_bo = bo->unique_id; 275103b705cfSriastradh sna->blt_state.fill_pixel = pixel; 275203b705cfSriastradh sna->blt_state.fill_alu = alu; 275303b705cfSriastradh } 275403b705cfSriastradh 275503b705cfSriastradh do { 275603b705cfSriastradh int nbox_this_time; 275703b705cfSriastradh 275803b705cfSriastradh nbox_this_time = nbox; 275903b705cfSriastradh if (3*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) 276003b705cfSriastradh nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 3; 276103b705cfSriastradh assert(nbox_this_time); 276203b705cfSriastradh nbox -= nbox_this_time; 276303b705cfSriastradh 276403b705cfSriastradh do { 276503b705cfSriastradh uint32_t *b; 276603b705cfSriastradh 276703b705cfSriastradh DBG(("%s: (%d, %d), (%d, %d): %08x\n", 276803b705cfSriastradh __FUNCTION__, 276903b705cfSriastradh box->x1, box->y1, 277003b705cfSriastradh box->x2, box->y2, 277103b705cfSriastradh pixel)); 277203b705cfSriastradh 277303b705cfSriastradh assert(box->x1 >= 0); 277403b705cfSriastradh assert(box->y1 >= 0); 277503b705cfSriastradh assert(box->y2 * bo->pitch <= kgem_bo_size(bo)); 277603b705cfSriastradh 277703b705cfSriastradh b = kgem->batch + kgem->nbatch; 277803b705cfSriastradh kgem->nbatch += 3; 277903b705cfSriastradh assert(kgem->nbatch < kgem->surface); 278003b705cfSriastradh b[0] = cmd; 278103b705cfSriastradh *(uint64_t *)(b+1) = *(const uint64_t *)box; 278203b705cfSriastradh box++; 278303b705cfSriastradh } while (--nbox_this_time); 278403b705cfSriastradh 278503b705cfSriastradh if (nbox) { 278603b705cfSriastradh uint32_t *b; 278703b705cfSriastradh 278803b705cfSriastradh _kgem_submit(kgem); 278903b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 279003b705cfSriastradh 279103b705cfSriastradh b = kgem->batch + kgem->nbatch; 279203b705cfSriastradh b[0] = XY_SETUP_MONO_PATTERN_SL_BLT; 279303b705cfSriastradh if (bpp == 32) 279403b705cfSriastradh b[0] |= BLT_WRITE_ALPHA | BLT_WRITE_RGB; 279503b705cfSriastradh b[1] = br13; 279603b705cfSriastradh b[2] = 0; 279703b705cfSriastradh b[3] = 0; 279803b705cfSriastradh b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, bo, 279903b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 280003b705cfSriastradh I915_GEM_DOMAIN_RENDER | 280103b705cfSriastradh KGEM_RELOC_FENCED, 280203b705cfSriastradh 0); 280303b705cfSriastradh b[5] = pixel; 280403b705cfSriastradh b[6] = pixel; 280503b705cfSriastradh b[7] = 0; 280603b705cfSriastradh b[8] = 0; 280703b705cfSriastradh kgem->nbatch += 9; 280803b705cfSriastradh assert(kgem->nbatch < kgem->surface); 280903b705cfSriastradh } 281003b705cfSriastradh } while (nbox); 281103b705cfSriastradh 281203b705cfSriastradh if (kgem->nexec > 1 && __kgem_ring_empty(kgem)) 281303b705cfSriastradh _kgem_submit(kgem); 281403b705cfSriastradh 281503b705cfSriastradh return true; 281603b705cfSriastradh} 281703b705cfSriastradh 281803b705cfSriastradhbool sna_blt_copy_boxes(struct sna *sna, uint8_t alu, 281903b705cfSriastradh struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, 282003b705cfSriastradh struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, 282103b705cfSriastradh int bpp, const BoxRec *box, int nbox) 282203b705cfSriastradh{ 282303b705cfSriastradh struct kgem *kgem = &sna->kgem; 282403b705cfSriastradh unsigned src_pitch, br13, cmd; 282503b705cfSriastradh 282603b705cfSriastradh#if DEBUG_NO_BLT || NO_BLT_COPY_BOXES 282703b705cfSriastradh return false; 282803b705cfSriastradh#endif 282903b705cfSriastradh 283003b705cfSriastradh DBG(("%s src=(%d, %d) -> (%d, %d) x %d, tiling=(%d, %d), pitch=(%d, %d)\n", 283103b705cfSriastradh __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, nbox, 283203b705cfSriastradh src_bo->tiling, dst_bo->tiling, 283303b705cfSriastradh src_bo->pitch, dst_bo->pitch)); 283403b705cfSriastradh 283503b705cfSriastradh if (!kgem_bo_can_blt(kgem, src_bo) || !kgem_bo_can_blt(kgem, dst_bo)) { 283603b705cfSriastradh DBG(("%s: cannot blt to src? %d or dst? %d\n", 283703b705cfSriastradh __FUNCTION__, 283803b705cfSriastradh kgem_bo_can_blt(kgem, src_bo), 283903b705cfSriastradh kgem_bo_can_blt(kgem, dst_bo))); 284003b705cfSriastradh return false; 284103b705cfSriastradh } 284203b705cfSriastradh 284303b705cfSriastradh cmd = XY_SRC_COPY_BLT_CMD; 284403b705cfSriastradh if (bpp == 32) 284503b705cfSriastradh cmd |= BLT_WRITE_ALPHA | BLT_WRITE_RGB; 284603b705cfSriastradh 284703b705cfSriastradh src_pitch = src_bo->pitch; 284803b705cfSriastradh if (kgem->gen >= 040 && src_bo->tiling) { 284903b705cfSriastradh cmd |= BLT_SRC_TILED; 285003b705cfSriastradh src_pitch >>= 2; 285103b705cfSriastradh } 285203b705cfSriastradh assert(src_pitch <= MAXSHORT); 285303b705cfSriastradh 285403b705cfSriastradh br13 = dst_bo->pitch; 285503b705cfSriastradh if (kgem->gen >= 040 && dst_bo->tiling) { 285603b705cfSriastradh cmd |= BLT_DST_TILED; 285703b705cfSriastradh br13 >>= 2; 285803b705cfSriastradh } 285903b705cfSriastradh assert(br13 <= MAXSHORT); 286003b705cfSriastradh 286103b705cfSriastradh br13 |= copy_ROP[alu] << 16; 286203b705cfSriastradh switch (bpp) { 286303b705cfSriastradh default: assert(0); 286403b705cfSriastradh case 32: br13 |= 1 << 25; /* RGB8888 */ 286503b705cfSriastradh case 16: br13 |= 1 << 24; /* RGB565 */ 286603b705cfSriastradh case 8: break; 286703b705cfSriastradh } 286803b705cfSriastradh 286903b705cfSriastradh /* Compare first box against a previous fill */ 287003b705cfSriastradh if (kgem->nbatch >= 6 && 287103b705cfSriastradh (alu == GXcopy || alu == GXclear || alu == GXset) && 287203b705cfSriastradh kgem->reloc[kgem->nreloc-1].target_handle == dst_bo->target_handle && 287303b705cfSriastradh kgem->batch[kgem->nbatch-6] == ((cmd & ~XY_SRC_COPY_BLT_CMD) | XY_COLOR_BLT) && 287403b705cfSriastradh kgem->batch[kgem->nbatch-4] == ((uint32_t)(box->y1 + dst_dy) << 16 | (uint16_t)(box->x1 + dst_dx)) && 287503b705cfSriastradh kgem->batch[kgem->nbatch-3] == ((uint32_t)(box->y2 + dst_dy) << 16 | (uint16_t)(box->x2 + dst_dx))) { 287603b705cfSriastradh DBG(("%s: deleting last fill\n", __FUNCTION__)); 287703b705cfSriastradh kgem->nbatch -= 6; 287803b705cfSriastradh kgem->nreloc--; 287903b705cfSriastradh } 288003b705cfSriastradh 288103b705cfSriastradh kgem_set_mode(kgem, KGEM_BLT, dst_bo); 288203b705cfSriastradh if (!kgem_check_batch(kgem, 8) || 288303b705cfSriastradh !kgem_check_reloc(kgem, 2) || 288403b705cfSriastradh !kgem_check_many_bo_fenced(kgem, dst_bo, src_bo, NULL)) { 288503b705cfSriastradh kgem_submit(kgem); 288603b705cfSriastradh if (!kgem_check_many_bo_fenced(kgem, dst_bo, src_bo, NULL)) 288703b705cfSriastradh return sna_tiling_blt_copy_boxes(sna, alu, 288803b705cfSriastradh src_bo, src_dx, src_dy, 288903b705cfSriastradh dst_bo, dst_dx, dst_dy, 289003b705cfSriastradh bpp, box, nbox); 289103b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 289203b705cfSriastradh } 289303b705cfSriastradh 289403b705cfSriastradh if ((dst_dx | dst_dy) == 0) { 289503b705cfSriastradh uint64_t hdr = (uint64_t)br13 << 32 | cmd; 289603b705cfSriastradh do { 289703b705cfSriastradh int nbox_this_time; 289803b705cfSriastradh 289903b705cfSriastradh nbox_this_time = nbox; 290003b705cfSriastradh if (8*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) 290103b705cfSriastradh nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; 290203b705cfSriastradh if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) 290303b705cfSriastradh nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc)/2; 290403b705cfSriastradh assert(nbox_this_time); 290503b705cfSriastradh nbox -= nbox_this_time; 290603b705cfSriastradh 290703b705cfSriastradh do { 290803b705cfSriastradh uint32_t *b = kgem->batch + kgem->nbatch; 290903b705cfSriastradh 291003b705cfSriastradh DBG((" %s: box=(%d, %d)x(%d, %d)\n", 291103b705cfSriastradh __FUNCTION__, 291203b705cfSriastradh box->x1, box->y1, 291303b705cfSriastradh box->x2 - box->x1, box->y2 - box->y1)); 291403b705cfSriastradh 291503b705cfSriastradh assert(box->x1 + src_dx >= 0); 291603b705cfSriastradh assert(box->y1 + src_dy >= 0); 291703b705cfSriastradh assert(box->x1 + src_dx <= INT16_MAX); 291803b705cfSriastradh assert(box->y1 + src_dy <= INT16_MAX); 291903b705cfSriastradh 292003b705cfSriastradh assert(box->x1 >= 0); 292103b705cfSriastradh assert(box->y1 >= 0); 292203b705cfSriastradh 292303b705cfSriastradh *(uint64_t *)&b[0] = hdr; 292403b705cfSriastradh *(uint64_t *)&b[2] = *(const uint64_t *)box; 292503b705cfSriastradh b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, dst_bo, 292603b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 292703b705cfSriastradh I915_GEM_DOMAIN_RENDER | 292803b705cfSriastradh KGEM_RELOC_FENCED, 292903b705cfSriastradh 0); 293003b705cfSriastradh b[5] = add2(b[2], src_dx, src_dy); 293103b705cfSriastradh b[6] = src_pitch; 293203b705cfSriastradh b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7, src_bo, 293303b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 293403b705cfSriastradh KGEM_RELOC_FENCED, 293503b705cfSriastradh 0); 293603b705cfSriastradh kgem->nbatch += 8; 293703b705cfSriastradh assert(kgem->nbatch < kgem->surface); 293803b705cfSriastradh box++; 293903b705cfSriastradh } while (--nbox_this_time); 294003b705cfSriastradh 294103b705cfSriastradh if (!nbox) 294203b705cfSriastradh break; 294303b705cfSriastradh 294403b705cfSriastradh _kgem_submit(kgem); 294503b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 294603b705cfSriastradh } while (1); 294703b705cfSriastradh } else { 294803b705cfSriastradh do { 294903b705cfSriastradh int nbox_this_time; 295003b705cfSriastradh 295103b705cfSriastradh nbox_this_time = nbox; 295203b705cfSriastradh if (8*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) 295303b705cfSriastradh nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; 295403b705cfSriastradh if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) 295503b705cfSriastradh nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc)/2; 295603b705cfSriastradh assert(nbox_this_time); 295703b705cfSriastradh nbox -= nbox_this_time; 295803b705cfSriastradh 295903b705cfSriastradh do { 296003b705cfSriastradh uint32_t *b = kgem->batch + kgem->nbatch; 296103b705cfSriastradh 296203b705cfSriastradh DBG((" %s: box=(%d, %d)x(%d, %d)\n", 296303b705cfSriastradh __FUNCTION__, 296403b705cfSriastradh box->x1, box->y1, 296503b705cfSriastradh box->x2 - box->x1, box->y2 - box->y1)); 296603b705cfSriastradh 296703b705cfSriastradh assert(box->x1 + src_dx >= 0); 296803b705cfSriastradh assert(box->y1 + src_dy >= 0); 296903b705cfSriastradh 297003b705cfSriastradh assert(box->x1 + dst_dx >= 0); 297103b705cfSriastradh assert(box->y1 + dst_dy >= 0); 297203b705cfSriastradh 297303b705cfSriastradh b[0] = cmd; 297403b705cfSriastradh b[1] = br13; 297503b705cfSriastradh b[2] = ((box->y1 + dst_dy) << 16) | (box->x1 + dst_dx); 297603b705cfSriastradh b[3] = ((box->y2 + dst_dy) << 16) | (box->x2 + dst_dx); 297703b705cfSriastradh b[4] = kgem_add_reloc(kgem, kgem->nbatch + 4, dst_bo, 297803b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 297903b705cfSriastradh I915_GEM_DOMAIN_RENDER | 298003b705cfSriastradh KGEM_RELOC_FENCED, 298103b705cfSriastradh 0); 298203b705cfSriastradh b[5] = ((box->y1 + src_dy) << 16) | (box->x1 + src_dx); 298303b705cfSriastradh b[6] = src_pitch; 298403b705cfSriastradh b[7] = kgem_add_reloc(kgem, kgem->nbatch + 7, src_bo, 298503b705cfSriastradh I915_GEM_DOMAIN_RENDER << 16 | 298603b705cfSriastradh KGEM_RELOC_FENCED, 298703b705cfSriastradh 0); 298803b705cfSriastradh kgem->nbatch += 8; 298903b705cfSriastradh assert(kgem->nbatch < kgem->surface); 299003b705cfSriastradh box++; 299103b705cfSriastradh } while (--nbox_this_time); 299203b705cfSriastradh 299303b705cfSriastradh if (!nbox) 299403b705cfSriastradh break; 299503b705cfSriastradh 299603b705cfSriastradh _kgem_submit(kgem); 299703b705cfSriastradh _kgem_set_mode(kgem, KGEM_BLT); 299803b705cfSriastradh } while (1); 299903b705cfSriastradh } 300003b705cfSriastradh 300103b705cfSriastradh if (kgem->nexec > 1 && __kgem_ring_empty(kgem)) { 300203b705cfSriastradh _kgem_submit(kgem); 300303b705cfSriastradh } else if (kgem->gen >= 060 && kgem_check_batch(kgem, 3)) { 300403b705cfSriastradh uint32_t *b = kgem->batch + kgem->nbatch; 300503b705cfSriastradh b[0] = XY_SETUP_CLIP; 300603b705cfSriastradh b[1] = b[2] = 0; 300703b705cfSriastradh kgem->nbatch += 3; 300803b705cfSriastradh assert(kgem->nbatch < kgem->surface); 300903b705cfSriastradh } 301003b705cfSriastradh 301103b705cfSriastradh sna->blt_state.fill_bo = 0; 301203b705cfSriastradh return true; 301303b705cfSriastradh} 301403b705cfSriastradh 301503b705cfSriastradhstatic void box_extents(const BoxRec *box, int n, BoxRec *extents) 301603b705cfSriastradh{ 301703b705cfSriastradh *extents = *box; 301803b705cfSriastradh while (--n) { 301903b705cfSriastradh box++; 302003b705cfSriastradh if (box->x1 < extents->x1) 302103b705cfSriastradh extents->x1 = box->x1; 302203b705cfSriastradh if (box->y1 < extents->y1) 302303b705cfSriastradh extents->y1 = box->y1; 302403b705cfSriastradh 302503b705cfSriastradh if (box->x2 > extents->x2) 302603b705cfSriastradh extents->x2 = box->x2; 302703b705cfSriastradh if (box->y2 > extents->y2) 302803b705cfSriastradh extents->y2 = box->y2; 302903b705cfSriastradh } 303003b705cfSriastradh} 303103b705cfSriastradh 303203b705cfSriastradhbool sna_blt_copy_boxes_fallback(struct sna *sna, uint8_t alu, 303303b705cfSriastradh PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, 303403b705cfSriastradh PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, 303503b705cfSriastradh const BoxRec *box, int nbox) 303603b705cfSriastradh{ 303703b705cfSriastradh struct kgem_bo *free_bo = NULL; 303803b705cfSriastradh bool ret; 303903b705cfSriastradh 304003b705cfSriastradh DBG(("%s: alu=%d, n=%d\n", __FUNCTION__, alu, nbox)); 304103b705cfSriastradh 304203b705cfSriastradh if (!sna_blt_compare_depth(&src->drawable, &dst->drawable)) { 304303b705cfSriastradh DBG(("%s: mismatching depths %d -> %d\n", 304403b705cfSriastradh __FUNCTION__, src->drawable.depth, dst->drawable.depth)); 304503b705cfSriastradh return false; 304603b705cfSriastradh } 304703b705cfSriastradh 304803b705cfSriastradh if (src_bo == dst_bo) { 304903b705cfSriastradh DBG(("%s: dst == src\n", __FUNCTION__)); 305003b705cfSriastradh 305103b705cfSriastradh if (src_bo->tiling == I915_TILING_Y && 305203b705cfSriastradh kgem_bo_blt_pitch_is_ok(&sna->kgem, src_bo)) { 305303b705cfSriastradh struct kgem_bo *bo; 305403b705cfSriastradh 305503b705cfSriastradh DBG(("%s: src is Y-tiled\n", __FUNCTION__)); 305603b705cfSriastradh 305703b705cfSriastradh assert(src_bo == sna_pixmap(src)->gpu_bo); 305803b705cfSriastradh bo = sna_pixmap_change_tiling(src, I915_TILING_X); 305903b705cfSriastradh if (bo == NULL) { 306003b705cfSriastradh BoxRec extents; 306103b705cfSriastradh 306203b705cfSriastradh DBG(("%s: y-tiling conversion failed\n", 306303b705cfSriastradh __FUNCTION__)); 306403b705cfSriastradh 306503b705cfSriastradh box_extents(box, nbox, &extents); 306603b705cfSriastradh free_bo = kgem_create_2d(&sna->kgem, 306703b705cfSriastradh extents.x2 - extents.x1, 306803b705cfSriastradh extents.y2 - extents.y1, 306903b705cfSriastradh src->drawable.bitsPerPixel, 307003b705cfSriastradh I915_TILING_X, 0); 307103b705cfSriastradh if (free_bo == NULL) { 307203b705cfSriastradh DBG(("%s: fallback -- temp allocation failed\n", 307303b705cfSriastradh __FUNCTION__)); 307403b705cfSriastradh return false; 307503b705cfSriastradh } 307603b705cfSriastradh 307703b705cfSriastradh if (!sna_blt_copy_boxes(sna, GXcopy, 307803b705cfSriastradh src_bo, src_dx, src_dy, 307903b705cfSriastradh free_bo, -extents.x1, -extents.y1, 308003b705cfSriastradh src->drawable.bitsPerPixel, 308103b705cfSriastradh box, nbox)) { 308203b705cfSriastradh DBG(("%s: fallback -- temp copy failed\n", 308303b705cfSriastradh __FUNCTION__)); 308403b705cfSriastradh kgem_bo_destroy(&sna->kgem, free_bo); 308503b705cfSriastradh return false; 308603b705cfSriastradh } 308703b705cfSriastradh 308803b705cfSriastradh src_dx = -extents.x1; 308903b705cfSriastradh src_dy = -extents.y1; 309003b705cfSriastradh src_bo = free_bo; 309103b705cfSriastradh } else 309203b705cfSriastradh dst_bo = src_bo = bo; 309303b705cfSriastradh } 309403b705cfSriastradh } else { 309503b705cfSriastradh if (src_bo->tiling == I915_TILING_Y && 309603b705cfSriastradh kgem_bo_blt_pitch_is_ok(&sna->kgem, src_bo)) { 309703b705cfSriastradh DBG(("%s: src is y-tiled\n", __FUNCTION__)); 309803b705cfSriastradh assert(src_bo == sna_pixmap(src)->gpu_bo); 309903b705cfSriastradh src_bo = sna_pixmap_change_tiling(src, I915_TILING_X); 310003b705cfSriastradh if (src_bo == NULL) { 310103b705cfSriastradh DBG(("%s: fallback -- src y-tiling conversion failed\n", 310203b705cfSriastradh __FUNCTION__)); 310303b705cfSriastradh return false; 310403b705cfSriastradh } 310503b705cfSriastradh } 310603b705cfSriastradh 310703b705cfSriastradh if (dst_bo->tiling == I915_TILING_Y && 310803b705cfSriastradh kgem_bo_blt_pitch_is_ok(&sna->kgem, dst_bo)) { 310903b705cfSriastradh DBG(("%s: dst is y-tiled\n", __FUNCTION__)); 311003b705cfSriastradh assert(dst_bo == sna_pixmap(dst)->gpu_bo); 311103b705cfSriastradh dst_bo = sna_pixmap_change_tiling(dst, I915_TILING_X); 311203b705cfSriastradh if (dst_bo == NULL) { 311303b705cfSriastradh DBG(("%s: fallback -- dst y-tiling conversion failed\n", 311403b705cfSriastradh __FUNCTION__)); 311503b705cfSriastradh return false; 311603b705cfSriastradh } 311703b705cfSriastradh } 311803b705cfSriastradh } 311903b705cfSriastradh 312003b705cfSriastradh ret = sna_blt_copy_boxes(sna, alu, 312103b705cfSriastradh src_bo, src_dx, src_dy, 312203b705cfSriastradh dst_bo, dst_dx, dst_dy, 312303b705cfSriastradh dst->drawable.bitsPerPixel, 312403b705cfSriastradh box, nbox); 312503b705cfSriastradh 312603b705cfSriastradh if (free_bo) 312703b705cfSriastradh kgem_bo_destroy(&sna->kgem, free_bo); 312803b705cfSriastradh 312903b705cfSriastradh return ret; 313003b705cfSriastradh} 3131