1428d7b3dSmrg#ifndef SNA_RENDER_INLINE_H 2428d7b3dSmrg#define SNA_RENDER_INLINE_H 3428d7b3dSmrg 4428d7b3dSmrgstatic inline bool need_tiling(struct sna *sna, int16_t width, int16_t height) 5428d7b3dSmrg{ 6428d7b3dSmrg /* Is the damage area too large to fit in 3D pipeline, 7428d7b3dSmrg * and so do we need to split the operation up into tiles? 8428d7b3dSmrg */ 9428d7b3dSmrg return (width > sna->render.max_3d_size || 10428d7b3dSmrg height > sna->render.max_3d_size); 11428d7b3dSmrg} 12428d7b3dSmrg 13428d7b3dSmrgstatic inline bool need_redirect(struct sna *sna, PixmapPtr dst) 14428d7b3dSmrg{ 15428d7b3dSmrg /* Is the pixmap too large to render to? */ 16428d7b3dSmrg return (dst->drawable.width > sna->render.max_3d_size || 17428d7b3dSmrg dst->drawable.height > sna->render.max_3d_size); 18428d7b3dSmrg} 19428d7b3dSmrg 20428d7b3dSmrgstatic force_inline float pack_2s(int16_t x, int16_t y) 21428d7b3dSmrg{ 22428d7b3dSmrg union { 23428d7b3dSmrg struct sna_coordinate p; 24428d7b3dSmrg float f; 25428d7b3dSmrg } u; 26428d7b3dSmrg u.p.x = x; 27428d7b3dSmrg u.p.y = y; 28428d7b3dSmrg return u.f; 29428d7b3dSmrg} 30428d7b3dSmrg 31428d7b3dSmrgstatic force_inline int vertex_space(struct sna *sna) 32428d7b3dSmrg{ 33428d7b3dSmrg return sna->render.vertex_size - sna->render.vertex_used; 34428d7b3dSmrg} 35428d7b3dSmrgstatic force_inline void vertex_emit(struct sna *sna, float v) 36428d7b3dSmrg{ 37428d7b3dSmrg assert(sna->render.vertex_used < sna->render.vertex_size); 38428d7b3dSmrg sna->render.vertices[sna->render.vertex_used++] = v; 39428d7b3dSmrg} 40428d7b3dSmrgstatic force_inline void vertex_emit_2s(struct sna *sna, int16_t x, int16_t y) 41428d7b3dSmrg{ 42428d7b3dSmrg vertex_emit(sna, pack_2s(x, y)); 43428d7b3dSmrg} 44428d7b3dSmrg 45428d7b3dSmrgstatic force_inline int batch_space(struct sna *sna) 46428d7b3dSmrg{ 47428d7b3dSmrg assert(sna->kgem.nbatch <= KGEM_BATCH_SIZE(&sna->kgem)); 48428d7b3dSmrg assert(sna->kgem.nbatch + KGEM_BATCH_RESERVED <= sna->kgem.surface); 49428d7b3dSmrg return sna->kgem.surface - sna->kgem.nbatch - KGEM_BATCH_RESERVED; 50428d7b3dSmrg} 51428d7b3dSmrg 52428d7b3dSmrgstatic force_inline void batch_emit(struct sna *sna, uint32_t dword) 53428d7b3dSmrg{ 54428d7b3dSmrg assert(sna->kgem.mode != KGEM_NONE); 55428d7b3dSmrg assert(sna->kgem.nbatch + KGEM_BATCH_RESERVED < sna->kgem.surface); 56428d7b3dSmrg sna->kgem.batch[sna->kgem.nbatch++] = dword; 57428d7b3dSmrg} 58428d7b3dSmrg 59428d7b3dSmrgstatic force_inline void batch_emit64(struct sna *sna, uint64_t qword) 60428d7b3dSmrg{ 61428d7b3dSmrg assert(sna->kgem.mode != KGEM_NONE); 62428d7b3dSmrg assert(sna->kgem.nbatch + 2 + KGEM_BATCH_RESERVED < sna->kgem.surface); 63428d7b3dSmrg *(uint64_t *)(sna->kgem.batch+sna->kgem.nbatch) = qword; 64428d7b3dSmrg sna->kgem.nbatch += 2; 65428d7b3dSmrg} 66428d7b3dSmrg 67428d7b3dSmrgstatic force_inline void batch_emit_float(struct sna *sna, float f) 68428d7b3dSmrg{ 69428d7b3dSmrg union { 70428d7b3dSmrg uint32_t dw; 71428d7b3dSmrg float f; 72428d7b3dSmrg } u; 73428d7b3dSmrg u.f = f; 74428d7b3dSmrg batch_emit(sna, u.dw); 75428d7b3dSmrg} 76428d7b3dSmrg 77428d7b3dSmrgstatic inline bool 78428d7b3dSmrgis_gpu(struct sna *sna, DrawablePtr drawable, unsigned prefer) 79428d7b3dSmrg{ 80428d7b3dSmrg struct sna_pixmap *priv = sna_pixmap_from_drawable(drawable); 81428d7b3dSmrg 82428d7b3dSmrg if (priv == NULL || priv->clear || priv->cpu) 83428d7b3dSmrg return false; 84428d7b3dSmrg 85428d7b3dSmrg if (priv->cpu_damage == NULL) 86428d7b3dSmrg return true; 87428d7b3dSmrg 88428d7b3dSmrg if (priv->gpu_damage && !priv->gpu_bo->proxy && 89428d7b3dSmrg (sna->render.prefer_gpu & prefer)) 90428d7b3dSmrg return true; 91428d7b3dSmrg 92428d7b3dSmrg if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) 93428d7b3dSmrg return true; 94428d7b3dSmrg 95428d7b3dSmrg if (DAMAGE_IS_ALL(priv->cpu_damage)) 96428d7b3dSmrg return false; 97428d7b3dSmrg 98428d7b3dSmrg return priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo); 99428d7b3dSmrg} 100428d7b3dSmrg 101428d7b3dSmrgstatic inline bool 102428d7b3dSmrgtoo_small(struct sna_pixmap *priv) 103428d7b3dSmrg{ 104428d7b3dSmrg assert(priv); 105428d7b3dSmrg 106428d7b3dSmrg if (priv->gpu_bo) 107428d7b3dSmrg return false; 108428d7b3dSmrg 109428d7b3dSmrg if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) 110428d7b3dSmrg return false; 111428d7b3dSmrg 112428d7b3dSmrg return (priv->create & KGEM_CAN_CREATE_GPU) == 0; 113428d7b3dSmrg} 114428d7b3dSmrg 115428d7b3dSmrgstatic inline bool 116428d7b3dSmrgcan_render_to_picture(PicturePtr dst) 117428d7b3dSmrg{ 118428d7b3dSmrg if (dst->alphaMap) { 119428d7b3dSmrg DBG(("%s(pixmap=%ld) -- no, has alphamap\n", __FUNCTION__, 120428d7b3dSmrg get_drawable_pixmap(dst->pDrawable)->drawable.serialNumber)); 121428d7b3dSmrg return false; 122428d7b3dSmrg } 123428d7b3dSmrg 124428d7b3dSmrg switch (PICT_FORMAT_TYPE(dst->format)) { 125428d7b3dSmrg case PICT_TYPE_COLOR: 126428d7b3dSmrg case PICT_TYPE_GRAY: 127428d7b3dSmrg case PICT_TYPE_OTHER: 128428d7b3dSmrg DBG(("%s(pixmap=%ld) -- no, has palette\n", __FUNCTION__, 129428d7b3dSmrg get_drawable_pixmap(dst->pDrawable)->drawable.serialNumber)); 130428d7b3dSmrg return false; 131428d7b3dSmrg default: 132428d7b3dSmrg break; 133428d7b3dSmrg } 134428d7b3dSmrg 135428d7b3dSmrg return true; 136428d7b3dSmrg} 137428d7b3dSmrg 138428d7b3dSmrg 139428d7b3dSmrgstatic inline bool 140428d7b3dSmrgis_gpu_dst(struct sna_pixmap *priv) 141428d7b3dSmrg{ 142428d7b3dSmrg assert(priv); 143428d7b3dSmrg 144428d7b3dSmrg if (too_small(priv)) 145428d7b3dSmrg return false; 146428d7b3dSmrg 147428d7b3dSmrg if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo)) 148428d7b3dSmrg return true; 149428d7b3dSmrg 150428d7b3dSmrg if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) 151428d7b3dSmrg return true; 152428d7b3dSmrg 153428d7b3dSmrg if (DAMAGE_IS_ALL(priv->cpu_damage)) 154428d7b3dSmrg return false; 155428d7b3dSmrg 156428d7b3dSmrg return priv->gpu_damage != NULL || !priv->cpu; 157428d7b3dSmrg} 158428d7b3dSmrg 159428d7b3dSmrgstatic inline bool 160428d7b3dSmrgunattached(DrawablePtr drawable) 161428d7b3dSmrg{ 162428d7b3dSmrg struct sna_pixmap *priv = sna_pixmap_from_drawable(drawable); 163428d7b3dSmrg return priv == NULL || (priv->gpu_damage == NULL && priv->cpu_damage && !priv->cpu_bo); 164428d7b3dSmrg} 165428d7b3dSmrg 166428d7b3dSmrgstatic inline bool 167428d7b3dSmrgpicture_is_gpu(struct sna *sna, PicturePtr picture, unsigned flags) 168428d7b3dSmrg{ 169428d7b3dSmrg if (!picture) 170428d7b3dSmrg return false; 171428d7b3dSmrg 172428d7b3dSmrg if (!picture->pDrawable) { 173428d7b3dSmrg switch (flags) { 174428d7b3dSmrg case PREFER_GPU_RENDER: 175428d7b3dSmrg switch (picture->pSourcePict->type) { 176428d7b3dSmrg case SourcePictTypeSolidFill: 177428d7b3dSmrg case SourcePictTypeLinear: 178428d7b3dSmrg return false; 179428d7b3dSmrg default: 180428d7b3dSmrg return true; 181428d7b3dSmrg } 182428d7b3dSmrg case PREFER_GPU_SPANS: 183428d7b3dSmrg return true; 184428d7b3dSmrg default: 185428d7b3dSmrg return false; 186428d7b3dSmrg } 187428d7b3dSmrg } else { 188428d7b3dSmrg if (picture->repeat && 189428d7b3dSmrg (picture->pDrawable->width | picture->pDrawable->height) == 1) 190428d7b3dSmrg return flags == PREFER_GPU_SPANS; 191428d7b3dSmrg } 192428d7b3dSmrg 193428d7b3dSmrg return is_gpu(sna, picture->pDrawable, flags); 194428d7b3dSmrg} 195428d7b3dSmrg 196428d7b3dSmrgstatic inline bool 197428d7b3dSmrgpicture_is_cpu(struct sna *sna, PicturePtr picture) 198428d7b3dSmrg{ 199428d7b3dSmrg if (!picture->pDrawable) 200428d7b3dSmrg return false; 201428d7b3dSmrg 202428d7b3dSmrg return !is_gpu(sna, picture->pDrawable, PREFER_GPU_RENDER); 203428d7b3dSmrg} 204428d7b3dSmrg 205428d7b3dSmrgstatic inline bool sna_blt_compare_depth(const DrawableRec *src, const DrawableRec *dst) 206428d7b3dSmrg{ 207428d7b3dSmrg if (src->depth == dst->depth) 208428d7b3dSmrg return true; 209428d7b3dSmrg 210428d7b3dSmrg /* Also allow for the alpha to be discarded on a copy */ 211428d7b3dSmrg if (src->bitsPerPixel != dst->bitsPerPixel) 212428d7b3dSmrg return false; 213428d7b3dSmrg 214428d7b3dSmrg if (dst->depth == 24 && src->depth == 32) 215428d7b3dSmrg return true; 216428d7b3dSmrg 217428d7b3dSmrg /* Note that a depth-16 pixmap is r5g6b5, not x1r5g5b5. */ 218428d7b3dSmrg 219428d7b3dSmrg return false; 220428d7b3dSmrg} 221428d7b3dSmrg 222428d7b3dSmrgstatic inline struct kgem_bo * 223428d7b3dSmrgsna_render_get_alpha_gradient(struct sna *sna) 224428d7b3dSmrg{ 225428d7b3dSmrg return kgem_bo_reference(sna->render.alpha_cache.cache_bo); 226428d7b3dSmrg} 227428d7b3dSmrg 228428d7b3dSmrgstatic inline void 229428d7b3dSmrgsna_render_picture_extents(PicturePtr p, BoxRec *box) 230428d7b3dSmrg{ 231428d7b3dSmrg box->x1 = p->pDrawable->x; 232428d7b3dSmrg box->y1 = p->pDrawable->y; 233428d7b3dSmrg box->x2 = bound(box->x1, p->pDrawable->width); 234428d7b3dSmrg box->y2 = bound(box->y1, p->pDrawable->height); 235428d7b3dSmrg 236428d7b3dSmrg if (box->x1 < p->pCompositeClip->extents.x1) 237428d7b3dSmrg box->x1 = p->pCompositeClip->extents.x1; 238428d7b3dSmrg if (box->y1 < p->pCompositeClip->extents.y1) 239428d7b3dSmrg box->y1 = p->pCompositeClip->extents.y1; 240428d7b3dSmrg 241428d7b3dSmrg if (box->x2 > p->pCompositeClip->extents.x2) 242428d7b3dSmrg box->x2 = p->pCompositeClip->extents.x2; 243428d7b3dSmrg if (box->y2 > p->pCompositeClip->extents.y2) 244428d7b3dSmrg box->y2 = p->pCompositeClip->extents.y2; 245428d7b3dSmrg 246428d7b3dSmrg assert(box->x2 > box->x1 && box->y2 > box->y1); 247428d7b3dSmrg} 248428d7b3dSmrg 249428d7b3dSmrgstatic inline void 250428d7b3dSmrgsna_render_reduce_damage(struct sna_composite_op *op, 251428d7b3dSmrg int dst_x, int dst_y, 252428d7b3dSmrg int width, int height) 253428d7b3dSmrg{ 254428d7b3dSmrg BoxRec r; 255428d7b3dSmrg 256428d7b3dSmrg if (op->damage == NULL || *op->damage == NULL) 257428d7b3dSmrg return; 258428d7b3dSmrg 259428d7b3dSmrg if (DAMAGE_IS_ALL(*op->damage)) { 260428d7b3dSmrg DBG(("%s: damage-all, dicarding damage\n", 261428d7b3dSmrg __FUNCTION__)); 262428d7b3dSmrg op->damage = NULL; 263428d7b3dSmrg return; 264428d7b3dSmrg } 265428d7b3dSmrg 266428d7b3dSmrg if (width == 0 || height == 0) 267428d7b3dSmrg return; 268428d7b3dSmrg 269428d7b3dSmrg r.x1 = dst_x + op->dst.x; 270428d7b3dSmrg r.x2 = r.x1 + width; 271428d7b3dSmrg 272428d7b3dSmrg r.y1 = dst_y + op->dst.y; 273428d7b3dSmrg r.y2 = r.y1 + height; 274428d7b3dSmrg 275428d7b3dSmrg if (sna_damage_contains_box__no_reduce(*op->damage, &r)) { 276428d7b3dSmrg DBG(("%s: damage contains render extents, dicarding damage\n", 277428d7b3dSmrg __FUNCTION__)); 278428d7b3dSmrg op->damage = NULL; 279428d7b3dSmrg } 280428d7b3dSmrg} 281428d7b3dSmrg 282428d7b3dSmrginline static uint32_t 283428d7b3dSmrgcolor_convert(uint32_t pixel, 284428d7b3dSmrg uint32_t src_format, 285428d7b3dSmrg uint32_t dst_format) 286428d7b3dSmrg{ 287428d7b3dSmrg DBG(("%s: src=%08x [%08x]\n", __FUNCTION__, pixel, src_format)); 288428d7b3dSmrg 289428d7b3dSmrg if (src_format != dst_format) { 290428d7b3dSmrg uint16_t red, green, blue, alpha; 291428d7b3dSmrg 292428d7b3dSmrg if (!sna_get_rgba_from_pixel(pixel, 293428d7b3dSmrg &red, &green, &blue, &alpha, 294428d7b3dSmrg src_format)) 295428d7b3dSmrg return 0; 296428d7b3dSmrg 297428d7b3dSmrg if (!sna_get_pixel_from_rgba(&pixel, 298428d7b3dSmrg red, green, blue, alpha, 299428d7b3dSmrg dst_format)) 300428d7b3dSmrg return 0; 301428d7b3dSmrg } 302428d7b3dSmrg 303428d7b3dSmrg DBG(("%s: dst=%08x [%08x]\n", __FUNCTION__, pixel, dst_format)); 304428d7b3dSmrg return pixel; 305428d7b3dSmrg} 306428d7b3dSmrg 307428d7b3dSmrginline static bool dst_use_gpu(PixmapPtr pixmap) 308428d7b3dSmrg{ 309428d7b3dSmrg struct sna_pixmap *priv = sna_pixmap(pixmap); 310428d7b3dSmrg if (priv == NULL) 311428d7b3dSmrg return false; 312428d7b3dSmrg 313428d7b3dSmrg if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)) 314428d7b3dSmrg return true; 315428d7b3dSmrg 316428d7b3dSmrg if (priv->clear) 317428d7b3dSmrg return false; 318428d7b3dSmrg 319428d7b3dSmrg if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo)) 320428d7b3dSmrg return true; 321428d7b3dSmrg 322428d7b3dSmrg return priv->gpu_damage && (!priv->cpu || !priv->cpu_damage); 323428d7b3dSmrg} 324428d7b3dSmrg 325428d7b3dSmrginline static bool dst_use_cpu(PixmapPtr pixmap) 326428d7b3dSmrg{ 327428d7b3dSmrg struct sna_pixmap *priv = sna_pixmap(pixmap); 328428d7b3dSmrg if (priv == NULL || priv->shm) 329428d7b3dSmrg return true; 330428d7b3dSmrg 331428d7b3dSmrg return priv->cpu_damage && priv->cpu; 332428d7b3dSmrg} 333428d7b3dSmrg 334428d7b3dSmrginline static bool dst_is_cpu(PixmapPtr pixmap) 335428d7b3dSmrg{ 336428d7b3dSmrg struct sna_pixmap *priv = sna_pixmap(pixmap); 337428d7b3dSmrg return priv == NULL || DAMAGE_IS_ALL(priv->cpu_damage); 338428d7b3dSmrg} 339428d7b3dSmrg 340428d7b3dSmrginline static bool 341428d7b3dSmrguntransformed(PicturePtr p) 342428d7b3dSmrg{ 343428d7b3dSmrg return !p->transform || pixman_transform_is_int_translate(p->transform); 344428d7b3dSmrg} 345428d7b3dSmrg 346428d7b3dSmrginline static void 347428d7b3dSmrgboxes_extents(const BoxRec *box, int n, BoxRec *extents) 348428d7b3dSmrg{ 349428d7b3dSmrg *extents = box[0]; 350428d7b3dSmrg while (--n) { 351428d7b3dSmrg box++; 352428d7b3dSmrg 353428d7b3dSmrg if (box->x1 < extents->x1) 354428d7b3dSmrg extents->x1 = box->x1; 355428d7b3dSmrg if (box->x2 > extents->x2) 356428d7b3dSmrg extents->x2 = box->x2; 357428d7b3dSmrg 358428d7b3dSmrg if (box->y1 < extents->y1) 359428d7b3dSmrg extents->y1 = box->y1; 360428d7b3dSmrg if (box->y2 > extents->y2) 361428d7b3dSmrg extents->y2 = box->y2; 362428d7b3dSmrg } 363428d7b3dSmrg} 364428d7b3dSmrg 365428d7b3dSmrginline static bool 366428d7b3dSmrgoverlaps(struct sna *sna, 367428d7b3dSmrg struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy, 368428d7b3dSmrg struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy, 369428d7b3dSmrg const BoxRec *box, int n, unsigned flags, 370428d7b3dSmrg BoxRec *extents) 371428d7b3dSmrg{ 372428d7b3dSmrg if (src_bo != dst_bo) 373428d7b3dSmrg return false; 374428d7b3dSmrg 375428d7b3dSmrg if (flags & COPY_NO_OVERLAP) 376428d7b3dSmrg return false; 377428d7b3dSmrg 378428d7b3dSmrg boxes_extents(box, n, extents); 379428d7b3dSmrg return (extents->x2 + src_dx > extents->x1 + dst_dx && 380428d7b3dSmrg extents->x1 + src_dx < extents->x2 + dst_dx && 381428d7b3dSmrg extents->y2 + src_dy > extents->y1 + dst_dy && 382428d7b3dSmrg extents->y1 + src_dy < extents->y2 + dst_dy); 383428d7b3dSmrg} 384428d7b3dSmrg 385428d7b3dSmrgstatic inline long get_picture_id(PicturePtr picture) 386428d7b3dSmrg{ 387428d7b3dSmrg return picture && picture->pDrawable ? get_drawable_pixmap(picture->pDrawable)->drawable.serialNumber : 0; 388428d7b3dSmrg} 389428d7b3dSmrg 390428d7b3dSmrg#endif /* SNA_RENDER_INLINE_H */ 391