2
* Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3
* Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4
* Copyright 2006 Thomas Hellström. All Rights Reserved.
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the "Software"),
8
* to deal in the Software without restriction, including without limitation
9
* the rights to use, copy, modify, merge, publish, distribute, sub license,
10
* and/or sell copies of the Software, and to permit persons to whom the
11
* Software is furnished to do so, subject to the following conditions:
13
* The above copyright notice and this permission notice (including the
14
* next paragraph) shall be included in all copies or substantial portions
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
* DEALINGS IN THE SOFTWARE.
27
* 2D acceleration functions for the VIA/S3G UniChrome IGPs.
29
* Mostly rewritten, and modified for EXA support, by Thomas Hellström.
36
#include <X11/Xarch.h>
39
#include "via_driver.h"
41
#include "via_dmabuffer.h"
45
* Emit clipping borders to the command buffer and update the 2D context
46
* current command with clipping info.
49
viaAccelClippingHelper_H6(VIAPtr pVia, int refY)
51
ViaTwodContext *tdc = &pVia->td;
56
refY = (refY < tdc->clipY1) ? refY : tdc->clipY1;
57
tdc->cmd |= VIA_GEC_CLIP_ENABLE;
59
OUT_RING_H1(VIA_REG_CLIPTL_M1,
60
((tdc->clipY1 - refY) << 16) | tdc->clipX1);
61
OUT_RING_H1(VIA_REG_CLIPBR_M1,
62
((tdc->clipY2 - refY) << 16) | tdc->clipX2);
64
tdc->cmd &= ~VIA_GEC_CLIP_ENABLE;
70
* Check if we can use a planeMask and update the 2D context accordingly.
73
viaAccelPlaneMaskHelper_H6(ViaTwodContext * tdc, CARD32 planeMask)
75
CARD32 modeMask = (1 << ((1 << tdc->bytesPPShift) << 3)) - 1;
76
CARD32 curMask = 0x00000000;
80
if ((planeMask & modeMask) != modeMask) {
82
/* Masking doesn't work in 8bpp. */
83
if (modeMask == 0xFF) {
84
tdc->keyControl &= 0x0FFFFFFF;
88
/* Translate the bit planemask to a byte planemask. */
89
for (i = 0; i < (1 << tdc->bytesPPShift); ++i) {
90
curByteMask = (0xFF << (i << 3));
92
if ((planeMask & curByteMask) == 0) {
94
} else if ((planeMask & curByteMask) != curByteMask) {
95
tdc->keyControl &= 0x0FFFFFFF;
99
ErrorF("DEBUG: planeMask 0x%08x, curMask 0%02x\n",
100
(unsigned)planeMask, (unsigned)curMask);
102
tdc->keyControl = (tdc->keyControl & 0x0FFFFFFF) | (curMask << 28);
109
* Emit transparency state and color to the command buffer.
112
viaAccelTransparentHelper_H6(VIAPtr pVia, CARD32 keyControl,
113
CARD32 transColor, Bool usePlaneMask)
115
ViaTwodContext *tdc = &pVia->td;
119
tdc->keyControl &= ((usePlaneMask) ? 0xF0000000 : 0x00000000);
120
tdc->keyControl |= (keyControl & 0x0FFFFFFF);
122
OUT_RING_H1(VIA_REG_KEYCONTROL_M1, tdc->keyControl);
124
OUT_RING_H1(VIA_REG_SRCCOLORKEY_M1, transColor);
129
* Mark Sync using the 2D blitter for AGP. NoOp for PCI.
130
* In the future one could even launch a NULL PCI DMA command
131
* to have an interrupt generated, provided it is possible to
132
* write to the PCI DMA engines from the AGP command stream.
135
viaAccelMarkSync_H6(ScreenPtr pScreen)
137
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
138
VIAPtr pVia = VIAPTR(pScrn);
144
/* Wrap around without affecting the sign bit. */
145
pVia->curMarker &= 0x7FFFFFFF;
150
OUT_RING_H1(VIA_REG_KEYCONTROL_M1, 0x00);
151
OUT_RING_H1(VIA_REG_GEMODE_M1, VIA_GEM_32bpp);
152
OUT_RING_H1(VIA_REG_DSTBASE_M1, pVia->curMarker >> 3);
153
OUT_RING_H1(VIA_REG_PITCH_M1, 0);
154
OUT_RING_H1(VIA_REG_DSTPOS_M1, 0);
155
OUT_RING_H1(VIA_REG_DIMENSION_M1, 0);
156
OUT_RING_H1(VIA_REG_MONOPATFGC_M1, pVia->curMarker);
157
OUT_RING_H1(VIA_REG_GECMD_M1, (0xF0 << 24) | VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT);
161
return pVia->curMarker;
165
* Exa functions. It is assumed that EXA does not exceed the blitter limits.
168
viaExaPrepareSolid_H6(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
170
ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
171
VIAPtr pVia = VIAPTR(pScrn);
172
ViaTwodContext *tdc = &pVia->td;
176
if (exaGetPixmapPitch(pPixmap) & 7)
179
if (!viaAccelSetMode(pPixmap->drawable.depth, tdc))
182
if (!viaAccelPlaneMaskHelper_H6(tdc, planeMask))
185
viaAccelTransparentHelper_H6(pVia, 0x0, 0x0, TRUE);
187
tdc->cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(alu);
195
viaExaSolid_H6(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
197
ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
198
CARD32 dstOffset = exaGetPixmapOffset(pPixmap);
199
CARD32 dstPitch = exaGetPixmapPitch(pPixmap);
200
int w = x2 - x1, h = y2 - y1;
201
VIAPtr pVia = VIAPTR(pScrn);
202
ViaTwodContext *tdc = &pVia->td;
207
OUT_RING_H1(VIA_REG_GEMODE_M1, tdc->mode);
208
OUT_RING_H1(VIA_REG_DSTBASE_M1, dstOffset >> 3);
209
OUT_RING_H1(VIA_REG_PITCH_M1, (dstPitch >> 3) << 16);
210
OUT_RING_H1(VIA_REG_DSTPOS_M1, (y1 << 16) | (x1 & 0xFFFF));
211
OUT_RING_H1(VIA_REG_DIMENSION_M1, ((h - 1) << 16) | (w - 1));
212
OUT_RING_H1(VIA_REG_MONOPATFGC_M1, tdc->fgColor);
213
OUT_RING_H1(VIA_REG_GECMD_M1, tdc->cmd);
219
viaExaDoneSolidCopy_H6(PixmapPtr pPixmap)
224
viaExaPrepareCopy_H6(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
225
int ydir, int alu, Pixel planeMask)
227
ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
228
VIAPtr pVia = VIAPTR(pScrn);
229
ViaTwodContext *tdc = &pVia->td;
233
if (pSrcPixmap->drawable.bitsPerPixel != pDstPixmap->drawable.bitsPerPixel)
236
if ((tdc->srcPitch = exaGetPixmapPitch(pSrcPixmap)) & 3)
239
if (exaGetPixmapPitch(pDstPixmap) & 7)
242
tdc->srcOffset = exaGetPixmapOffset(pSrcPixmap);
244
tdc->cmd = VIA_GEC_BLT | VIAACCELCOPYROP(alu);
246
tdc->cmd |= VIA_GEC_DECX;
248
tdc->cmd |= VIA_GEC_DECY;
250
if (!viaAccelSetMode(pDstPixmap->drawable.bitsPerPixel, tdc))
253
if (!viaAccelPlaneMaskHelper_H6(tdc, planeMask))
255
viaAccelTransparentHelper_H6(pVia, 0x0, 0x0, TRUE);
261
viaExaCopy_H6(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
262
int width, int height)
264
ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
265
CARD32 dstOffset = exaGetPixmapOffset(pDstPixmap), val;
266
CARD32 dstPitch = exaGetPixmapPitch(pDstPixmap);
267
VIAPtr pVia = VIAPTR(pScrn);
268
ViaTwodContext *tdc = &pVia->td;
270
if (!width || !height)
275
if (tdc->cmd & VIA_GEC_DECY) {
280
if (tdc->cmd & VIA_GEC_DECX) {
284
val = (dstPitch >> 3) << 16 | (tdc->srcPitch >> 3);
287
OUT_RING_H1(VIA_REG_GEMODE_M1, tdc->mode);
288
OUT_RING_H1(VIA_REG_SRCBASE_M1, tdc->srcOffset >> 3);
289
OUT_RING_H1(VIA_REG_DSTBASE_M1, dstOffset >> 3);
290
OUT_RING_H1(VIA_REG_PITCH_M1, val);
292
OUT_RING_H1(VIA_REG_SRCPOS_M1, (srcY << 16) | (srcX & 0xFFFF));
293
OUT_RING_H1(VIA_REG_DSTPOS_M1, (dstY << 16) | (dstX & 0xFFFF));
294
OUT_RING_H1(VIA_REG_DIMENSION_M1, ((height - 1) << 16) | (width - 1));
295
OUT_RING_H1(VIA_REG_GECMD_M1, tdc->cmd);
301
viaExaCheckComposite_H6(int op, PicturePtr pSrcPicture,
302
PicturePtr pMaskPicture, PicturePtr pDstPicture)
304
ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPicture->pDrawable->pScreen);
305
VIAPtr pVia = VIAPTR(pScrn);
306
Via3DState *v3d = &pVia->v3d;
308
if (!pSrcPicture->pDrawable) {
311
/* Reject small composites early. They are done much faster in software. */
312
if (!pSrcPicture->repeat &&
313
pSrcPicture->pDrawable->width *
314
pSrcPicture->pDrawable->height < VIA_MIN_COMPOSITE) {
316
#ifdef VIA_DEBUG_COMPOSITE
317
viaExaPrintCompositeInfo("Source picture too small", op, pSrcPicture, pMaskPicture, pDstPicture);
322
if (pMaskPicture && pMaskPicture->pDrawable &&
323
!pMaskPicture->repeat &&
324
pMaskPicture->pDrawable->width *
325
pMaskPicture->pDrawable->height < VIA_MIN_COMPOSITE) {
326
#ifdef VIA_DEBUG_COMPOSITE
327
viaExaPrintCompositeInfo("Mask picture too small", op, pSrcPicture, pMaskPicture, pDstPicture);
332
if (pMaskPicture && pMaskPicture->repeat && pMaskPicture->repeatType != RepeatNormal) {
333
#ifdef VIA_DEBUG_COMPOSITE
334
viaExaPrintCompositeInfo("Repeat is different than normal", op, pSrcPicture, pMaskPicture, pDstPicture);
338
if (pMaskPicture && pMaskPicture->componentAlpha) {
339
#ifdef VIA_DEBUG_COMPOSITE
340
viaExaPrintCompositeInfo("Component Alpha operation", op, pSrcPicture, pMaskPicture, pDstPicture);
345
if (!v3d->opSupported(op)) {
346
#ifdef VIA_DEBUG_COMPOSITE
347
viaExaPrintCompositeInfo("Operator not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
353
* FIXME: A8 destination formats are currently not supported and do not
354
* seem supported by the hardware, although there are some leftover
355
* register settings apparent in the via_3d_reg.h file. We need to fix this
356
* (if important), by using component ARGB8888 operations with bitmask.
359
if (!v3d->dstSupported(pDstPicture->format)) {
360
#ifdef VIA_DEBUG_COMPOSITE
361
viaExaPrintCompositeInfo("Destination format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
366
if (v3d->texSupported(pSrcPicture->format)) {
367
if (pMaskPicture && (PICT_FORMAT_A(pMaskPicture->format) == 0 ||
368
!v3d->texSupported(pMaskPicture->format))) {
369
#ifdef VIA_DEBUG_COMPOSITE
370
viaExaPrintCompositeInfo("Mask format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
376
#ifdef VIA_DEBUG_COMPOSITE
377
viaExaPrintCompositeInfo("Src format not supported",op, pSrcPicture, pMaskPicture, pDstPicture);
383
viaIsAGP(VIAPtr pVia, PixmapPtr pPix, unsigned long *offset)
388
if (pVia->directRenderingType && !pVia->IsPCI) {
389
offs = ((unsigned long)pPix->devPrivate.ptr
390
- (unsigned long)pVia->agpMappedAddr);
392
if ((offs - pVia->scratchOffset) < pVia->agpSize) {
393
*offset = offs + pVia->agpAddr;
402
viaExaIsOffscreen(PixmapPtr pPix)
404
ScrnInfoPtr pScrn = xf86ScreenToScrn(pPix->drawable.pScreen);
405
VIAPtr pVia = VIAPTR(pScrn);
407
return ((unsigned long)pPix->devPrivate.ptr -
408
(unsigned long) drm_bo_map(pScrn, pVia->drmmode.front_bo)) < pVia->drmmode.front_bo->size;
412
viaExaPrepareComposite_H6(int op, PicturePtr pSrcPicture,
413
PicturePtr pMaskPicture, PicturePtr pDstPicture,
414
PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
416
CARD32 height, width;
417
ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
418
VIAPtr pVia = VIAPTR(pScrn);
419
Via3DState *v3d = &pVia->v3d;
421
ViaTexBlendingModes srcMode;
423
unsigned long offset;
425
/* Workaround: EXA crash with new libcairo2 on a VIA VX800 (#298) */
426
/* TODO Add real source only pictures */
428
ErrorF("pSrc is NULL\n");
432
v3d->setDestination(v3d, exaGetPixmapOffset(pDst),
433
exaGetPixmapPitch(pDst), pDstPicture->format);
434
v3d->setCompositeOperator(v3d, op);
435
v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0xFF);
437
viaOrder(pSrc->drawable.width, &width);
438
viaOrder(pSrc->drawable.height, &height);
441
* For one-pixel repeat mask pictures we avoid using multitexturing by
442
* modifying the src's texture blending equation and feed the pixel
443
* value as a constant alpha for the src's texture. Multitexturing on the
444
* Unichromes seems somewhat slow, so this speeds up translucent windows.
450
(pMaskPicture->pDrawable->height == 1) &&
451
(pMaskPicture->pDrawable->width == 1) &&
452
pMaskPicture->repeat && viaExpandablePixel(pMaskPicture->format)) {
453
pVia->maskP = pMask->devPrivate.ptr;
454
pVia->maskFormat = pMaskPicture->format;
455
pVia->componentAlpha = pMaskPicture->componentAlpha;
456
srcMode = ((pMaskPicture->componentAlpha)
457
? via_src_onepix_comp_mask : via_src_onepix_mask);
461
* One-Pixel repeat src pictures go as solid color instead of textures.
462
* Speeds up window shadows.
466
if (pSrcPicture && pSrcPicture->repeat
467
&& (pSrcPicture->pDrawable->height == 1)
468
&& (pSrcPicture->pDrawable->width == 1)
469
&& viaExpandablePixel(pSrcPicture->format)) {
470
pVia->srcP = pSrc->devPrivate.ptr;
471
pVia->srcFormat = pSrcPicture->format;
474
/* Exa should be smart enough to eliminate this IN operation. */
475
if (pVia->srcP && pVia->maskP) {
476
ErrorF("Bad one-pixel IN composite operation. "
477
"EXA needs to be smarter.\n");
482
offset = exaGetPixmapOffset(pSrc);
483
isAGP = viaIsAGP(pVia, pSrc, &offset);
484
if (!isAGP && !viaExaIsOffscreen(pSrc))
486
if (!v3d->setTexture(v3d, curTex, offset,
487
exaGetPixmapPitch(pSrc), pVia->nPOT[curTex],
488
1 << width, 1 << height, pSrcPicture->format,
489
via_repeat, via_repeat, srcMode, isAGP)) {
495
if (pMaskPicture && !pVia->maskP) {
496
offset = exaGetPixmapOffset(pMask);
497
isAGP = viaIsAGP(pVia, pMask, &offset);
498
if (!isAGP && !viaExaIsOffscreen(pMask))
500
viaOrder(pMask->drawable.width, &width);
501
viaOrder(pMask->drawable.height, &height);
502
if (!v3d->setTexture(v3d, curTex, offset,
503
exaGetPixmapPitch(pMask), pVia->nPOT[curTex],
504
1 << width, 1 << height, pMaskPicture->format,
505
via_repeat, via_repeat,
506
((pMaskPicture->componentAlpha)
507
? via_comp_mask : via_mask), isAGP)) {
513
v3d->setFlags(v3d, curTex, FALSE, TRUE, TRUE);
514
v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
515
v3d->emitClipRect(v3d, &pVia->cb, 0, 0, pDst->drawable.width,
516
pDst->drawable.height);
522
viaExaComposite_H6(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
523
int dstX, int dstY, int width, int height)
525
ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
526
VIAPtr pVia = VIAPTR(pScrn);
527
Via3DState *v3d = &pVia->v3d;
531
viaPixelARGB8888(pVia->maskFormat, pVia->maskP, &col);
532
v3d->setTexBlendCol(v3d, 0, pVia->componentAlpha, col);
535
viaPixelARGB8888(pVia->srcFormat, pVia->srcP, &col);
536
v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, col & 0x00FFFFFF, col >> 24);
541
if (pVia->maskP || pVia->srcP)
542
v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
544
v3d->emitQuad(v3d, &pVia->cb, dstX, dstY, srcX, srcY, maskX, maskY,