xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

fbpict.c (14434B)


      1 /*
      2  *
      3  * Copyright © 2000 SuSE, Inc.
      4  * Copyright © 2007 Red Hat, Inc.
      5  *
      6  * Permission to use, copy, modify, distribute, and sell this software and its
      7  * documentation for any purpose is hereby granted without fee, provided that
      8  * the above copyright notice appear in all copies and that both that
      9  * copyright notice and this permission notice appear in supporting
     10  * documentation, and that the name of SuSE not be used in advertising or
     11  * publicity pertaining to distribution of the software without specific,
     12  * written prior permission.  SuSE makes no representations about the
     13  * suitability of this software for any purpose.  It is provided "as is"
     14  * without express or implied warranty.
     15  *
     16  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
     18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     22  *
     23  * Author:  Keith Packard, SuSE, Inc.
     24  */
     25 
     26 #ifdef HAVE_DIX_CONFIG_H
     27 #include <dix-config.h>
     28 #endif
     29 
     30 #include <string.h>
     31 
     32 #include "fb.h"
     33 
     34 #include "picturestr.h"
     35 #include "mipict.h"
     36 #include "fbpict.h"
     37 
     38 void
     39 fbComposite(CARD8 op,
     40             PicturePtr pSrc,
     41             PicturePtr pMask,
     42             PicturePtr pDst,
     43             INT16 xSrc,
     44             INT16 ySrc,
     45             INT16 xMask,
     46             INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
     47 {
     48     pixman_image_t *src, *mask, *dest;
     49     int src_xoff, src_yoff;
     50     int msk_xoff, msk_yoff;
     51     int dst_xoff, dst_yoff;
     52 
     53     miCompositeSourceValidate(pSrc);
     54     if (pMask)
     55         miCompositeSourceValidate(pMask);
     56 
     57     src = image_from_pict(pSrc, FALSE, &src_xoff, &src_yoff);
     58     mask = image_from_pict(pMask, FALSE, &msk_xoff, &msk_yoff);
     59     dest = image_from_pict(pDst, TRUE, &dst_xoff, &dst_yoff);
     60 
     61     if (src && dest && !(pMask && !mask)) {
     62         pixman_image_composite(op, src, mask, dest,
     63                                xSrc + src_xoff, ySrc + src_yoff,
     64                                xMask + msk_xoff, yMask + msk_yoff,
     65                                xDst + dst_xoff, yDst + dst_yoff, width, height);
     66     }
     67 
     68     free_pixman_pict(pSrc, src);
     69     free_pixman_pict(pMask, mask);
     70     free_pixman_pict(pDst, dest);
     71 }
     72 
     73 static pixman_glyph_cache_t *glyphCache;
     74 
     75 void
     76 fbDestroyGlyphCache(void)
     77 {
     78     if (glyphCache)
     79     {
     80 	pixman_glyph_cache_destroy (glyphCache);
     81 	glyphCache = NULL;
     82     }
     83 }
     84 
     85 static void
     86 fbUnrealizeGlyph(ScreenPtr pScreen,
     87 		 GlyphPtr pGlyph)
     88 {
     89     if (glyphCache)
     90 	pixman_glyph_cache_remove (glyphCache, pGlyph, NULL);
     91 }
     92 
     93 void
     94 fbGlyphs(CARD8 op,
     95 	 PicturePtr pSrc,
     96 	 PicturePtr pDst,
     97 	 PictFormatPtr maskFormat,
     98 	 INT16 xSrc,
     99 	 INT16 ySrc, int nlist,
    100 	 GlyphListPtr list,
    101 	 GlyphPtr *glyphs)
    102 {
    103 #define N_STACK_GLYPHS 512
    104     ScreenPtr pScreen = pDst->pDrawable->pScreen;
    105     pixman_glyph_t stack_glyphs[N_STACK_GLYPHS];
    106     pixman_glyph_t *pglyphs = stack_glyphs;
    107     pixman_image_t *srcImage, *dstImage;
    108     int srcXoff, srcYoff, dstXoff, dstYoff;
    109     GlyphPtr glyph;
    110     int n_glyphs;
    111     int x, y;
    112     int i, n;
    113     int xDst = list->xOff, yDst = list->yOff;
    114 
    115     miCompositeSourceValidate(pSrc);
    116 
    117     n_glyphs = 0;
    118     for (i = 0; i < nlist; ++i)
    119 	n_glyphs += list[i].len;
    120 
    121     if (!glyphCache)
    122 	glyphCache = pixman_glyph_cache_create();
    123 
    124     pixman_glyph_cache_freeze (glyphCache);
    125 
    126     if (n_glyphs > N_STACK_GLYPHS) {
    127 	if (!(pglyphs = xallocarray(n_glyphs, sizeof(pixman_glyph_t))))
    128 	    goto out;
    129     }
    130 
    131     i = 0;
    132     x = y = 0;
    133     while (nlist--) {
    134         x += list->xOff;
    135         y += list->yOff;
    136         n = list->len;
    137         while (n--) {
    138 	    const void *g;
    139 
    140             glyph = *glyphs++;
    141 
    142 	    if (!(g = pixman_glyph_cache_lookup (glyphCache, glyph, NULL))) {
    143 		pixman_image_t *glyphImage;
    144 		PicturePtr pPicture;
    145 		int xoff, yoff;
    146 
    147 		pPicture = GetGlyphPicture(glyph, pScreen);
    148 		if (!pPicture) {
    149 		    n_glyphs--;
    150 		    goto next;
    151 		}
    152 
    153 		if (!(glyphImage = image_from_pict(pPicture, FALSE, &xoff, &yoff)))
    154 		    goto out;
    155 
    156 		g = pixman_glyph_cache_insert(glyphCache, glyph, NULL,
    157 					      glyph->info.x,
    158 					      glyph->info.y,
    159 					      glyphImage);
    160 
    161 		free_pixman_pict(pPicture, glyphImage);
    162 
    163 		if (!g)
    164 		    goto out;
    165 	    }
    166 
    167 	    pglyphs[i].x = x;
    168 	    pglyphs[i].y = y;
    169 	    pglyphs[i].glyph = g;
    170 	    i++;
    171 
    172 	next:
    173             x += glyph->info.xOff;
    174             y += glyph->info.yOff;
    175 	}
    176 	list++;
    177     }
    178 
    179     if (!(srcImage = image_from_pict(pSrc, FALSE, &srcXoff, &srcYoff)))
    180 	goto out;
    181 
    182     if (!(dstImage = image_from_pict(pDst, TRUE, &dstXoff, &dstYoff)))
    183 	goto out_free_src;
    184 
    185     if (maskFormat) {
    186 	pixman_format_code_t format;
    187 	pixman_box32_t extents;
    188 
    189 	format = maskFormat->format | (maskFormat->depth << 24);
    190 
    191 	pixman_glyph_get_extents(glyphCache, n_glyphs, pglyphs, &extents);
    192 
    193 	pixman_composite_glyphs(op, srcImage, dstImage, format,
    194 				xSrc + srcXoff + extents.x1 - xDst, ySrc + srcYoff + extents.y1 - yDst,
    195 				extents.x1, extents.y1,
    196 				extents.x1 + dstXoff, extents.y1 + dstYoff,
    197 				extents.x2 - extents.x1,
    198 				extents.y2 - extents.y1,
    199 				glyphCache, n_glyphs, pglyphs);
    200     }
    201     else {
    202 	pixman_composite_glyphs_no_mask(op, srcImage, dstImage,
    203 					xSrc + srcXoff - xDst, ySrc + srcYoff - yDst,
    204 					dstXoff, dstYoff,
    205 					glyphCache, n_glyphs, pglyphs);
    206     }
    207 
    208     free_pixman_pict(pDst, dstImage);
    209 
    210 out_free_src:
    211     free_pixman_pict(pSrc, srcImage);
    212 
    213 out:
    214     pixman_glyph_cache_thaw(glyphCache);
    215     if (pglyphs != stack_glyphs)
    216 	free(pglyphs);
    217 }
    218 
    219 static pixman_image_t *
    220 create_solid_fill_image(PicturePtr pict)
    221 {
    222     PictSolidFill *solid = &pict->pSourcePict->solidFill;
    223     /* pixman_color_t and xRenderColor have the same layout */
    224     pixman_color_t *color = (pixman_color_t *)&solid->fullcolor;
    225 
    226     return pixman_image_create_solid_fill(color);
    227 }
    228 
    229 static pixman_image_t *
    230 create_linear_gradient_image(PictGradient * gradient)
    231 {
    232     PictLinearGradient *linear = (PictLinearGradient *) gradient;
    233     pixman_point_fixed_t p1;
    234     pixman_point_fixed_t p2;
    235 
    236     p1.x = linear->p1.x;
    237     p1.y = linear->p1.y;
    238     p2.x = linear->p2.x;
    239     p2.y = linear->p2.y;
    240 
    241     return pixman_image_create_linear_gradient(&p1, &p2,
    242                                                (pixman_gradient_stop_t *)
    243                                                gradient->stops,
    244                                                gradient->nstops);
    245 }
    246 
    247 static pixman_image_t *
    248 create_radial_gradient_image(PictGradient * gradient)
    249 {
    250     PictRadialGradient *radial = (PictRadialGradient *) gradient;
    251     pixman_point_fixed_t c1;
    252     pixman_point_fixed_t c2;
    253 
    254     c1.x = radial->c1.x;
    255     c1.y = radial->c1.y;
    256     c2.x = radial->c2.x;
    257     c2.y = radial->c2.y;
    258 
    259     return pixman_image_create_radial_gradient(&c1, &c2, radial->c1.radius,
    260                                                radial->c2.radius,
    261                                                (pixman_gradient_stop_t *)
    262                                                gradient->stops,
    263                                                gradient->nstops);
    264 }
    265 
    266 static pixman_image_t *
    267 create_conical_gradient_image(PictGradient * gradient)
    268 {
    269     PictConicalGradient *conical = (PictConicalGradient *) gradient;
    270     pixman_point_fixed_t center;
    271 
    272     center.x = conical->center.x;
    273     center.y = conical->center.y;
    274 
    275     return pixman_image_create_conical_gradient(&center, conical->angle,
    276                                                 (pixman_gradient_stop_t *)
    277                                                 gradient->stops,
    278                                                 gradient->nstops);
    279 }
    280 
    281 static pixman_image_t *
    282 create_bits_picture(PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
    283 {
    284     PixmapPtr pixmap;
    285     FbBits *bits;
    286     FbStride stride;
    287     int bpp;
    288     pixman_image_t *image;
    289 
    290     fbGetDrawablePixmap(pict->pDrawable, pixmap, *xoff, *yoff);
    291     fbGetPixmapBitsData(pixmap, bits, stride, bpp);
    292 
    293     image = pixman_image_create_bits((pixman_format_code_t) pict->format,
    294                                      pixmap->drawable.width,
    295                                      pixmap->drawable.height, (uint32_t *) bits,
    296                                      stride * sizeof(FbStride));
    297 
    298     if (!image)
    299         return NULL;
    300 
    301 #ifdef FB_ACCESS_WRAPPER
    302     pixman_image_set_accessors(image,
    303                                (pixman_read_memory_func_t) wfbReadMemory,
    304                                (pixman_write_memory_func_t) wfbWriteMemory);
    305 #endif
    306 
    307     /* pCompositeClip is undefined for source pictures, so
    308      * only set the clip region for pictures with drawables
    309      */
    310     if (has_clip) {
    311         if (pict->clientClip)
    312             pixman_image_set_has_client_clip(image, TRUE);
    313 
    314         if (*xoff || *yoff)
    315             pixman_region_translate(pict->pCompositeClip, *xoff, *yoff);
    316 
    317         pixman_image_set_clip_region(image, pict->pCompositeClip);
    318 
    319         if (*xoff || *yoff)
    320             pixman_region_translate(pict->pCompositeClip, -*xoff, -*yoff);
    321     }
    322 
    323     /* Indexed table */
    324     if (pict->pFormat->index.devPrivate)
    325         pixman_image_set_indexed(image, pict->pFormat->index.devPrivate);
    326 
    327     /* Add in drawable origin to position within the image */
    328     *xoff += pict->pDrawable->x;
    329     *yoff += pict->pDrawable->y;
    330 
    331     return image;
    332 }
    333 
    334 static pixman_image_t *image_from_pict_internal(PicturePtr pict, Bool has_clip,
    335                                                 int *xoff, int *yoff,
    336                                                 Bool is_alpha_map);
    337 
    338 static void image_destroy(pixman_image_t *image, void *data)
    339 {
    340     fbFinishAccess((DrawablePtr)data);
    341 }
    342 
    343 static void
    344 set_image_properties(pixman_image_t * image, PicturePtr pict, Bool has_clip,
    345                      int *xoff, int *yoff, Bool is_alpha_map)
    346 {
    347     pixman_repeat_t repeat;
    348     pixman_filter_t filter;
    349 
    350     if (pict->transform) {
    351         /* For source images, adjust the transform to account
    352          * for the drawable offset within the pixman image,
    353          * then set the offset to 0 as it will be used
    354          * to compute positions within the transformed image.
    355          */
    356         if (!has_clip) {
    357             struct pixman_transform adjusted;
    358 
    359             adjusted = *pict->transform;
    360             pixman_transform_translate(&adjusted,
    361                                        NULL,
    362                                        pixman_int_to_fixed(*xoff),
    363                                        pixman_int_to_fixed(*yoff));
    364             pixman_image_set_transform(image, &adjusted);
    365             *xoff = 0;
    366             *yoff = 0;
    367         }
    368         else
    369             pixman_image_set_transform(image, pict->transform);
    370     }
    371 
    372     switch (pict->repeatType) {
    373     default:
    374     case RepeatNone:
    375         repeat = PIXMAN_REPEAT_NONE;
    376         break;
    377 
    378     case RepeatPad:
    379         repeat = PIXMAN_REPEAT_PAD;
    380         break;
    381 
    382     case RepeatNormal:
    383         repeat = PIXMAN_REPEAT_NORMAL;
    384         break;
    385 
    386     case RepeatReflect:
    387         repeat = PIXMAN_REPEAT_REFLECT;
    388         break;
    389     }
    390 
    391     pixman_image_set_repeat(image, repeat);
    392 
    393     /* Fetch alpha map unless 'pict' is being used
    394      * as the alpha map for this operation
    395      */
    396     if (pict->alphaMap && !is_alpha_map) {
    397         int alpha_xoff, alpha_yoff;
    398         pixman_image_t *alpha_map =
    399             image_from_pict_internal(pict->alphaMap, FALSE, &alpha_xoff,
    400                                      &alpha_yoff, TRUE);
    401 
    402         pixman_image_set_alpha_map(image, alpha_map, pict->alphaOrigin.x,
    403                                    pict->alphaOrigin.y);
    404 
    405         free_pixman_pict(pict->alphaMap, alpha_map);
    406     }
    407 
    408     pixman_image_set_component_alpha(image, pict->componentAlpha);
    409 
    410     switch (pict->filter) {
    411     default:
    412     case PictFilterNearest:
    413     case PictFilterFast:
    414         filter = PIXMAN_FILTER_NEAREST;
    415         break;
    416 
    417     case PictFilterBilinear:
    418     case PictFilterGood:
    419         filter = PIXMAN_FILTER_BILINEAR;
    420         break;
    421 
    422     case PictFilterConvolution:
    423         filter = PIXMAN_FILTER_CONVOLUTION;
    424         break;
    425     }
    426 
    427     if (pict->pDrawable)
    428         pixman_image_set_destroy_function(image, &image_destroy,
    429                                           pict->pDrawable);
    430 
    431     pixman_image_set_filter(image, filter,
    432                             (pixman_fixed_t *) pict->filter_params,
    433                             pict->filter_nparams);
    434     pixman_image_set_source_clipping(image, TRUE);
    435 }
    436 
    437 static pixman_image_t *
    438 image_from_pict_internal(PicturePtr pict, Bool has_clip, int *xoff, int *yoff,
    439                          Bool is_alpha_map)
    440 {
    441     pixman_image_t *image = NULL;
    442 
    443     if (!pict)
    444         return NULL;
    445 
    446     if (pict->pDrawable) {
    447         image = create_bits_picture(pict, has_clip, xoff, yoff);
    448     }
    449     else if (pict->pSourcePict) {
    450         SourcePict *sp = pict->pSourcePict;
    451 
    452         if (sp->type == SourcePictTypeSolidFill) {
    453             image = create_solid_fill_image(pict);
    454         }
    455         else {
    456             PictGradient *gradient = &pict->pSourcePict->gradient;
    457 
    458             if (sp->type == SourcePictTypeLinear)
    459                 image = create_linear_gradient_image(gradient);
    460             else if (sp->type == SourcePictTypeRadial)
    461                 image = create_radial_gradient_image(gradient);
    462             else if (sp->type == SourcePictTypeConical)
    463                 image = create_conical_gradient_image(gradient);
    464         }
    465         *xoff = *yoff = 0;
    466     }
    467 
    468     if (image)
    469         set_image_properties(image, pict, has_clip, xoff, yoff, is_alpha_map);
    470 
    471     return image;
    472 }
    473 
    474 pixman_image_t *
    475 image_from_pict(PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
    476 {
    477     return image_from_pict_internal(pict, has_clip, xoff, yoff, FALSE);
    478 }
    479 
    480 void
    481 free_pixman_pict(PicturePtr pict, pixman_image_t * image)
    482 {
    483     if (image)
    484         pixman_image_unref(image);
    485 }
    486 
    487 Bool
    488 fbPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
    489 {
    490 
    491     PictureScreenPtr ps;
    492 
    493     if (!miPictureInit(pScreen, formats, nformats))
    494         return FALSE;
    495     ps = GetPictureScreen(pScreen);
    496     ps->Composite = fbComposite;
    497     ps->Glyphs = fbGlyphs;
    498     ps->UnrealizeGlyph = fbUnrealizeGlyph;
    499     ps->CompositeRects = miCompositeRects;
    500     ps->RasterizeTrapezoid = fbRasterizeTrapezoid;
    501     ps->Trapezoids = fbTrapezoids;
    502     ps->AddTraps = fbAddTraps;
    503     ps->AddTriangles = fbAddTriangles;
    504     ps->Triangles = fbTriangles;
    505 
    506     return TRUE;
    507 }