10
#include <X11/extensions/Xv.h>
13
static Atom xvColorKey, xvFilterQuality;
15
/* These should move into tdfxdefs.h with better names */
16
#define YUV_Y_BASE 0xC00000
17
#define YUV_U_BASE 0xD00000
18
#define YUV_V_BASE 0xE00000
20
#define SST_2D_FORMAT_YUYV 0x8
21
#define SST_2D_FORMAT_UYVY 0x9
23
#define YUVBASEADDR 0x80100
24
#define YUVSTRIDE 0x80104
25
#define VIDPROCCFGMASK 0xa2e3eb6c
27
#define OFF_DELAY 250 /* milliseconds */
28
#define FREE_DELAY 15000
30
#define OFF_TIMER 0x01
31
#define FREE_TIMER 0x02
32
#define CLIENT_VIDEO_ON 0x04
33
#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
35
#define TDFX_MAX_OVERLAY_PORTS 1
36
#define TDFX_MAX_TEXTURE_PORTS 32
38
#define GET_PORT_PRIVATE(pScrn) \
39
(TDFXPortPrivPtr)((TDFXPTR(pScrn))->overlayAdaptor->pPortPrivates[0].ptr)
41
/* Needed for attribute atoms */
42
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
48
static FBAreaPtr TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height);
49
static FBLinearPtr TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size);
50
static void TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time);
52
static XF86VideoAdaptorPtr TDFXSetupImageVideoTexture(ScreenPtr);
53
static int TDFXSetPortAttributeTexture(ScrnInfoPtr, Atom, INT32, pointer);
54
static int TDFXGetPortAttributeTexture(ScrnInfoPtr, Atom ,INT32 *, pointer);
55
static int TDFXPutImageTexture(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr);
56
static void TDFXStopVideoTexture(ScrnInfoPtr, pointer, Bool);
58
static XF86VideoAdaptorPtr TDFXSetupImageVideoOverlay(ScreenPtr);
59
static int TDFXSetPortAttributeOverlay(ScrnInfoPtr, Atom, INT32, pointer);
60
static int TDFXGetPortAttributeOverlay(ScrnInfoPtr, Atom ,INT32 *, pointer);
61
static int TDFXPutImageOverlay(ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr);
62
static void TDFXStopVideoOverlay(ScrnInfoPtr, pointer, Bool);
63
static void TDFXResetVideoOverlay(ScrnInfoPtr);
65
static void TDFXQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer);
66
static int TDFXQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *);
68
static void TDFXInitOffscreenImages(ScreenPtr);
74
static XF86VideoEncodingRec OverlayEncoding[] =
76
{ 0, "XV_IMAGE", 2048, 2048, {1, 1} }
79
static XF86VideoEncodingRec TextureEncoding[] =
81
{ 0, "XV_IMAGE", 1024, 1024, {1, 1} }
84
static XF86VideoFormatRec OverlayFormats[] =
86
{8, TrueColor}, {8, DirectColor}, {8, PseudoColor},
87
{8, GrayScale}, {8, StaticGray}, {8, StaticColor},
88
{15, TrueColor}, {16, TrueColor}, {24, TrueColor},
89
{15, DirectColor}, {16, DirectColor}, {24, DirectColor}
92
static XF86VideoFormatRec TextureFormats[] =
94
{15, TrueColor}, {16, TrueColor}, {24, TrueColor}
97
static XF86AttributeRec OverlayAttributes[] =
99
{XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
100
{XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"}
103
static XF86AttributeRec TextureAttributes[] =
105
{XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
106
{XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"}
109
static XF86ImageRec OverlayImages[] =
111
XVIMAGE_YUY2, XVIMAGE_UYVY, XVIMAGE_YV12, XVIMAGE_I420
114
static XF86ImageRec TextureImages[] =
116
XVIMAGE_YV12, XVIMAGE_I420
120
* COMMON SETUP FUNCTIONS
123
void TDFXInitVideo(ScreenPtr pScreen)
125
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
126
XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
127
XF86VideoAdaptorPtr newAdaptor = NULL;
128
TDFXPtr pTDFX = TDFXPTR(pScrn);
131
/* The hardware can't convert YUV->8 bit color */
135
if (!pTDFX->TextureXvideo) {
136
/* Offscreen support for Overlay only */
137
TDFXInitOffscreenImages(pScreen);
139
/* Overlay adaptor */
140
newAdaptor = TDFXSetupImageVideoOverlay(pScreen);
142
/* Texture adaptor */
143
newAdaptor = TDFXSetupImageVideoTexture(pScreen);
146
num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
151
adaptors = &newAdaptor;
154
malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
156
memcpy(newAdaptors, adaptors, num_adaptors *
157
sizeof(XF86VideoAdaptorPtr));
158
newAdaptors[num_adaptors] = newAdaptor;
159
adaptors = newAdaptors;
166
xf86XVScreenInit(pScreen, adaptors, num_adaptors);
173
void TDFXCloseVideo (ScreenPtr pScreen)
178
static XF86VideoAdaptorPtr
179
TDFXAllocAdaptor(ScrnInfoPtr pScrn, int numberPorts)
181
XF86VideoAdaptorPtr adapt;
182
TDFXPtr pTDFX = TDFXPTR(pScrn);
183
TDFXPortPrivPtr pPriv;
185
if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
188
if(!(pPriv = calloc(1, sizeof(TDFXPortPrivRec) + (numberPorts * sizeof(DevUnion)))))
194
adapt->pPortPrivates = (DevUnion*)(&pPriv[1]);
195
adapt->pPortPrivates[0].ptr = (pointer)pPriv;
197
xvColorKey = MAKE_ATOM("XV_COLORKEY");
198
xvFilterQuality = MAKE_ATOM("XV_FILTER_QUALITY");
200
pPriv->colorKey = pTDFX->videoKey;
201
pPriv->videoStatus = 0;
202
pPriv->filterQuality = 1;
208
static XF86VideoAdaptorPtr
209
TDFXSetupImageVideoOverlay(ScreenPtr pScreen)
211
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
212
TDFXPtr pTDFX = TDFXPTR(pScrn);
213
TDFXPortPrivPtr pPriv;
214
XF86VideoAdaptorPtr adapt;
216
if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_OVERLAY_PORTS)))
219
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
220
adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
221
adapt->name = "3dfx Video Overlay";
222
adapt->nPorts = TDFX_MAX_OVERLAY_PORTS;
223
adapt->nEncodings = sizeof(OverlayEncoding) / sizeof(XF86VideoEncodingRec);
224
adapt->pEncodings = OverlayEncoding;
225
adapt->nFormats = sizeof(OverlayFormats) / sizeof(XF86VideoFormatRec);
226
adapt->pFormats = OverlayFormats;
227
adapt->nAttributes = sizeof(OverlayAttributes) / sizeof(XF86AttributeRec);
228
adapt->pAttributes = OverlayAttributes;
229
adapt->nImages = sizeof(OverlayImages) / sizeof(XF86ImageRec);
230
adapt->pImages = OverlayImages;
231
adapt->PutVideo = NULL;
232
adapt->PutStill = NULL;
233
adapt->GetVideo = NULL;
234
adapt->GetStill = NULL;
235
adapt->StopVideo = TDFXStopVideoOverlay;
236
adapt->SetPortAttribute = TDFXSetPortAttributeOverlay;
237
adapt->GetPortAttribute = TDFXGetPortAttributeOverlay;
238
adapt->QueryBestSize = TDFXQueryBestSize;
239
adapt->PutImage = TDFXPutImageOverlay;
240
adapt->QueryImageAttributes = TDFXQueryImageAttributes;
242
pTDFX->overlayAdaptor = adapt;
244
pPriv = (TDFXPortPrivPtr)(adapt->pPortPrivates[0].ptr);
245
REGION_NULL(pScreen, &(pPriv->clip));
247
TDFXResetVideoOverlay(pScrn);
252
static XF86VideoAdaptorPtr
253
TDFXSetupImageVideoTexture(ScreenPtr pScreen)
255
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
256
TDFXPtr pTDFX = TDFXPTR(pScrn);
257
XF86VideoAdaptorPtr adapt;
260
if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_TEXTURE_PORTS)))
263
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
264
adapt->flags = VIDEO_OVERLAID_IMAGES;
265
adapt->name = "3dfx Video Texture";
266
adapt->nPorts = TDFX_MAX_TEXTURE_PORTS;
267
adapt->nEncodings = sizeof(TextureEncoding) / sizeof(XF86VideoEncodingRec);
268
adapt->pEncodings = TextureEncoding;
269
adapt->nFormats = sizeof(TextureFormats) / sizeof(XF86VideoFormatRec);
270
adapt->pFormats = TextureFormats;
271
adapt->nAttributes = sizeof(TextureAttributes) / sizeof(XF86AttributeRec);
272
adapt->pAttributes = TextureAttributes;
273
adapt->nImages = sizeof(TextureImages) / sizeof(XF86ImageRec);
274
adapt->pImages = TextureImages;
275
adapt->PutVideo = NULL;
276
adapt->PutStill = NULL;
277
adapt->GetVideo = NULL;
278
adapt->GetStill = NULL;
279
adapt->StopVideo = TDFXStopVideoTexture;
280
adapt->SetPortAttribute = TDFXSetPortAttributeTexture;
281
adapt->GetPortAttribute = TDFXGetPortAttributeTexture;
282
adapt->QueryBestSize = TDFXQueryBestSize;
283
adapt->PutImage = TDFXPutImageTexture;
284
adapt->QueryImageAttributes = TDFXQueryImageAttributes;
286
for(i = 0; i < TDFX_MAX_TEXTURE_PORTS; i++)
287
adapt->pPortPrivates[i].val = i;
289
pTDFX->textureAdaptor = adapt;
296
* MISCELLANEOUS ROUTINES
300
TDFXQueryImageAttributes(
303
unsigned short *w, unsigned short *h,
304
int *pitches, int *offsets
308
if(*w > 1024) *w = 1024;
309
if(*h > 1024) *h = 1024;
312
if(offsets) offsets[0] = 0;
318
size = (*w + 3) & ~3;
319
if(pitches) pitches[0] = size;
321
if(offsets) offsets[1] = size;
322
tmp = ((*w >> 1) + 3) & ~3;
323
if(pitches) pitches[1] = pitches[2] = tmp;
326
if(offsets) offsets[2] = size;
333
if(pitches) pitches[0] = size;
343
TDFXSetPortAttributeOverlay(
350
TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
351
TDFXPtr pTDFX = TDFXPTR(pScrn);
353
if(attribute == xvColorKey) {
354
pPriv->colorKey = value;
355
pTDFX->writeLong(pTDFX, VIDCHROMAMIN, pPriv->colorKey);
356
pTDFX->writeLong(pTDFX, VIDCHROMAMAX, pPriv->colorKey);
357
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
358
} else if(attribute == xvFilterQuality) {
359
if((value < 0) || (value > 1))
361
pPriv->filterQuality = value;
362
} else return BadMatch;
368
TDFXGetPortAttributeOverlay(
374
TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
376
if(attribute == xvColorKey) {
377
*value = pPriv->colorKey;
378
} else if(attribute == xvFilterQuality) {
379
*value = pPriv->filterQuality;
380
} else return BadMatch;
387
TDFXSetPortAttributeTexture(
398
TDFXGetPortAttributeTexture(
412
short vid_w, short vid_h,
413
short drw_w, short drw_h,
414
unsigned int *p_w, unsigned int *p_h,
417
if(vid_w > drw_w) drw_w = vid_w;
418
if(vid_h > drw_h) drw_h = vid_h;
434
#if X_BYTE_ORDER == X_BIG_ENDIAN
439
((unsigned long *)dst)[i]=BE_WSWAP32(((unsigned long *)src)[i]);
471
for(j = 0; j < h; j++) {
473
s1 = src1; s2 = src2; s3 = src3;
476
dst[0] = BE_WSWAP32(s1[0] | (s1[1] << 16) | (s3[0] << 8) |
478
dst[1] = BE_WSWAP32(s1[2] | (s1[3] << 16) | (s3[1] << 8) |
480
dst[2] = BE_WSWAP32(s1[4] | (s1[5] << 16) | (s3[2] << 8) |
482
dst[3] = BE_WSWAP32(s1[6] | (s1[7] << 16) | (s3[3] << 8) |
484
dst += 4; s2 += 4; s3 += 4; s1 += 8;
488
dst[0] = BE_WSWAP32(s1[0] | (s1[1] << 16) | (s3[0] << 8) |
505
* TEXTURE DRAWING FUNCTIONS
510
TDFXStopVideoTexture(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
512
TDFXPtr pTDFX = TDFXPTR(pScrn);
515
if(pTDFX->textureBuffer) {
516
xf86FreeOffscreenArea(pTDFX->textureBuffer);
517
pTDFX->textureBuffer = NULL;
524
TDFXScreenToScreenYUVStretchBlit (ScrnInfoPtr pScrn,
525
short src_x1, short src_y1,
526
short src_x2, short src_y2,
527
short dst_x1, short dst_y1,
528
short dst_x2, short dst_y2)
530
TDFXPtr pTDFX = TDFXPTR(pScrn);
531
/* reformulate the paramaters the way the hardware wants them */
532
INT32 src_x = src_x1 & 0x1FFF;
533
INT32 src_y = src_y1 & 0x1FFF;
534
INT32 dst_x = dst_x1 & 0x1FFF;
535
INT32 dst_y = dst_y1 & 0x1FFF;
536
INT32 src_w = (src_x2 - src_x1) & 0x1FFF;
537
INT32 src_h = (src_y2 - src_y1) & 0x1FFF;
538
INT32 dst_w = (dst_x2 - dst_x1) & 0x1FFF;
539
INT32 dst_h = (dst_y2 - dst_y1) & 0x1FFF;
541
/* Setup for blit src and dest */
542
TDFXMakeRoom(pTDFX, 4);
543
DECLARE(SSTCP_DSTSIZE|SSTCP_SRCSIZE|SSTCP_DSTXY|SSTCP_COMMAND/*|SSTCP_COMMANDEXTRA*/);
544
/* TDFXWriteLong(pTDFX, SST_2D_COMMANDEXTRA, SST_COMMANDEXTRA_VSYNC);*/
545
TDFXWriteLong(pTDFX, SST_2D_SRCSIZE, src_w | (src_h<<16));
546
TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, dst_w | (dst_h<<16));
547
TDFXWriteLong(pTDFX, SST_2D_DSTXY, dst_x | (dst_y<<16));
548
TDFXWriteLong(pTDFX, SST_2D_COMMAND, SST_2D_SCRNTOSCRNSTRETCH | 0xCC000000);
549
/* Write to the launch area to start the blit */
550
TDFXMakeRoom(pTDFX, 1);
551
DECLARE_LAUNCH(1, 0);
552
TDFXWriteLong(pTDFX, SST_2D_LAUNCH, (src_x<<1) | (src_y<<16));
553
/* Wait for it to happen */
554
TDFXSendNOPFifo2D(pScrn);
559
YUVPlanarToPacked (ScrnInfoPtr pScrn,
560
short src_x, short src_y,
561
short src_h, short src_w,
562
int id, unsigned char *buf,
563
short width, short height,
566
TDFXPtr pTDFX = TDFXPTR(pScrn);
567
unsigned char *psrc, *pdst;
570
INT32 yuvBaseAddr, yuvStride;
572
/* Save these registers so I can restore them when we are done. */
573
yuvBaseAddr = TDFXReadLongMMIO(pTDFX, YUVBASEADDR);
574
yuvStride = TDFXReadLongMMIO(pTDFX, YUVSTRIDE);
576
/* Set yuvBaseAddress and yuvStride. */
577
baseaddr = pTDFX->fbOffset + pTDFX->cpp * fbarea->box.x1 + pTDFX->stride * fbarea->box.y1;
578
TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, pTDFX->stride);
579
TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, baseaddr);
581
/* Copy Y plane (twice as much Y as U or V) */
583
psrc += (src_x & ~0x1) + src_y * width;
584
pdst = pTDFX->MMIOBase[0] + YUV_Y_BASE;
585
TDFXCopyData(psrc, pdst, width, 1024, src_h, src_w + (src_x & 0x1));
588
psrc = buf + width * height;
589
psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1);
590
pdst = pTDFX->MMIOBase[0] + YUV_V_BASE;
591
TDFXCopyData(psrc, pdst, width >> 1, 1024, src_h >> 1, src_w >> 1);
594
psrc = buf + width * height + (width >> 1) * (height >> 1);
595
psrc += (src_x >> 1) + (src_y >> 1) * (width >> 1);
596
pdst = pTDFX->MMIOBase[0] + YUV_U_BASE;
597
TDFXCopyData(psrc, pdst, width >> 1, 1024, src_h >> 1, src_w >> 1);
599
/* IDLE until the copy finished, timeout for safety */
600
for (count = 0; count < 1000; count++)
601
if (!((TDFXReadLongMMIO(pTDFX, STATUS) & SST_BUSY)))
604
/* Restore trashed registers */
605
TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, yuvBaseAddr);
606
TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, yuvStride);
608
/* Wait for it to happen */
609
TDFXSendNOPFifo2D(pScrn);
616
short src_x, short src_y,
617
short drw_x, short drw_y,
618
short src_w, short src_h,
619
short drw_w, short drw_h,
620
int id, unsigned char* buf,
621
short width, short height,
623
RegionPtr clipBoxes, pointer data,
627
TDFXPtr pTDFX = TDFXPTR(pScrn);
632
TDFXTRACE("TDFXPutImageTexture(src_x=%d, src_y=%d, drw_x=%d, drw_y=%d, .. sync=%d\n",
633
src_x, src_y, drw_x, drw_y, sync);
635
/* Check the source format */
636
if (id == FOURCC_YV12) format = SST_2D_FORMAT_YUYV;
637
else if (id == FOURCC_UYVY) format = SST_2D_FORMAT_UYVY;
638
else return BadAlloc;
640
/* Get a buffer to store the packed YUV data */
641
if (!(pTDFX->textureBuffer = TDFXAllocateMemoryArea(pScrn, pTDFX->textureBuffer, src_w, src_h)))
644
/* Pack the YUV data in offscreen memory using YUV framebuffer (0x[CDE]0000) */
645
YUVPlanarToPacked (pScrn, src_x, src_y, src_h, src_w,
646
id, buf, width, height,
647
pTDFX->textureBuffer);
649
/* Setup source and destination pixel formats (yuv -> rgb) */
650
TDFXMakeRoom(pTDFX, 2);
651
DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
652
TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->stride|((pTDFX->cpp+1)<<16));
653
TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->stride|((format)<<16));
655
/* Blit packed YUV data from offscreen memory, respecting clips */
656
#define SRC_X1 (pTDFX->textureBuffer->box.x1)
657
#define SRC_Y1 (pTDFX->textureBuffer->box.y1)
658
#define SCALEX(dx) ((int)(((dx) * src_w) / drw_w))
659
#define SCALEY(dy) ((int)(((dy) * src_h) / drw_h))
660
for (nbox = REGION_NUM_RECTS(clipBoxes),
661
pbox = REGION_RECTS(clipBoxes); nbox > 0; nbox--, pbox++)
663
TDFXScreenToScreenYUVStretchBlit (pScrn,
664
SRC_X1 + SCALEX(pbox->x1 - drw_x),
665
SRC_Y1 + SCALEY(pbox->y1 - drw_y),
666
SRC_X1 + SCALEX(pbox->x2 - drw_x),
667
SRC_Y1 + SCALEY(pbox->y2 - drw_y),
672
/* Restore the WAX registers we trashed */
673
TDFXMakeRoom(pTDFX, 2);
674
DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
675
TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, pTDFX->sst2DDstFmtShadow);
676
TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, pTDFX->sst2DSrcFmtShadow);
678
/* Wait for it to happen */
679
TDFXSendNOPFifo2D(pScrn);
686
* OVERLAY DRAWING FUNCTIONS
691
TDFXResetVideoOverlay(ScrnInfoPtr pScrn)
693
TDFXPtr pTDFX = TDFXPTR(pScrn);
694
TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
696
/* reset the video */
697
pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
698
pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
699
pTDFX->writeLong(pTDFX, RGBMAXDELTA, 0x0080808);
700
pTDFX->writeLong(pTDFX, VIDCHROMAMIN, pPriv->colorKey);
701
pTDFX->writeLong(pTDFX, VIDCHROMAMAX, pPriv->colorKey);
706
TDFXStopVideoOverlay(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
708
TDFXPtr pTDFX = TDFXPTR(pScrn);
709
TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
711
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
714
if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
715
pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
716
pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
718
if(pTDFX->overlayBuffer) {
719
xf86FreeOffscreenLinear(pTDFX->overlayBuffer);
720
pTDFX->overlayBuffer = NULL;
722
if(pTDFX->overlayBuffer2) {
723
xf86FreeOffscreenLinear(pTDFX->overlayBuffer2);
724
pTDFX->overlayBuffer2 = NULL;
726
pPriv->videoStatus = 0;
728
if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
729
pPriv->videoStatus |= OFF_TIMER;
730
pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
740
VIDPROCCFG: 0x5c: Video Processor Configuration register
742
#define VIDPROCCFGMASK 0xa2e3eb6c
744
10987654321098765432109876543210
745
10100010111000111110101101101100
747
The "1" bits are the bits cleared to 0 in pTDFX->ModeReg.vidcfg
756
bit 11=0: Do not bypass clut (colour lookup) for overlay
757
bit 10=0: Do not bypass clut for desktop
758
bit 9=1: use video-in buffer address as overlay start
759
address (auto-flipping)
760
bit 8=1: fetch overlay surface
761
bit 7=0: do not fetch the desktop surface (?)
762
bit 6=0: chromakey not inverted
763
bit 5=1: chromakey enabled
764
bit 4=0: half-mode disabled
765
bit 3=0: not interlaced (interlace doesn't work on Avenger)
766
bit 2=0: overlay stereo disabled
767
bit 1=0: Windows cursor mode
768
bit 0=0: Video processor off, VGA mode on
770
SST_VIDEO_2X_MODE_EN: bit26: means 2 pixels per screen clock mode is on
772
VIDOVERLAYSTARTCOORDS: x&y coords of overlay on the screen
773
VIDOVERLAYENDSCREENCOORDS: x&y coorder of bot-right of overlay on the screen
774
VIDOVERLAYDUDX: step size in source per hoz step in screen space (x-mag)
775
VIDOVERLAYDUDXOFFSETSRCWIDTH:
776
VIDOVERLAYDVDY: step size in sourcxe per vertical step in screen (y-mag)
777
VIDOVERLAYDVDYOFFSET: initial offset of DVDY
778
VIDDESKTOPOVERLAYSTRIDE: desktop surface stride
780
SST_3D_LEFTOVERLAYBUF: starting physical address of the overlay surface buffer
781
VIDINADDR0: starting address of video-in buffer-0
782
[this is set, but this is for video _input_ as I understand docs...?]
787
TDFXDisplayVideoOverlay(
791
short width, short height,
793
int left, int right, int top,
795
short src_w, short src_h,
796
short drw_w, short drw_h
798
TDFXPtr pTDFX = TDFXPTR(pScrn);
799
TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
802
dudx = (src_w << 20) / drw_w;
803
/* subtract 1 to eliminate garbage on last line */
804
dvdy = (( src_h - 1 )<< 20) / drw_h;
806
offset += ((left >> 16) & ~1) << 1;
807
left = (left & 0x0001ffff) << 3;
809
pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
810
pTDFX->ModeReg.vidcfg |= 0x00000320;
812
if(drw_w != src_w) pTDFX->ModeReg.vidcfg |= (1 << 14);
813
if(drw_h != src_h) pTDFX->ModeReg.vidcfg |= (1 << 15);
814
if(id == FOURCC_UYVY) pTDFX->ModeReg.vidcfg |= (6 << 21);
815
else pTDFX->ModeReg.vidcfg |= (5 << 21);
816
if(pScrn->depth == 8) pTDFX->ModeReg.vidcfg |= (1 << 11);
817
/* can't do bilinear filtering when in 2X mode */
818
if(pPriv->filterQuality && !(pTDFX->ModeReg.vidcfg & SST_VIDEO_2X_MODE_EN))
819
pTDFX->ModeReg.vidcfg |= (3 << 16);
820
pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
822
pTDFX->writeLong(pTDFX, VIDOVERLAYSTARTCOORDS, dstBox->x1 | (dstBox->y1 << 12));
823
pTDFX->writeLong(pTDFX, VIDOVERLAYENDSCREENCOORDS, (dstBox->x2 - 1) | ((dstBox->y2 - 1) << 12));
824
pTDFX->writeLong(pTDFX, VIDOVERLAYDUDX, dudx);
825
pTDFX->writeLong(pTDFX, VIDOVERLAYDUDXOFFSETSRCWIDTH, left | (src_w << 20));
826
pTDFX->writeLong(pTDFX, VIDOVERLAYDVDY, dvdy);
827
pTDFX->writeLong(pTDFX, VIDOVERLAYDVDYOFFSET, (top & 0x0000ffff) << 3);
829
pTDFX->ModeReg.stride &= 0x0000ffff;
830
pTDFX->ModeReg.stride |= pitch << 16;
831
pTDFX->writeLong(pTDFX, VIDDESKTOPOVERLAYSTRIDE, pTDFX->ModeReg.stride);
832
pTDFX->writeLong(pTDFX, SST_3D_LEFTOVERLAYBUF, offset & ~3);
833
pTDFX->writeLong(pTDFX, VIDINADDR0, offset & ~3);
834
TDFXTRACE("TDFXDisplayVideoOverlay: done, offset=0x%x\n", offset);
842
TDFXSwapVideoOverlayBuffer tries to use the Avenger SWAPBUFFER
843
capability to change frames without tearing.
845
Use this in preference to TDFXDisplayVideoOverlay where all image
846
parameters are the same as the previous frame - ie where only the
847
SST_3D_LEFTOVERLAYBUF register would have been changed.
849
NOTE: Work in progress - doesn't seem to sync to VSYNC, and only every
850
other frame gets displayed...
852
Seeing that the buffer swap initiated by DisplayVideoOverlay gets
853
synced to VSYNC anyway, just adding double-buffering to PutImageOverlay
854
appears to do the job. Still - I leave this code in in case we can
857
-- Steve Davies 2002-10-04
858
-- <steve@daviesfam.org>
863
TDFXSwapVideoOverlayBuffer(
868
TDFXPtr pTDFX = TDFXPTR(pScrn);
869
offset += ((left >> 16) & ~1) << 1;
870
/* Write mew buffer address */
871
pTDFX->writeLong(pTDFX, SST_3D_LEFTOVERLAYBUF, offset & ~3);
872
/* Incremement the swap-pending counter */
873
pTDFX->writeLong(pTDFX, SST_3D_SWAPPENDING, 0);
874
/* write the swapbuffer command - triggered by (next) VSYNC */
875
pTDFX->writeLong(pTDFX, SST_3D_SWAPBUFFERCMD, 1);
883
short src_x, short src_y,
884
short drw_x, short drw_y,
885
short src_w, short src_h,
886
short drw_w, short drw_h,
887
int id, unsigned char* buf,
888
short width, short height,
890
RegionPtr clipBoxes, pointer data,
893
TDFXPtr pTDFX = TDFXPTR(pScrn);
894
TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
895
INT32 xa, xb, ya, yb;
896
unsigned char *dst_start;
897
int new_size, offset;
898
int s2offset = 0, s3offset = 0;
899
int srcPitch = 0, srcPitch2 = 0;
901
int top, left, npixels, nlines, bpp;
905
TDFXTRACE("TDFXPutImageOverlay: src_x=%d, src_y=%d, drw_x=%d, drw_y=%d, src_w=%d, src_h=%d, drw_w=%d, drw_h=%d, id=%d, width=%d, height=%d, sync=%d\n",
906
src_x, src_y, drw_x, drw_y, src_w, src_h, drw_w, drw_h, id, width, height, Sync);
909
* s2offset, s3offset - byte offsets into U and V plane of the
910
* source where copying starts. Y plane is
911
* done by editing "buf".
913
* offset - byte offset to the first line of the destination.
915
* dst_start - byte address to the first displayed pel.
919
if(src_w > drw_w) drw_w = src_w;
920
if(src_h > drw_h) drw_h = src_h;
929
dstBox.x2 = drw_x + drw_w;
931
dstBox.y2 = drw_y + drw_h;
933
if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb,
934
clipBoxes, width, height))
937
dstBox.x1 -= pScrn->frameX0;
938
dstBox.x2 -= pScrn->frameX0;
939
dstBox.y1 -= pScrn->frameY0;
940
dstBox.y2 -= pScrn->frameY0;
942
bpp = pScrn->bitsPerPixel >> 3;
947
dstPitch = ((width << 1) + 3) & ~3;
948
new_size = ((dstPitch * height) + bpp - 1) / bpp;
949
srcPitch = (width + 3) & ~3;
950
s2offset = srcPitch * height;
951
srcPitch2 = ((width >> 1) + 3) & ~3;
952
s3offset = (srcPitch2 * (height >> 1)) + s2offset;
957
dstPitch = ((width << 1) + 3) & ~3;
958
new_size = ((dstPitch * height) + bpp - 1) / bpp;
959
srcPitch = (width << 1);
963
if(!(pTDFX->overlayBuffer = TDFXAllocateMemoryLinear(pScrn, pTDFX->overlayBuffer, new_size)))
965
/* Second buffer for double-buffering (If we can't get the memory then we just don't double-buffer) */
966
if (!(pTDFX->overlayBuffer2 = TDFXAllocateMemoryLinear(pScrn, pTDFX->overlayBuffer2, new_size)))
967
pTDFX->whichOverlayBuffer = 0;
968
TDFXTRACE("TDFXPutImageOverlay: %s have a second overlay buffer for double-buffering\n",
969
pTDFX->overlayBuffer2 ? "Do" : "Do not");
973
left = (xa >> 16) & ~1;
974
npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left;
976
/* Get buffer offset */
977
if (pTDFX->whichOverlayBuffer == 0)
978
offset = (pTDFX->overlayBuffer->offset * bpp) + (top * dstPitch) + pTDFX->fbOffset;
980
offset = (pTDFX->overlayBuffer2->offset * bpp) + (top * dstPitch) + pTDFX->fbOffset;
982
/* Flip to other buffer for next time */
983
pTDFX->whichOverlayBuffer ^= 1;
985
dst_start = pTDFX->FbBase + offset;
991
dst_start += left << 1;
992
tmp = ((top >> 1) * srcPitch2) + (left >> 1);
995
if(id == FOURCC_I420) {
1000
nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top;
1001
TDFXTRACE("TDFXPutImageOverlay: using copymungeddata\n");
1002
TDFXCopyMungedData(buf + (top * srcPitch) + left, buf + s2offset,
1003
buf + s3offset, dst_start, srcPitch, srcPitch2,
1004
dstPitch, nlines, npixels);
1010
buf += (top * srcPitch) + left;
1011
nlines = ((yb + 0xffff) >> 16) - top;
1013
TDFXTRACE("TDFXPutImageOverlay: using copydata\n");
1014
TDFXCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
1018
if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
1019
REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
1020
xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
1023
TDFXDisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
1025
pPriv->videoStatus = CLIENT_VIDEO_ON;
1027
pTDFX->VideoTimerCallback = TDFXVideoTimerCallback;
1029
/* Display some swap-buffer related info...: vidCurrOverlayStartAddr, fbiSwapHistory */
1030
/* To give us some insight into workings or otherwise of swapbuffer stuff */
1031
TDFXTRACE("TDFXPutImageOverlay: vidCurrOverlayStrtAdr=%x, fbiSwpHist=%x, whchBuf=%d, 3Dstus=%x\n",
1032
pTDFX->readLong(pTDFX, VIDCUROVERLAYSTARTADDR),
1033
pTDFX->readLong(pTDFX, SST_3D_FBISWAPHISTORY),
1034
pTDFX->whichOverlayBuffer,
1035
pTDFX->readLong(pTDFX, SST_3D_STATUS)
1043
TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time)
1045
TDFXPtr pTDFX = TDFXPTR(pScrn);
1046
TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
1048
if(pPriv->videoStatus & TIMER_MASK) {
1049
if(pPriv->videoStatus & OFF_TIMER) {
1050
if(pPriv->offTime < time) {
1051
pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
1052
pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
1053
pPriv->videoStatus = FREE_TIMER;
1054
pPriv->freeTime = time + FREE_DELAY;
1057
if(pPriv->videoStatus & FREE_TIMER) {
1058
if(pPriv->freeTime < time) {
1059
if(pTDFX->overlayBuffer) {
1060
xf86FreeOffscreenLinear(pTDFX->overlayBuffer);
1061
pTDFX->overlayBuffer = NULL;
1063
if(pTDFX->overlayBuffer2) {
1064
xf86FreeOffscreenLinear(pTDFX->overlayBuffer2);
1065
pTDFX->overlayBuffer2 = NULL;
1067
pPriv->videoStatus = 0;
1068
pTDFX->VideoTimerCallback = NULL;
1071
} else /* shouldn't get here */
1072
pTDFX->VideoTimerCallback = NULL;
1082
TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height)
1084
TDFXPtr pTDFX = TDFXPTR(pScrn);
1089
if ((area->box.x2 - area->box.x1 >= width) &&
1090
(area->box.y2 - area->box.y1 >= height))
1093
if (xf86ResizeOffscreenArea(area, width, height))
1096
xf86FreeOffscreenArea(area);
1099
pScreen = xf86ScrnToScreen(pScrn);
1101
new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL);
1104
int max_width, max_height;
1106
xf86QueryLargestOffscreenArea(pScreen, &max_width, &max_height, pTDFX->cpp, 0, PRIORITY_EXTREME);
1108
if (max_width < width || max_height < height)
1111
xf86PurgeUnlockedOffscreenAreas(pScreen);
1112
new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL);
1120
TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
1123
FBLinearPtr new_linear;
1126
if(linear->size >= size)
1129
if(xf86ResizeOffscreenLinear(linear, size))
1132
xf86FreeOffscreenLinear(linear);
1135
pScreen = xf86ScrnToScreen(pScrn);
1137
new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
1142
xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, PRIORITY_EXTREME);
1147
xf86PurgeUnlockedOffscreenAreas(pScreen);
1148
new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
1154
/****************** Offscreen stuff ***************/
1159
} OffscreenPrivRec, * OffscreenPrivPtr;
1162
TDFXAllocateSurface(
1167
XF86SurfacePtr surface
1169
TDFXPtr pTDFX = TDFXPTR(pScrn);
1171
int pitch, size, bpp;
1172
OffscreenPrivPtr pPriv;
1174
if((w > 2048) || (h > 2048))
1178
pitch = ((w << 1) + 15) & ~15;
1179
bpp = pScrn->bitsPerPixel >> 3;
1180
size = ((pitch * h) + bpp - 1) / bpp;
1182
if(!(linear = TDFXAllocateMemoryLinear(pScrn, NULL, size)))
1186
surface->height = h;
1188
if(!(surface->pitches = malloc(sizeof(int)))) {
1189
xf86FreeOffscreenLinear(linear);
1192
if(!(surface->offsets = malloc(sizeof(int)))) {
1193
free(surface->pitches);
1194
xf86FreeOffscreenLinear(linear);
1197
if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
1198
free(surface->pitches);
1199
free(surface->offsets);
1200
xf86FreeOffscreenLinear(linear);
1204
pPriv->linear = linear;
1205
pPriv->isOn = FALSE;
1207
surface->pScrn = pScrn;
1209
surface->pitches[0] = pitch;
1210
surface->offsets[0] = pTDFX->fbOffset + (linear->offset * bpp);
1211
surface->devPrivate.ptr = (pointer)pPriv;
1218
XF86SurfacePtr surface
1220
OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1223
TDFXPtr pTDFX = TDFXPTR(surface->pScrn);
1224
pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
1225
pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
1226
pPriv->isOn = FALSE;
1235
XF86SurfacePtr surface
1237
OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1240
TDFXStopSurface(surface);
1241
xf86FreeOffscreenLinear(pPriv->linear);
1242
free(surface->pitches);
1243
free(surface->offsets);
1244
free(surface->devPrivate.ptr);
1250
TDFXGetSurfaceAttribute(
1255
return TDFXGetPortAttributeOverlay(pScrn, attribute, value,
1256
(pointer)(GET_PORT_PRIVATE(pScrn)));
1260
TDFXSetSurfaceAttribute(
1265
return TDFXSetPortAttributeOverlay(pScrn, attribute, value,
1266
(pointer)(GET_PORT_PRIVATE(pScrn)));
1271
XF86SurfacePtr surface,
1272
short src_x, short src_y,
1273
short drw_x, short drw_y,
1274
short src_w, short src_h,
1275
short drw_w, short drw_h,
1278
OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1279
ScrnInfoPtr pScrn = surface->pScrn;
1280
TDFXPtr pTDFX = TDFXPTR(pScrn);
1281
TDFXPortPrivPtr portPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
1282
INT32 x1, y1, x2, y2;
1291
dstBox.x2 = drw_x + drw_w;
1293
dstBox.y2 = drw_y + drw_h;
1295
if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
1296
surface->width, surface->height))
1301
dstBox.x1 -= pScrn->frameX0;
1302
dstBox.x2 -= pScrn->frameX0;
1303
dstBox.y1 -= pScrn->frameY0;
1304
dstBox.y2 -= pScrn->frameY0;
1307
TDFXResetVideoOverlay(pScrn);
1310
TDFXDisplayVideoOverlay(pScrn, surface->id, surface->offsets[0],
1311
surface->width, surface->height, surface->pitches[0],
1312
x1, y1, x2, &dstBox, src_w, src_h, drw_w, drw_h);
1314
xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
1317
/* we've prempted the XvImage stream so set its free timer */
1318
if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
1319
REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
1320
UpdateCurrentTime();
1321
portPriv->videoStatus = FREE_TIMER;
1322
portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
1323
pTDFX->VideoTimerCallback = TDFXVideoTimerCallback;
1330
TDFXInitOffscreenImages(ScreenPtr pScreen)
1332
XF86OffscreenImagePtr offscreenImages;
1334
/* need to free this someplace */
1335
if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec))))
1338
offscreenImages[0].image = &OverlayImages[0];
1339
offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES |
1340
VIDEO_CLIP_TO_VIEWPORT;
1341
offscreenImages[0].alloc_surface = TDFXAllocateSurface;
1342
offscreenImages[0].free_surface = TDFXFreeSurface;
1343
offscreenImages[0].display = TDFXDisplaySurface;
1344
offscreenImages[0].stop = TDFXStopSurface;
1345
offscreenImages[0].setAttribute = TDFXSetSurfaceAttribute;
1346
offscreenImages[0].getAttribute = TDFXGetSurfaceAttribute;
1347
offscreenImages[0].max_width = 2048;
1348
offscreenImages[0].max_height = 2048;
1349
offscreenImages[0].num_attributes = 2;
1350
offscreenImages[0].attributes = OverlayAttributes;
1352
xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);