103b705cfSriastradh#ifndef SNA_RENDER_INLINE_H 203b705cfSriastradh#define SNA_RENDER_INLINE_H 303b705cfSriastradh 403b705cfSriastradhstatic inline bool need_tiling(struct sna *sna, int16_t width, int16_t height) 503b705cfSriastradh{ 603b705cfSriastradh /* Is the damage area too large to fit in 3D pipeline, 703b705cfSriastradh * and so do we need to split the operation up into tiles? 803b705cfSriastradh */ 903b705cfSriastradh return (width > sna->render.max_3d_size || 1003b705cfSriastradh height > sna->render.max_3d_size); 1103b705cfSriastradh} 1203b705cfSriastradh 1303b705cfSriastradhstatic inline bool need_redirect(struct sna *sna, PixmapPtr dst) 1403b705cfSriastradh{ 1503b705cfSriastradh /* Is the pixmap too large to render to? */ 1603b705cfSriastradh return (dst->drawable.width > sna->render.max_3d_size || 1703b705cfSriastradh dst->drawable.height > sna->render.max_3d_size); 1803b705cfSriastradh} 1903b705cfSriastradh 2003b705cfSriastradhstatic force_inline float pack_2s(int16_t x, int16_t y) 2103b705cfSriastradh{ 2203b705cfSriastradh union { 2303b705cfSriastradh struct sna_coordinate p; 2403b705cfSriastradh float f; 2503b705cfSriastradh } u; 2603b705cfSriastradh u.p.x = x; 2703b705cfSriastradh u.p.y = y; 2803b705cfSriastradh return u.f; 2903b705cfSriastradh} 3003b705cfSriastradh 3103b705cfSriastradhstatic force_inline int vertex_space(struct sna *sna) 3203b705cfSriastradh{ 3303b705cfSriastradh return sna->render.vertex_size - sna->render.vertex_used; 3403b705cfSriastradh} 3503b705cfSriastradhstatic force_inline void vertex_emit(struct sna *sna, float v) 3603b705cfSriastradh{ 3703b705cfSriastradh assert(sna->render.vertex_used < sna->render.vertex_size); 3803b705cfSriastradh sna->render.vertices[sna->render.vertex_used++] = v; 3903b705cfSriastradh} 4003b705cfSriastradhstatic force_inline void vertex_emit_2s(struct sna *sna, int16_t x, int16_t y) 4103b705cfSriastradh{ 4203b705cfSriastradh vertex_emit(sna, pack_2s(x, y)); 4303b705cfSriastradh} 4403b705cfSriastradh 4503b705cfSriastradhstatic force_inline int batch_space(struct sna *sna) 4603b705cfSriastradh{ 4703b705cfSriastradh assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem)); 4803b705cfSriastradh assert(sna->kgem.nbatch + KGEM_BATCH_RESERVED <= sna->kgem.surface); 4903b705cfSriastradh return sna->kgem.surface - sna->kgem.nbatch - KGEM_BATCH_RESERVED; 5003b705cfSriastradh} 5103b705cfSriastradh 5203b705cfSriastradhstatic force_inline void batch_emit(struct sna *sna, uint32_t dword) 5303b705cfSriastradh{ 5403b705cfSriastradh assert(sna->kgem.mode != KGEM_NONE); 5503b705cfSriastradh assert(sna->kgem.nbatch + KGEM_BATCH_RESERVED < sna->kgem.surface); 5603b705cfSriastradh sna->kgem.batch[sna->kgem.nbatch++] = dword; 5703b705cfSriastradh} 5803b705cfSriastradh 59fe8aea9eSmrgstatic force_inline void batch_emit_aligned(struct sna *sna, uint32_t dword, unsigned align) 60fe8aea9eSmrg{ 61fe8aea9eSmrg assert(sna->kgem.mode != KGEM_NONE); 62fe8aea9eSmrg assert(sna->kgem.nbatch + KGEM_BATCH_RESERVED < sna->kgem.surface); 63fe8aea9eSmrg while (sna->kgem.nbatch & (align-1)) 64fe8aea9eSmrg sna->kgem.batch[sna->kgem.nbatch++] = 0; 65fe8aea9eSmrg sna->kgem.batch[sna->kgem.nbatch++] = dword; 66fe8aea9eSmrg} 67fe8aea9eSmrg 6842542f5fSchristosstatic force_inline void batch_emit64(struct sna *sna, uint64_t qword) 6942542f5fSchristos{ 7042542f5fSchristos assert(sna->kgem.mode != KGEM_NONE); 7142542f5fSchristos assert(sna->kgem.nbatch + 2 + KGEM_BATCH_RESERVED < sna->kgem.surface); 7242542f5fSchristos *(uint64_t *)(sna->kgem.batch+sna->kgem.nbatch) = qword; 7342542f5fSchristos sna->kgem.nbatch += 2; 7442542f5fSchristos} 7542542f5fSchristos 7603b705cfSriastradhstatic force_inline void batch_emit_float(struct sna *sna, float f) 7703b705cfSriastradh{ 7803b705cfSriastradh union { 7903b705cfSriastradh uint32_t dw; 8003b705cfSriastradh float f; 8103b705cfSriastradh } u; 8203b705cfSriastradh u.f = f; 8303b705cfSriastradh batch_emit(sna, u.dw); 8403b705cfSriastradh} 8503b705cfSriastradh 8603b705cfSriastradhstatic inline bool 8703b705cfSriastradhis_gpu(struct sna *sna, DrawablePtr drawable, unsigned prefer) 8803b705cfSriastradh{ 8903b705cfSriastradh struct sna_pixmap *priv = sna_pixmap_from_drawable(drawable); 9003b705cfSriastradh 9103b705cfSriastradh if (priv == NULL || priv->clear || priv->cpu) 9203b705cfSriastradh return false; 9303b705cfSriastradh 9403b705cfSriastradh if (priv->cpu_damage == NULL) 9503b705cfSriastradh return true; 9603b705cfSriastradh 9703b705cfSriastradh if (priv->gpu_damage && !priv->gpu_bo->proxy && 9803b705cfSriastradh (sna->render.prefer_gpu & prefer)) 9903b705cfSriastradh return true; 10003b705cfSriastradh 10103b705cfSriastradh if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) 10203b705cfSriastradh return true; 10303b705cfSriastradh 10442542f5fSchristos if (DAMAGE_IS_ALL(priv->cpu_damage)) 10542542f5fSchristos return false; 10642542f5fSchristos 10703b705cfSriastradh return priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo); 10803b705cfSriastradh} 10903b705cfSriastradh 11003b705cfSriastradhstatic inline bool 11103b705cfSriastradhtoo_small(struct sna_pixmap *priv) 11203b705cfSriastradh{ 11303b705cfSriastradh assert(priv); 11403b705cfSriastradh 11503b705cfSriastradh if (priv->gpu_bo) 11603b705cfSriastradh return false; 11703b705cfSriastradh 11803b705cfSriastradh if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) 11903b705cfSriastradh return false; 12003b705cfSriastradh 12103b705cfSriastradh return (priv->create & KGEM_CAN_CREATE_GPU) == 0; 12203b705cfSriastradh} 12303b705cfSriastradh 12413496ba1Ssnjstatic inline bool 12513496ba1Ssnjcan_render_to_picture(PicturePtr dst) 12613496ba1Ssnj{ 12713496ba1Ssnj if (dst->alphaMap) { 12813496ba1Ssnj DBG(("%s(pixmap=%ld) -- no, has alphamap\n", __FUNCTION__, 12913496ba1Ssnj get_drawable_pixmap(dst->pDrawable)->drawable.serialNumber)); 13013496ba1Ssnj return false; 13113496ba1Ssnj } 13213496ba1Ssnj 13313496ba1Ssnj switch (PICT_FORMAT_TYPE(dst->format)) { 13413496ba1Ssnj case PICT_TYPE_COLOR: 13513496ba1Ssnj case PICT_TYPE_GRAY: 13613496ba1Ssnj case PICT_TYPE_OTHER: 13713496ba1Ssnj DBG(("%s(pixmap=%ld) -- no, has palette\n", __FUNCTION__, 13813496ba1Ssnj get_drawable_pixmap(dst->pDrawable)->drawable.serialNumber)); 13913496ba1Ssnj return false; 14013496ba1Ssnj default: 14113496ba1Ssnj break; 14213496ba1Ssnj } 14313496ba1Ssnj 14413496ba1Ssnj return true; 14513496ba1Ssnj} 14613496ba1Ssnj 14713496ba1Ssnj 14842542f5fSchristosstatic inline bool 14942542f5fSchristosis_gpu_dst(struct sna_pixmap *priv) 15042542f5fSchristos{ 15142542f5fSchristos assert(priv); 15242542f5fSchristos 15342542f5fSchristos if (too_small(priv)) 15442542f5fSchristos return false; 15542542f5fSchristos 15642542f5fSchristos if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo)) 15742542f5fSchristos return true; 15842542f5fSchristos 15942542f5fSchristos if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) 16042542f5fSchristos return true; 16142542f5fSchristos 16242542f5fSchristos if (DAMAGE_IS_ALL(priv->cpu_damage)) 16342542f5fSchristos return false; 16442542f5fSchristos 16542542f5fSchristos return priv->gpu_damage != NULL || !priv->cpu; 16642542f5fSchristos} 16742542f5fSchristos 16803b705cfSriastradhstatic inline bool 16903b705cfSriastradhunattached(DrawablePtr drawable) 17003b705cfSriastradh{ 17103b705cfSriastradh struct sna_pixmap *priv = sna_pixmap_from_drawable(drawable); 17203b705cfSriastradh return priv == NULL || (priv->gpu_damage == NULL && priv->cpu_damage && !priv->cpu_bo); 17303b705cfSriastradh} 17403b705cfSriastradh 17503b705cfSriastradhstatic inline bool 17642542f5fSchristospicture_is_gpu(struct sna *sna, PicturePtr picture, unsigned flags) 17703b705cfSriastradh{ 17842542f5fSchristos if (!picture) 17903b705cfSriastradh return false; 18042542f5fSchristos 18142542f5fSchristos if (!picture->pDrawable) { 18242542f5fSchristos switch (flags) { 18342542f5fSchristos case PREFER_GPU_RENDER: 18442542f5fSchristos switch (picture->pSourcePict->type) { 18542542f5fSchristos case SourcePictTypeSolidFill: 18642542f5fSchristos case SourcePictTypeLinear: 18742542f5fSchristos return false; 18842542f5fSchristos default: 18942542f5fSchristos return true; 19042542f5fSchristos } 19142542f5fSchristos case PREFER_GPU_SPANS: 19242542f5fSchristos return true; 19342542f5fSchristos default: 19442542f5fSchristos return false; 19542542f5fSchristos } 19642542f5fSchristos } else { 19742542f5fSchristos if (picture->repeat && 19842542f5fSchristos (picture->pDrawable->width | picture->pDrawable->height) == 1) 19942542f5fSchristos return flags == PREFER_GPU_SPANS; 20042542f5fSchristos } 20142542f5fSchristos 20242542f5fSchristos return is_gpu(sna, picture->pDrawable, flags); 20303b705cfSriastradh} 20403b705cfSriastradh 20503b705cfSriastradhstatic inline bool 20603b705cfSriastradhpicture_is_cpu(struct sna *sna, PicturePtr picture) 20703b705cfSriastradh{ 20803b705cfSriastradh if (!picture->pDrawable) 20903b705cfSriastradh return false; 21003b705cfSriastradh 21103b705cfSriastradh return !is_gpu(sna, picture->pDrawable, PREFER_GPU_RENDER); 21203b705cfSriastradh} 21303b705cfSriastradh 21442542f5fSchristosstatic inline bool sna_blt_compare_depth(const DrawableRec *src, const DrawableRec *dst) 21503b705cfSriastradh{ 21603b705cfSriastradh if (src->depth == dst->depth) 21703b705cfSriastradh return true; 21803b705cfSriastradh 21903b705cfSriastradh /* Also allow for the alpha to be discarded on a copy */ 22003b705cfSriastradh if (src->bitsPerPixel != dst->bitsPerPixel) 22103b705cfSriastradh return false; 22203b705cfSriastradh 22303b705cfSriastradh if (dst->depth == 24 && src->depth == 32) 22403b705cfSriastradh return true; 22503b705cfSriastradh 22603b705cfSriastradh /* Note that a depth-16 pixmap is r5g6b5, not x1r5g5b5. */ 22703b705cfSriastradh 22803b705cfSriastradh return false; 22903b705cfSriastradh} 23003b705cfSriastradh 23103b705cfSriastradhstatic inline struct kgem_bo * 23203b705cfSriastradhsna_render_get_alpha_gradient(struct sna *sna) 23303b705cfSriastradh{ 23403b705cfSriastradh return kgem_bo_reference(sna->render.alpha_cache.cache_bo); 23503b705cfSriastradh} 23603b705cfSriastradh 23703b705cfSriastradhstatic inline void 23803b705cfSriastradhsna_render_picture_extents(PicturePtr p, BoxRec *box) 23903b705cfSriastradh{ 24003b705cfSriastradh box->x1 = p->pDrawable->x; 24103b705cfSriastradh box->y1 = p->pDrawable->y; 24203b705cfSriastradh box->x2 = bound(box->x1, p->pDrawable->width); 24303b705cfSriastradh box->y2 = bound(box->y1, p->pDrawable->height); 24403b705cfSriastradh 24503b705cfSriastradh if (box->x1 < p->pCompositeClip->extents.x1) 24603b705cfSriastradh box->x1 = p->pCompositeClip->extents.x1; 24703b705cfSriastradh if (box->y1 < p->pCompositeClip->extents.y1) 24803b705cfSriastradh box->y1 = p->pCompositeClip->extents.y1; 24903b705cfSriastradh 25003b705cfSriastradh if (box->x2 > p->pCompositeClip->extents.x2) 25103b705cfSriastradh box->x2 = p->pCompositeClip->extents.x2; 25203b705cfSriastradh if (box->y2 > p->pCompositeClip->extents.y2) 25303b705cfSriastradh box->y2 = p->pCompositeClip->extents.y2; 25403b705cfSriastradh 25503b705cfSriastradh assert(box->x2 > box->x1 && box->y2 > box->y1); 25603b705cfSriastradh} 25703b705cfSriastradh 25803b705cfSriastradhstatic inline void 25903b705cfSriastradhsna_render_reduce_damage(struct sna_composite_op *op, 26003b705cfSriastradh int dst_x, int dst_y, 26103b705cfSriastradh int width, int height) 26203b705cfSriastradh{ 26303b705cfSriastradh BoxRec r; 26403b705cfSriastradh 26503b705cfSriastradh if (op->damage == NULL || *op->damage == NULL) 26603b705cfSriastradh return; 26703b705cfSriastradh 26803b705cfSriastradh if (DAMAGE_IS_ALL(*op->damage)) { 26903b705cfSriastradh DBG(("%s: damage-all, dicarding damage\n", 27003b705cfSriastradh __FUNCTION__)); 27103b705cfSriastradh op->damage = NULL; 27203b705cfSriastradh return; 27303b705cfSriastradh } 27403b705cfSriastradh 27503b705cfSriastradh if (width == 0 || height == 0) 27603b705cfSriastradh return; 27703b705cfSriastradh 27803b705cfSriastradh r.x1 = dst_x + op->dst.x; 27903b705cfSriastradh r.x2 = r.x1 + width; 28003b705cfSriastradh 28103b705cfSriastradh r.y1 = dst_y + op->dst.y; 28203b705cfSriastradh r.y2 = r.y1 + height; 28303b705cfSriastradh 28403b705cfSriastradh if (sna_damage_contains_box__no_reduce(*op->damage, &r)) { 28503b705cfSriastradh DBG(("%s: damage contains render extents, dicarding damage\n", 28603b705cfSriastradh __FUNCTION__)); 28703b705cfSriastradh op->damage = NULL; 28803b705cfSriastradh } 28903b705cfSriastradh} 29003b705cfSriastradh 29103b705cfSriastradhinline static uint32_t 29203b705cfSriastradhcolor_convert(uint32_t pixel, 29303b705cfSriastradh uint32_t src_format, 29403b705cfSriastradh uint32_t dst_format) 29503b705cfSriastradh{ 29603b705cfSriastradh DBG(("%s: src=%08x [%08x]\n", __FUNCTION__, pixel, src_format)); 29703b705cfSriastradh 29803b705cfSriastradh if (src_format != dst_format) { 29903b705cfSriastradh uint16_t red, green, blue, alpha; 30003b705cfSriastradh 30103b705cfSriastradh if (!sna_get_rgba_from_pixel(pixel, 30203b705cfSriastradh &red, &green, &blue, &alpha, 30303b705cfSriastradh src_format)) 30403b705cfSriastradh return 0; 30503b705cfSriastradh 30603b705cfSriastradh if (!sna_get_pixel_from_rgba(&pixel, 30703b705cfSriastradh red, green, blue, alpha, 30803b705cfSriastradh dst_format)) 30903b705cfSriastradh return 0; 31003b705cfSriastradh } 31103b705cfSriastradh 31203b705cfSriastradh DBG(("%s: dst=%08x [%08x]\n", __FUNCTION__, pixel, dst_format)); 31303b705cfSriastradh return pixel; 31403b705cfSriastradh} 31503b705cfSriastradh 316fe8aea9eSmrginline static uint32_t 317fe8aea9eSmrgsolid_color(uint32_t format, uint32_t pixel) 318fe8aea9eSmrg{ 319fe8aea9eSmrg return color_convert(pixel, format, PICT_a8r8g8b8); 320fe8aea9eSmrg} 321fe8aea9eSmrg 32203b705cfSriastradhinline static bool dst_use_gpu(PixmapPtr pixmap) 32303b705cfSriastradh{ 32403b705cfSriastradh struct sna_pixmap *priv = sna_pixmap(pixmap); 32503b705cfSriastradh if (priv == NULL) 32603b705cfSriastradh return false; 32703b705cfSriastradh 32803b705cfSriastradh if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) 32903b705cfSriastradh return true; 33003b705cfSriastradh 33103b705cfSriastradh if (priv->clear) 33203b705cfSriastradh return false; 33303b705cfSriastradh 33403b705cfSriastradh if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo)) 33503b705cfSriastradh return true; 33603b705cfSriastradh 33703b705cfSriastradh return priv->gpu_damage && (!priv->cpu || !priv->cpu_damage); 33803b705cfSriastradh} 33903b705cfSriastradh 34003b705cfSriastradhinline static bool dst_use_cpu(PixmapPtr pixmap) 34103b705cfSriastradh{ 34203b705cfSriastradh struct sna_pixmap *priv = sna_pixmap(pixmap); 34303b705cfSriastradh if (priv == NULL || priv->shm) 34403b705cfSriastradh return true; 34503b705cfSriastradh 34603b705cfSriastradh return priv->cpu_damage && priv->cpu; 34703b705cfSriastradh} 34803b705cfSriastradh 34903b705cfSriastradhinline static bool dst_is_cpu(PixmapPtr pixmap) 35003b705cfSriastradh{ 35103b705cfSriastradh struct sna_pixmap *priv = sna_pixmap(pixmap); 35203b705cfSriastradh return priv == NULL || DAMAGE_IS_ALL(priv->cpu_damage); 35303b705cfSriastradh} 35403b705cfSriastradh 35503b705cfSriastradhinline static bool 35603b705cfSriastradhuntransformed(PicturePtr p) 35703b705cfSriastradh{ 35803b705cfSriastradh return !p->transform || pixman_transform_is_int_translate(p->transform); 35903b705cfSriastradh} 36003b705cfSriastradh 36142542f5fSchristosinline static void 36242542f5fSchristosboxes_extents(const BoxRec *box, int n, BoxRec *extents) 36342542f5fSchristos{ 36442542f5fSchristos *extents = box[0]; 36542542f5fSchristos while (--n) { 36642542f5fSchristos box++; 36742542f5fSchristos 36842542f5fSchristos if (box->x1 < extents->x1) 36942542f5fSchristos extents->x1 = box->x1; 37042542f5fSchristos if (box->x2 > extents->x2) 37142542f5fSchristos extents->x2 = box->x2; 37242542f5fSchristos 37342542f5fSchristos if (box->y1 < extents->y1) 37442542f5fSchristos extents->y1 = box->y1; 37542542f5fSchristos if (box->y2 > extents->y2) 37642542f5fSchristos extents->y2 = box->y2; 37742542f5fSchristos } 37842542f5fSchristos} 37942542f5fSchristos 38042542f5fSchristosinline static bool 38142542f5fSchristosoverlaps(struct sna *sna, 38242542f5fSchristos struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, 38342542f5fSchristos struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, 38442542f5fSchristos const BoxRec *box, int n, unsigned flags, 38542542f5fSchristos BoxRec *extents) 38642542f5fSchristos{ 38742542f5fSchristos if (src_bo != dst_bo) 38842542f5fSchristos return false; 38942542f5fSchristos 39042542f5fSchristos if (flags & COPY_NO_OVERLAP) 39142542f5fSchristos return false; 39242542f5fSchristos 39342542f5fSchristos boxes_extents(box, n, extents); 39442542f5fSchristos return (extents->x2 + src_dx > extents->x1 + dst_dx && 39542542f5fSchristos extents->x1 + src_dx < extents->x2 + dst_dx && 39642542f5fSchristos extents->y2 + src_dy > extents->y1 + dst_dy && 39742542f5fSchristos extents->y1 + src_dy < extents->y2 + dst_dy); 39842542f5fSchristos} 39942542f5fSchristos 40042542f5fSchristosstatic inline long get_picture_id(PicturePtr picture) 40142542f5fSchristos{ 40242542f5fSchristos return picture && picture->pDrawable ? get_drawable_pixmap(picture->pDrawable)->drawable.serialNumber : 0; 40342542f5fSchristos} 40403b705cfSriastradh 40503b705cfSriastradh#endif /* SNA_RENDER_INLINE_H */ 406