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_H2(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,
60
((tdc->clipY1 - refY) << 16) | tdc->clipX1);
61
OUT_RING_H1(VIA_REG_CLIPBR,
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_H2(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_H2(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, tdc->keyControl);
124
OUT_RING_H1(VIA_REG_SRCCOLORKEY, 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_H2(ScreenPtr pScreen)
137
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
138
VIAPtr pVia = VIAPTR(pScrn);
144
/* Wrap around without affecting the sign bit. */
145
pVia->curMarker &= 0x7FFFFFFF;
149
OUT_RING_H1(VIA_REG_KEYCONTROL, 0x00);
150
OUT_RING_H1(VIA_REG_GEMODE, VIA_GEM_32bpp);
151
OUT_RING_H1(VIA_REG_DSTBASE, pVia->markerOffset >> 3);
152
OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE);
153
OUT_RING_H1(VIA_REG_DSTPOS, 0);
154
OUT_RING_H1(VIA_REG_DIMENSION, 0);
155
OUT_RING_H1(VIA_REG_FGCOLOR, pVia->curMarker);
156
OUT_RING_H1(VIA_REG_GECMD, (0xF0 << 24) | VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT);
160
return pVia->curMarker;
164
* Exa functions. It is assumed that EXA does not exceed the blitter limits.
167
viaExaPrepareSolid_H2(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
169
ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
170
VIAPtr pVia = VIAPTR(pScrn);
171
ViaTwodContext *tdc = &pVia->td;
175
if (exaGetPixmapPitch(pPixmap) & 7)
178
if (!viaAccelSetMode(pPixmap->drawable.depth, tdc))
181
if (!viaAccelPlaneMaskHelper_H2(tdc, planeMask))
184
viaAccelTransparentHelper_H2(pVia, 0x0, 0x0, TRUE);
186
tdc->cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(alu);
194
viaExaSolid_H2(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
196
ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
197
CARD32 dstOffset = exaGetPixmapOffset(pPixmap);
198
CARD32 dstPitch = exaGetPixmapPitch(pPixmap);
199
int w = x2 - x1, h = y2 - y1;
200
VIAPtr pVia = VIAPTR(pScrn);
201
ViaTwodContext *tdc = &pVia->td;
206
OUT_RING_H1(VIA_REG_GEMODE, tdc->mode);
207
OUT_RING_H1(VIA_REG_DSTBASE, dstOffset >> 3);
208
OUT_RING_H1(VIA_REG_PITCH, VIA_PITCH_ENABLE | (dstPitch >> 3) << 16);
209
OUT_RING_H1(VIA_REG_DSTPOS, (y1 << 16) | (x1 & 0xFFFF));
210
OUT_RING_H1(VIA_REG_DIMENSION, ((h - 1) << 16) | (w - 1));
211
OUT_RING_H1(VIA_REG_FGCOLOR, tdc->fgColor);
212
OUT_RING_H1(VIA_REG_GECMD, tdc->cmd);
218
viaExaDoneSolidCopy_H2(PixmapPtr pPixmap)
223
viaExaPrepareCopy_H2(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
224
int ydir, int alu, Pixel planeMask)
226
ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
227
VIAPtr pVia = VIAPTR(pScrn);
228
ViaTwodContext *tdc = &pVia->td;
232
if (pSrcPixmap->drawable.bitsPerPixel != pDstPixmap->drawable.bitsPerPixel)
235
if ((tdc->srcPitch = exaGetPixmapPitch(pSrcPixmap)) & 3)
238
if (exaGetPixmapPitch(pDstPixmap) & 7)
241
tdc->srcOffset = exaGetPixmapOffset(pSrcPixmap);
243
tdc->cmd = VIA_GEC_BLT | VIAACCELCOPYROP(alu);
245
tdc->cmd |= VIA_GEC_DECX;
247
tdc->cmd |= VIA_GEC_DECY;
249
if (!viaAccelSetMode(pDstPixmap->drawable.bitsPerPixel, tdc))
252
if (!viaAccelPlaneMaskHelper_H2(tdc, planeMask))
254
viaAccelTransparentHelper_H2(pVia, 0x0, 0x0, TRUE);
260
viaExaCopy_H2(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
261
int width, int height)
263
ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
264
CARD32 dstOffset = exaGetPixmapOffset(pDstPixmap), val;
265
CARD32 dstPitch = exaGetPixmapPitch(pDstPixmap);
266
VIAPtr pVia = VIAPTR(pScrn);
267
ViaTwodContext *tdc = &pVia->td;
269
if (!width || !height)
272
if (tdc->cmd & VIA_GEC_DECY) {
277
if (tdc->cmd & VIA_GEC_DECX) {
281
val = VIA_PITCH_ENABLE | (dstPitch >> 3) << 16 | (tdc->srcPitch >> 3);
286
OUT_RING_H1(VIA_REG_GEMODE, tdc->mode);
287
OUT_RING_H1(VIA_REG_SRCBASE, tdc->srcOffset >> 3);
288
OUT_RING_H1(VIA_REG_DSTBASE, dstOffset >> 3);
289
OUT_RING_H1(VIA_REG_PITCH, val);
290
OUT_RING_H1(VIA_REG_SRCPOS, (srcY << 16) | (srcX & 0xFFFF));
291
OUT_RING_H1(VIA_REG_DSTPOS, (dstY << 16) | (dstX & 0xFFFF));
292
OUT_RING_H1(VIA_REG_DIMENSION, ((height - 1) << 16) | (width - 1));
293
OUT_RING_H1(VIA_REG_GECMD, tdc->cmd);
299
viaExaCheckComposite_H2(int op, PicturePtr pSrcPicture,
300
PicturePtr pMaskPicture, PicturePtr pDstPicture)
302
ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPicture->pDrawable->pScreen);
303
VIAPtr pVia = VIAPTR(pScrn);
304
Via3DState *v3d = &pVia->v3d;
306
if (!pSrcPicture->pDrawable)
309
/* Reject small composites early. They are done much faster in software. */
310
if (!pSrcPicture->repeat &&
311
pSrcPicture->pDrawable->width *
312
pSrcPicture->pDrawable->height < VIA_MIN_COMPOSITE)
315
if (pMaskPicture && pMaskPicture->pDrawable &&
316
!pMaskPicture->repeat &&
317
pMaskPicture->pDrawable->width *
318
pMaskPicture->pDrawable->height < VIA_MIN_COMPOSITE)
321
if (pMaskPicture && pMaskPicture->repeat &&
322
pMaskPicture->repeatType != RepeatNormal)
325
if (pMaskPicture && pMaskPicture->componentAlpha) {
326
#ifdef VIA_DEBUG_COMPOSITE
327
viaExaPrintCompositeInfo("Component Alpha operation", op, pSrcPicture, pMaskPicture, pDstPicture);
332
if (!v3d->opSupported(op)) {
333
#ifdef VIA_DEBUG_COMPOSITE
334
viaExaPrintCompositeInfo("Operator not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
340
* FIXME: A8 destination formats are currently not supported and do not
341
* seem supported by the hardware, although there are some leftover
342
* register settings apparent in the via_3d_reg.h file. We need to fix this
343
* (if important), by using component ARGB8888 operations with bitmask.
346
if (!v3d->dstSupported(pDstPicture->format)) {
347
#ifdef VIA_DEBUG_COMPOSITE
348
viaExaPrintCompositeInfo(" Destination format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
353
if (v3d->texSupported(pSrcPicture->format)) {
354
if (pMaskPicture && (PICT_FORMAT_A(pMaskPicture->format) == 0 ||
355
!v3d->texSupported(pMaskPicture->format))) {
356
#ifdef VIA_DEBUG_COMPOSITE
357
viaExaPrintCompositeInfo("Mask format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
363
#ifdef VIA_DEBUG_COMPOSITE
364
viaExaPrintCompositeInfo("Src format not supported", op, pSrcPicture, pMaskPicture, pDstPicture);
370
viaIsAGP(VIAPtr pVia, PixmapPtr pPix, unsigned long *offset)
375
if (pVia->directRenderingType && !pVia->IsPCI) {
376
offs = ((unsigned long)pPix->devPrivate.ptr
377
- (unsigned long)pVia->agpMappedAddr);
379
if ((offs - pVia->scratchOffset) < pVia->agpSize) {
380
*offset = offs + pVia->agpAddr;
389
viaExaIsOffscreen(PixmapPtr pPix)
391
ScrnInfoPtr pScrn = xf86ScreenToScrn(pPix->drawable.pScreen);
392
VIAPtr pVia = VIAPTR(pScrn);
394
return ((unsigned long)pPix->devPrivate.ptr -
395
(unsigned long) drm_bo_map(pScrn, pVia->drmmode.front_bo)) < pVia->drmmode.front_bo->size;
399
viaExaPrepareComposite_H2(int op, PicturePtr pSrcPicture,
400
PicturePtr pMaskPicture, PicturePtr pDstPicture,
401
PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
403
CARD32 height, width;
404
ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
405
VIAPtr pVia = VIAPTR(pScrn);
406
Via3DState *v3d = &pVia->v3d;
408
ViaTexBlendingModes srcMode;
410
unsigned long offset;
412
/* Workaround: EXA crash with new libcairo2 on a VIA VX800 (#298) */
413
/* TODO Add real source only pictures */
415
ErrorF("pSrc is NULL\n");
419
v3d->setDestination(v3d, exaGetPixmapOffset(pDst),
420
exaGetPixmapPitch(pDst), pDstPicture->format);
421
v3d->setCompositeOperator(v3d, op);
422
v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0xFF);
424
viaOrder(pSrc->drawable.width, &width);
425
viaOrder(pSrc->drawable.height, &height);
428
* For one-pixel repeat mask pictures we avoid using multitexturing by
429
* modifying the src's texture blending equation and feed the pixel
430
* value as a constant alpha for the src's texture. Multitexturing on the
431
* Unichromes seems somewhat slow, so this speeds up translucent windows.
437
(pMaskPicture->pDrawable->height == 1) &&
438
(pMaskPicture->pDrawable->width == 1) &&
439
pMaskPicture->repeat && viaExpandablePixel(pMaskPicture->format)) {
440
pVia->maskP = pMask->devPrivate.ptr;
441
pVia->maskFormat = pMaskPicture->format;
442
pVia->componentAlpha = pMaskPicture->componentAlpha;
443
srcMode = ((pMaskPicture->componentAlpha)
444
? via_src_onepix_comp_mask : via_src_onepix_mask);
448
* One-Pixel repeat src pictures go as solid color instead of textures.
449
* Speeds up window shadows.
453
if (pSrcPicture && pSrcPicture->repeat
454
&& (pSrcPicture->pDrawable->height == 1)
455
&& (pSrcPicture->pDrawable->width == 1)
456
&& viaExpandablePixel(pSrcPicture->format)) {
457
pVia->srcP = pSrc->devPrivate.ptr;
458
pVia->srcFormat = pSrcPicture->format;
461
/* Exa should be smart enough to eliminate this IN operation. */
462
if (pVia->srcP && pVia->maskP) {
463
ErrorF("Bad one-pixel IN composite operation. "
464
"EXA needs to be smarter.\n");
469
offset = exaGetPixmapOffset(pSrc);
470
isAGP = viaIsAGP(pVia, pSrc, &offset);
471
if (!isAGP && !viaExaIsOffscreen(pSrc))
473
if (!v3d->setTexture(v3d, curTex, offset,
474
exaGetPixmapPitch(pSrc), pVia->nPOT[curTex],
475
1 << width, 1 << height, pSrcPicture->format,
476
via_repeat, via_repeat, srcMode, isAGP)) {
482
if (pMaskPicture && !pVia->maskP) {
483
offset = exaGetPixmapOffset(pMask);
484
isAGP = viaIsAGP(pVia, pMask, &offset);
485
if (!isAGP && !viaExaIsOffscreen(pMask))
487
viaOrder(pMask->drawable.width, &width);
488
viaOrder(pMask->drawable.height, &height);
489
if (!v3d->setTexture(v3d, curTex, offset,
490
exaGetPixmapPitch(pMask), pVia->nPOT[curTex],
491
1 << width, 1 << height, pMaskPicture->format,
492
via_repeat, via_repeat,
493
((pMaskPicture->componentAlpha)
494
? via_comp_mask : via_mask), isAGP)) {
500
v3d->setFlags(v3d, curTex, FALSE, TRUE, TRUE);
501
v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
502
v3d->emitClipRect(v3d, &pVia->cb, 0, 0, pDst->drawable.width,
503
pDst->drawable.height);
509
viaExaComposite_H2(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
510
int dstX, int dstY, int width, int height)
512
ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
513
VIAPtr pVia = VIAPTR(pScrn);
514
Via3DState *v3d = &pVia->v3d;
518
viaPixelARGB8888(pVia->maskFormat, pVia->maskP, &col);
519
v3d->setTexBlendCol(v3d, 0, pVia->componentAlpha, col);
522
viaPixelARGB8888(pVia->srcFormat, pVia->srcP, &col);
523
v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, col & 0x00FFFFFF, col >> 24);
528
if (pVia->maskP || pVia->srcP)
529
v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
531
v3d->emitQuad(v3d, &pVia->cb, dstX, dstY, srcX, srcY, maskX, maskY,
536
viaAccelTextureBlit(ScrnInfoPtr pScrn, unsigned long srcOffset,
537
unsigned srcPitch, unsigned w, unsigned h, unsigned srcX,
538
unsigned srcY, unsigned srcFormat, unsigned long dstOffset,
539
unsigned dstPitch, unsigned dstX, unsigned dstY,
540
unsigned dstFormat, int rotate)
542
VIAPtr pVia = VIAPTR(pScrn);
543
CARD32 wOrder, hOrder;
544
Via3DState *v3d = &pVia->v3d;
546
viaOrder(w, &wOrder);
547
viaOrder(h, &hOrder);
549
v3d->setDestination(v3d, dstOffset, dstPitch, dstFormat);
550
v3d->setDrawing(v3d, 0x0c, 0xFFFFFFFF, 0x000000FF, 0x00);
551
v3d->setFlags(v3d, 1, TRUE, TRUE, FALSE);
552
v3d->setTexture(v3d, 0, srcOffset, srcPitch, TRUE,
553
1 << wOrder, 1 << hOrder, srcFormat,
554
via_single, via_single, via_src, FALSE);
555
v3d->emitState(v3d, &pVia->cb, viaCheckUpload(pScrn, v3d));
556
v3d->emitClipRect(v3d, &pVia->cb, dstX, dstY, w, h);
557
v3d->emitQuad(v3d, &pVia->cb, dstX, dstY, srcX, srcY, 0, 0, w, h);