/* * Initialize one edge structure given a line, starting y value * and a pixel offset for the line */ void RenderLineFixedEdgeInit (RenderEdge *e, int n, xFixed y, xLineFixed *line, int x_off, int y_off) { xFixed x_off_fixed = IntToxFixed(x_off); xFixed y_off_fixed = IntToxFixed(y_off); xPointFixed *top, *bot; if (line->p1.y <= line->p2.y) { top = &line->p1; bot = &line->p2; } else { top = &line->p2; bot = &line->p1; } RenderEdgeInit (e, n, y, top->x + x_off_fixed, top->y + y_off_fixed, bot->x + x_off_fixed, bot->y + y_off_fixed); }
bool sna_transform_is_integer_translation(const PictTransform *t, int16_t *tx, int16_t *ty) { if (t == NULL) { *tx = *ty = 0; return true; } if (t->matrix[0][0] != IntToxFixed(1) || t->matrix[0][1] != 0 || t->matrix[1][0] != 0 || t->matrix[1][1] != IntToxFixed(1) || t->matrix[2][0] != 0 || t->matrix[2][1] != 0 || t->matrix[2][2] != IntToxFixed(1)) return false; if (pixman_fixed_fraction(t->matrix[0][2]) || pixman_fixed_fraction(t->matrix[1][2])) return false; *tx = pixman_fixed_to_int(t->matrix[0][2]); *ty = pixman_fixed_to_int(t->matrix[1][2]); return true; }
bool sna_transform_is_imprecise_integer_translation(const PictTransform *t, int filter, bool precise, int16_t *tx, int16_t *ty) { if (t == NULL) { DBG(("%s: no transform\n", __FUNCTION__)); *tx = *ty = 0; return true; } DBG(("%s: FilterNearest?=%d, precise?=%d, transform=[%f %f %f, %f %f %f, %f %f %f]\n", __FUNCTION__, filter==PictFilterNearest, precise, t->matrix[0][0]/65536., t->matrix[0][1]/65536., t->matrix[0][2]/65536., t->matrix[1][0]/65536., t->matrix[1][1]/65536., t->matrix[1][2]/65536., t->matrix[2][0]/65536., t->matrix[2][1]/65536., t->matrix[2][2]/65536.)); if (t->matrix[0][0] != IntToxFixed(1) || t->matrix[0][1] != 0 || t->matrix[1][0] != 0 || t->matrix[1][1] != IntToxFixed(1) || t->matrix[2][0] != 0 || t->matrix[2][1] != 0 || t->matrix[2][2] != IntToxFixed(1)) { DBG(("%s: not unity scaling\n", __FUNCTION__)); return false; } if (filter != PictFilterNearest) { if (precise) { if (pixman_fixed_fraction(t->matrix[0][2]) || pixman_fixed_fraction(t->matrix[1][2])) { DBG(("%s: precise, fractional translation\n", __FUNCTION__)); return false; } } else { int f; f = pixman_fixed_fraction(t->matrix[0][2]); if (f > IntToxFixed(1)/4 && f < IntToxFixed(3)/4) { DBG(("%s: imprecise, fractional translation X: %x\n", __FUNCTION__, f)); return false; } f = pixman_fixed_fraction(t->matrix[1][2]); if (f > IntToxFixed(1)/4 && f < IntToxFixed(3)/4) { DBG(("%s: imprecise, fractional translation Y: %x\n", __FUNCTION__, f)); return false; } } } *tx = pixman_fixed_to_int(t->matrix[0][2] + IntToxFixed(1)/2); *ty = pixman_fixed_to_int(t->matrix[1][2] + IntToxFixed(1)/2); return true; }
void fbRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap, int x_off, int y_off) { FbBits *buf; int bpp; int width; int stride; int height; int pxoff, pyoff; xFixed x_off_fixed; xFixed y_off_fixed; RenderEdge l, r; xFixed t, b; if (!xTrapezoidValid (trap)) return; fbGetDrawable (pPicture->pDrawable, buf, stride, bpp, pxoff, pyoff); width = pPicture->pDrawable->width; height = pPicture->pDrawable->height; x_off += pxoff; y_off += pyoff; x_off_fixed = IntToxFixed(x_off); y_off_fixed = IntToxFixed(y_off); t = trap->top + y_off_fixed; if (t < 0) t = 0; t = RenderSampleCeilY (t, bpp); b = trap->bottom + y_off_fixed; if (xFixedToInt (b) >= height) b = IntToxFixed (height) - 1; b = RenderSampleFloorY (b, bpp); if (b >= t) { /* initialize edge walkers */ RenderLineFixedEdgeInit (&l, bpp, t, &trap->left, x_off, y_off); RenderLineFixedEdgeInit (&r, bpp, t, &trap->right, x_off, y_off); fbRasterizeEdges (buf, bpp, width, stride, &l, &r, t, b); } }
static inline void NV40EXATransformCoord(PictTransformPtr t, int x, int y, float sx, float sy, float *x_ret, float *y_ret) { if (t) { PictVector v; v.vector[0] = IntToxFixed(x); v.vector[1] = IntToxFixed(y); v.vector[2] = xFixed1; PictureTransformPoint(t, &v); *x_ret = xFixedToFloat(v.vector[0]) / sx; *y_ret = xFixedToFloat(v.vector[1]) / sy; } else { *x_ret = (float)x / sx; *y_ret = (float)y / sy; } }
bool sna_transform_is_translation(const PictTransform *t, pixman_fixed_t *tx, pixman_fixed_t *ty) { if (t == NULL) { *tx = *ty = 0; return true; } if (t->matrix[0][0] != IntToxFixed(1) || t->matrix[0][1] != 0 || t->matrix[1][0] != 0 || t->matrix[1][1] != IntToxFixed(1) || t->matrix[2][0] != 0 || t->matrix[2][1] != 0 || t->matrix[2][2] != IntToxFixed(1)) return false; *tx = t->matrix[0][2]; *ty = t->matrix[1][2]; return true; }
void fbAddTraps (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntrap, xTrap *traps) { FbBits *buf; int bpp; int width; int stride; int height; int pxoff, pyoff; xFixed x_off_fixed; xFixed y_off_fixed; RenderEdge l, r; xFixed t, b; fbGetDrawable (pPicture->pDrawable, buf, stride, bpp, pxoff, pyoff); width = pPicture->pDrawable->width; height = pPicture->pDrawable->height; x_off += pxoff; y_off += pyoff; x_off_fixed = IntToxFixed(y_off); y_off_fixed = IntToxFixed(y_off); while (ntrap--) { t = traps->top.y + y_off_fixed; if (t < 0) t = 0; t = RenderSampleCeilY (t, bpp); b = traps->bot.y + y_off_fixed; if (xFixedToInt (b) >= height) b = IntToxFixed (height) - 1; b = RenderSampleFloorY (b, bpp); if (b >= t) { /* initialize edge walkers */ RenderEdgeInit (&l, bpp, t, traps->top.l + x_off_fixed, traps->top.y + y_off_fixed, traps->bot.l + x_off_fixed, traps->bot.y + y_off_fixed); RenderEdgeInit (&r, bpp, t, traps->top.r + x_off_fixed, traps->top.y + y_off_fixed, traps->bot.r + x_off_fixed, traps->bot.y + y_off_fixed); fbRasterizeEdges (buf, bpp, width, stride, &l, &r, t, b); } traps++; } }
/* * We want to detect the case where we add the same value to a long * span of pixels. The triangles on the end are filled in while we * count how many sub-pixel scanlines contribute to the middle section. * * +--------------------------+ * fill_height =| \ / * +------------------+ * |================| * fill_start fill_end */ static void fbRasterizeEdges8 (FbBits *buf, int width, int stride, RenderEdge *l, RenderEdge *r, xFixed t, xFixed b) { xFixed y = t; FbBits *line; int fill_start = -1, fill_end = -1; int fill_size = 0; line = buf + xFixedToInt (y) * stride; for (;;) { CARD8 *ap = (CARD8 *) line; xFixed lx, rx; int lxi, rxi; /* clip X */ lx = l->x; if (lx < 0) lx = 0; rx = r->x; if (xFixedToInt (rx) >= width) rx = IntToxFixed (width); /* Skip empty (or backwards) sections */ if (rx > lx) { int lxs, rxs; /* Find pixel bounds for span. */ lxi = xFixedToInt (lx); rxi = xFixedToInt (rx); /* Sample coverage for edge pixels */ lxs = RenderSamplesX (lx, 8); rxs = RenderSamplesX (rx, 8); /* Add coverage across row */ if (lxi == rxi) { ap[lxi] = clip255 (ap[lxi] + rxs - lxs); } else { ap[lxi] = clip255 (ap[lxi] + N_X_FRAC(8) - lxs); /* Move forward so that lxi/rxi is the pixel span */ lxi++; /* Don't bother trying to optimize the fill unless * the span is longer than 4 pixels. */ if (rxi - lxi > 4) { if (fill_start < 0) { fill_start = lxi; fill_end = rxi; fill_size++; } else { if (lxi >= fill_end || rxi < fill_start) { /* We're beyond what we saved, just fill it */ add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8), fill_end - fill_start); fill_start = lxi; fill_end = rxi; fill_size = 1; } else { /* Update fill_start */ if (lxi > fill_start) { add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8), lxi - fill_start); fill_start = lxi; } else if (lxi < fill_start) { add_saturate_8 (ap + lxi, N_X_FRAC(8), fill_start - lxi); } /* Update fill_end */ if (rxi < fill_end) { add_saturate_8 (ap + rxi, fill_size * N_X_FRAC(8), fill_end - rxi); fill_end = rxi; } else if (fill_end < rxi) { add_saturate_8 (ap + fill_end, N_X_FRAC(8), rxi - fill_end); } fill_size++; } } } else { add_saturate_8 (ap + lxi, N_X_FRAC(8), rxi - lxi); } /* Do not add in a 0 alpha here. This check is * necessary to avoid a buffer overrun, (when rx * is exactly on a pixel boundary). */ if (rxs) ap[rxi] = clip255 (ap[rxi] + rxs); } } if (y == b) { /* We're done, make sure we clean up any remaining fill. */ if (fill_start != fill_end) { if (fill_size == N_Y_FRAC(8)) { memset (ap + fill_start, 0xff, fill_end - fill_start); } else { add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8), fill_end - fill_start); } } break; } if (xFixedFrac (y) != Y_FRAC_LAST(8)) { RenderEdgeStepSmall (l); RenderEdgeStepSmall (r); y += STEP_Y_SMALL(8); } else { RenderEdgeStepBig (l); RenderEdgeStepBig (r); y += STEP_Y_BIG(8); if (fill_start != fill_end) { if (fill_size == N_Y_FRAC(8)) { memset (ap + fill_start, 0xff, fill_end - fill_start); } else { add_saturate_8 (ap + fill_start, fill_size * N_X_FRAC(8), fill_end - fill_start); } fill_start = fill_end = -1; fill_size = 0; } line += stride; } } }
static void xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region) { ScrnInfoPtr scrn = crtc->scrn; ScreenPtr screen = scrn->pScreen; WindowPtr root = WindowTable[screen->myNum]; PixmapPtr dst_pixmap = crtc->rotatedPixmap; PictFormatPtr format = compWindowFormat (WindowTable[screen->myNum]); int error; PicturePtr src, dst; PictTransform transform; int n = REGION_NUM_RECTS(region); BoxPtr b = REGION_RECTS(region); XID include_inferiors = IncludeInferiors; src = CreatePicture (None, &root->drawable, format, CPSubwindowMode, &include_inferiors, serverClient, &error); if (!src) return; dst = CreatePicture (None, &dst_pixmap->drawable, format, 0L, NULL, serverClient, &error); if (!dst) return; memset (&transform, '\0', sizeof (transform)); transform.matrix[2][2] = IntToxFixed(1); transform.matrix[0][2] = IntToxFixed(crtc->x); transform.matrix[1][2] = IntToxFixed(crtc->y); switch (crtc->rotation & 0xf) { default: case RR_Rotate_0: transform.matrix[0][0] = IntToxFixed(1); transform.matrix[1][1] = IntToxFixed(1); break; case RR_Rotate_90: transform.matrix[0][1] = IntToxFixed(-1); transform.matrix[1][0] = IntToxFixed(1); transform.matrix[0][2] += IntToxFixed(crtc->mode.VDisplay); break; case RR_Rotate_180: transform.matrix[0][0] = IntToxFixed(-1); transform.matrix[1][1] = IntToxFixed(-1); transform.matrix[0][2] += IntToxFixed(crtc->mode.HDisplay); transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay); break; case RR_Rotate_270: transform.matrix[0][1] = IntToxFixed(1); transform.matrix[1][0] = IntToxFixed(-1); transform.matrix[1][2] += IntToxFixed(crtc->mode.HDisplay); break; } /* handle reflection */ if (crtc->rotation & RR_Reflect_X) { /* XXX figure this out */ } if (crtc->rotation & RR_Reflect_Y) { /* XXX figure this out too */ } error = SetPictureTransform (src, &transform); if (error) return; while (n--) { BoxRec dst_box; xf86TransformBox (&dst_box, b, crtc->rotation, crtc->x, crtc->y, crtc->mode.HDisplay, crtc->mode.VDisplay); CompositePicture (PictOpSrc, src, NULL, dst, dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1, dst_box.x2 - dst_box.x1, dst_box.y2 - dst_box.y1); b++; } FreePicture (src, None); FreePicture (dst, None); }