summaryrefslogtreecommitdiff
path: root/saa/saa_render.c
diff options
context:
space:
mode:
Diffstat (limited to 'saa/saa_render.c')
-rw-r--r--saa/saa_render.c424
1 files changed, 424 insertions, 0 deletions
diff --git a/saa/saa_render.c b/saa/saa_render.c
new file mode 100644
index 0000000..c69f2c9
--- /dev/null
+++ b/saa/saa_render.c
@@ -0,0 +1,424 @@
1/*
2 * Copyright © 2001 Keith Packard
3 * Copyright 2011 VMWare, Inc. All Rights Reserved.
4 * May partly be based on code that is Copyright © The XFree86 Project Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * Author: Eric Anholt <eric@anholt.net>
27 * Author: Michel Dänzer <michel@tungstengraphics.com>
28 * Author: Thomas Hellstrom <thellstrom@vmware.com>
29 */
30#include "saa.h"
31#include "saa_priv.h"
32
33#ifdef RENDER
34#include <mipict.h>
35
36/**
37 * Same as miCreateAlphaPicture, except it uses
38 * saa_check_poly_fill_rect instead
39 */
40
41static PicturePtr
42saa_create_alpha_picture(ScreenPtr pScreen,
43 PicturePtr pDst,
44 PictFormatPtr pPictFormat, CARD16 width, CARD16 height)
45{
46 PixmapPtr pPixmap;
47 PicturePtr pPicture;
48 GCPtr pGC;
49 int error;
50 xRectangle rect;
51
52 if (width > 32767 || height > 32767)
53 return 0;
54
55 if (!pPictFormat) {
56 if (pDst->polyEdge == PolyEdgeSharp)
57 pPictFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
58 else
59 pPictFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
60 if (!pPictFormat)
61 return 0;
62 }
63
64 pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
65 pPictFormat->depth, 0);
66 if (!pPixmap)
67 return 0;
68 pGC = GetScratchGC(pPixmap->drawable.depth, pScreen);
69 if (!pGC) {
70 (*pScreen->DestroyPixmap) (pPixmap);
71 return 0;
72 }
73 ValidateGC(&pPixmap->drawable, pGC);
74 rect.x = 0;
75 rect.y = 0;
76 rect.width = width;
77 rect.height = height;
78 saa_check_poly_fill_rect(&pPixmap->drawable, pGC, 1, &rect);
79 FreeScratchGC(pGC);
80 pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
81 0, 0, serverClient, &error);
82 (*pScreen->DestroyPixmap) (pPixmap);
83 return pPicture;
84}
85
86/**
87 * saa_trapezoids is essentially a copy of miTrapezoids that uses
88 * saa_create_alpha_picture instead of miCreateAlphaPicture.
89 *
90 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
91 * to initialize the contents after creating the pixmap, which
92 * causes the pixmap to be moved in for acceleration. The subsequent
93 * call to RasterizeTrapezoid won't be accelerated however, which
94 * forces the pixmap to be moved out again.
95 *
96 */
97static void
98saa_trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
99 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
100 int ntrap, xTrapezoid * traps)
101{
102 ScreenPtr pScreen = pDst->pDrawable->pScreen;
103 PictureScreenPtr ps = GetPictureScreen(pScreen);
104 BoxRec bounds;
105
106 if (maskFormat) {
107 PicturePtr pPicture;
108 INT16 xDst, yDst;
109 INT16 xRel, yRel;
110 saa_access_t access;
111
112 miTrapezoidBounds(ntrap, traps, &bounds);
113
114 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
115 return;
116
117 xDst = traps[0].left.p1.x >> 16;
118 yDst = traps[0].left.p1.y >> 16;
119
120 pPicture = saa_create_alpha_picture(pScreen, pDst, maskFormat,
121 bounds.x2 - bounds.x1,
122 bounds.y2 - bounds.y1);
123 if (!pPicture)
124 return;
125
126 if (saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access)) {
127 for (; ntrap; ntrap--, traps++)
128 (*ps->RasterizeTrapezoid) (pPicture, traps,
129 -bounds.x1, -bounds.y1);
130 saa_fad_write(pPicture->pDrawable, access);
131 }
132
133 xRel = bounds.x1 + xSrc - xDst;
134 yRel = bounds.y1 + ySrc - yDst;
135 CompositePicture(op, pSrc, pPicture, pDst,
136 xRel, yRel, 0, 0, bounds.x1, bounds.y1,
137 bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
138 FreePicture(pPicture, 0);
139 } else {
140 if (pDst->polyEdge == PolyEdgeSharp)
141 maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
142 else
143 maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
144 for (; ntrap; ntrap--, traps++)
145 saa_trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
146 }
147}
148
149/**
150 * saa_triangles is essentially a copy of miTriangles that uses
151 * saa_create_alpha_picture instead of miCreateAlphaPicture.
152 *
153 * The problem with miCreateAlphaPicture is that it calls PolyFillRect
154 * to initialize the contents after creating the pixmap, which
155 * causes the pixmap to be moved in for acceleration. The subsequent
156 * call to AddTriangles won't be accelerated however, which forces the pixmap
157 * to be moved out again.
158 */
159static void
160saa_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
161 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
162 int ntri, xTriangle * tris)
163{
164 ScreenPtr pScreen = pDst->pDrawable->pScreen;
165 PictureScreenPtr ps = GetPictureScreen(pScreen);
166 BoxRec bounds;
167
168 if (maskFormat) {
169 PicturePtr pPicture;
170 INT16 xDst, yDst;
171 INT16 xRel, yRel;
172 saa_access_t access;
173
174 miTriangleBounds(ntri, tris, &bounds);
175
176 if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
177 return;
178
179 xDst = tris[0].p1.x >> 16;
180 yDst = tris[0].p1.y >> 16;
181
182 pPicture = saa_create_alpha_picture(pScreen, pDst, maskFormat,
183 bounds.x2 - bounds.x1,
184 bounds.y2 - bounds.y1);
185 if (!pPicture)
186 return;
187
188 if (saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access)) {
189 (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris);
190 saa_fad_write(pPicture->pDrawable, access);
191 }
192
193 xRel = bounds.x1 + xSrc - xDst;
194 yRel = bounds.y1 + ySrc - yDst;
195 CompositePicture(op, pSrc, pPicture, pDst,
196 xRel, yRel, 0, 0, bounds.x1, bounds.y1,
197 bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
198 FreePicture(pPicture, 0);
199 } else {
200 if (pDst->polyEdge == PolyEdgeSharp)
201 maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1);
202 else
203 maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8);
204
205 for (; ntri; ntri--, tris++)
206 saa_triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris);
207 }
208}
209
210static Bool
211saa_driver_composite(CARD8 op,
212 PicturePtr pSrc,
213 PicturePtr pMask,
214 PicturePtr pDst,
215 INT16 xSrc,
216 INT16 ySrc,
217 INT16 xMask,
218 INT16 yMask,
219 INT16 xDst,
220 INT16 yDst,
221 CARD16 width,
222 CARD16 height,
223 RegionPtr src_reg,
224 RegionPtr mask_reg,
225 RegionPtr dst_reg)
226{
227 struct saa_screen_priv *sscreen = saa_screen(pDst->pDrawable->pScreen);
228 BoxPtr pbox;
229 int nbox;
230 int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
231 PixmapPtr src_pix = NULL, mask_pix = NULL, dst_pix;
232 struct saa_driver *driver = sscreen->driver;
233
234 if (!driver->composite_prepare)
235 return FALSE;
236
237 dst_pix = saa_get_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
238 if (saa_pixmap(dst_pix)->auth_loc != saa_loc_driver)
239 return FALSE;
240
241 if (pMask && pMask->pDrawable) {
242 mask_pix = saa_get_pixmap(pMask->pDrawable, &mask_off_x, &mask_off_y);
243 if (saa_pixmap(mask_pix)->auth_loc != saa_loc_driver)
244 return FALSE;
245 }
246 if (pSrc->pDrawable) {
247 src_pix = saa_get_pixmap(pSrc->pDrawable, &src_off_x, &src_off_y);
248 if (saa_pixmap(src_pix)->auth_loc != saa_loc_driver)
249 return FALSE;
250 }
251
252 if (!driver->composite_prepare(driver, op, pSrc, pMask, pDst,
253 src_pix, mask_pix, dst_pix,
254 src_reg, mask_reg, dst_reg))
255 return FALSE;
256
257 nbox = REGION_NUM_RECTS(dst_reg);
258 pbox = REGION_RECTS(dst_reg);
259
260 xDst += pDst->pDrawable->x + dst_off_x;
261 yDst += pDst->pDrawable->y + dst_off_y;
262
263 if (src_pix) {
264 xSrc += pSrc->pDrawable->x + src_off_x - xDst;
265 ySrc += pSrc->pDrawable->y + src_off_y - yDst;
266 }
267 if (mask_pix) {
268 xMask += pMask->pDrawable->x + mask_off_x - xDst;
269 yMask += pMask->pDrawable->y + mask_off_y - yDst;
270 }
271
272 while (nbox--) {
273 driver->composite(driver,
274 pbox->x1 + xSrc,
275 pbox->y1 + ySrc,
276 pbox->x1 + xMask,
277 pbox->y1 + yMask,
278 pbox->x1,
279 pbox->y1,
280 pbox->x2 - pbox->x1,
281 pbox->y2 - pbox->y1);
282 pbox++;
283 }
284
285 driver->composite_done(driver);
286 saa_pixmap_dirty(dst_pix, TRUE, dst_reg);
287
288 return TRUE;
289}
290
291/*
292 * Try to turn a composite operation into an accelerated copy.
293 * We can do that in some special cases for PictOpSrc and PictOpOver.
294 */
295
296static Bool
297saa_copy_composite(CARD8 op,
298 PicturePtr pSrc,
299 PicturePtr pMask,
300 PicturePtr pDst,
301 INT16 xSrc,
302 INT16 ySrc,
303 INT16 xMask,
304 INT16 yMask,
305 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height,
306 RegionPtr dst_region)
307{
308 if (!pSrc->pDrawable || pSrc->transform ||
309 pSrc->repeat || xSrc < 0 || ySrc < 0 ||
310 xSrc + width > pSrc->pDrawable->width ||
311 ySrc + height > pSrc->pDrawable->height)
312 return FALSE;
313
314 if (op == PictOpSrc ||
315 (op == PictOpOver && PICT_FORMAT_A(pSrc->format) == 0 &&
316 pMask == NULL)) {
317
318 int xoff, yoff;
319 PixmapPtr dst_pix = saa_get_pixmap(pDst->pDrawable, &xoff, &yoff);
320 struct saa_pixmap *dst_spix = saa_pixmap(dst_pix);
321 struct saa_pixmap *src_spix =
322 saa_pixmap(saa_get_drawable_pixmap(pSrc->pDrawable));
323 int ret;
324
325 if (src_spix->auth_loc != saa_loc_driver ||
326 dst_spix->auth_loc != saa_loc_driver)
327 return FALSE;
328
329 src_spix->src_format = pSrc->format;
330 dst_spix->dst_format = pDst->format;
331
332 xDst += pDst->pDrawable->x;
333 yDst += pDst->pDrawable->y;
334 xSrc += pSrc->pDrawable->x;
335 ySrc += pSrc->pDrawable->y;
336
337 /*
338 * Dst region is in backing pixmap space. We need to
339 * translate it.
340 */
341 REGION_TRANSLATE(pScreen, dst_region, -xoff, -yoff);
342 ret = saa_hw_copy_nton(pSrc->pDrawable, pDst->pDrawable, NULL,
343 REGION_RECTS(dst_region),
344 REGION_NUM_RECTS(dst_region),
345 xSrc - xDst, ySrc - yDst, FALSE, FALSE);
346 REGION_TRANSLATE(pScreen, dst_region, xoff, yoff);
347
348 src_spix->src_format = 0;
349 dst_spix->dst_format = 0;
350
351 if (ret)
352 return TRUE;
353 }
354 return FALSE;
355}
356
357static void
358saa_composite(CARD8 op,
359 PicturePtr pSrc,
360 PicturePtr pMask,
361 PicturePtr pDst,
362 INT16 xSrc,
363 INT16 ySrc,
364 INT16 xMask,
365 INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
366{
367 ScreenPtr pScreen = pDst->pDrawable->pScreen;
368 RegionRec dst_region;
369 RegionPtr src_region;
370 RegionPtr mask_region;
371
372 REGION_NULL(pScreen, &dst_region);
373 if (!saa_compute_composite_regions(pScreen, pSrc, pMask, pDst,
374 xSrc, ySrc, xMask, yMask, xDst,
375 yDst, width, height,
376 &dst_region, &src_region, &mask_region))
377 goto out;
378
379 if (saa_copy_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
380 xDst, yDst, width, height, &dst_region))
381 goto out;
382
383 if (saa_driver_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
384 xDst, yDst, width, height, src_region,
385 mask_region, &dst_region))
386 goto out;
387
388 saa_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
389 xDst, yDst, width, height,
390 src_region, mask_region, &dst_region);
391 out:
392 if (src_region)
393 REGION_UNINIT(pScreen, src_region);
394 if (mask_region && mask_region != src_region)
395 REGION_UNINIT(pScreen, mask_region);
396 REGION_UNINIT(pScreen, &dst_region);
397}
398
399void
400saa_render_setup(ScreenPtr pScreen)
401{
402 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
403 struct saa_screen_priv *sscreen = saa_screen(pScreen);
404
405 if (ps) {
406 saa_wrap(sscreen, ps, Trapezoids, saa_trapezoids);
407 saa_wrap(sscreen, ps, Triangles, saa_triangles);
408 saa_wrap(sscreen, ps, Composite, saa_composite);
409 }
410}
411
412void
413saa_render_takedown(ScreenPtr pScreen)
414{
415 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
416 struct saa_screen_priv *sscreen = saa_screen(pScreen);
417
418 if (ps) {
419 saa_unwrap(sscreen, ps, Trapezoids);
420 saa_unwrap(sscreen, ps, Triangles);
421 saa_unwrap(sscreen, ps, Composite);
422 }
423}
424#endif