~ubuntu-branches/ubuntu/precise/xserver-xorg-video-tdfx-lts-quantal/precise-proposed

« back to all changes in this revision

Viewing changes to src/tdfx_video.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2012-11-30 21:00:30 UTC
  • Revision ID: package-import@ubuntu.com-20121130210030-z6cpk5qrun266ihv
Tags: upstream-1.4.5
ImportĀ upstreamĀ versionĀ 1.4.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#ifdef HAVE_CONFIG_H
 
3
#include "config.h"
 
4
#endif
 
5
 
 
6
#include "xf86.h"
 
7
#include "tdfx.h"
 
8
#include "dixstruct.h"
 
9
 
 
10
#include <X11/extensions/Xv.h>
 
11
#include "fourcc.h"
 
12
 
 
13
static Atom xvColorKey, xvFilterQuality;
 
14
 
 
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
 
19
 
 
20
#define SST_2D_FORMAT_YUYV      0x8
 
21
#define SST_2D_FORMAT_UYVY      0x9
 
22
 
 
23
#define YUVBASEADDR             0x80100
 
24
#define YUVSTRIDE               0x80104
 
25
#define VIDPROCCFGMASK          0xa2e3eb6c
 
26
 
 
27
#define OFF_DELAY               250  /* milliseconds */
 
28
#define FREE_DELAY              15000
 
29
 
 
30
#define OFF_TIMER               0x01
 
31
#define FREE_TIMER              0x02
 
32
#define CLIENT_VIDEO_ON         0x04
 
33
#define TIMER_MASK              (OFF_TIMER | FREE_TIMER)
 
34
 
 
35
#define TDFX_MAX_OVERLAY_PORTS  1
 
36
#define TDFX_MAX_TEXTURE_PORTS  32
 
37
 
 
38
#define GET_PORT_PRIVATE(pScrn) \
 
39
   (TDFXPortPrivPtr)((TDFXPTR(pScrn))->overlayAdaptor->pPortPrivates[0].ptr)
 
40
 
 
41
/* Needed for attribute atoms */
 
42
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
 
43
 
 
44
/*
 
45
 * PROTOTYPES
 
46
 */
 
47
 
 
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);
 
51
 
 
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);
 
57
 
 
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);
 
64
 
 
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 *);
 
67
 
 
68
static void TDFXInitOffscreenImages(ScreenPtr);
 
69
 
 
70
/*
 
71
 * ADAPTOR INFORMATION
 
72
 */
 
73
 
 
74
static XF86VideoEncodingRec OverlayEncoding[] =
 
75
{
 
76
   { 0, "XV_IMAGE", 2048, 2048, {1, 1} }
 
77
};
 
78
 
 
79
static XF86VideoEncodingRec TextureEncoding[] =
 
80
{
 
81
   { 0, "XV_IMAGE", 1024, 1024, {1, 1} }
 
82
};
 
83
 
 
84
static XF86VideoFormatRec OverlayFormats[] = 
 
85
{
 
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}
 
90
};
 
91
 
 
92
static XF86VideoFormatRec TextureFormats[] = 
 
93
{
 
94
   {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
 
95
};
 
96
 
 
97
static XF86AttributeRec OverlayAttributes[] =
 
98
{
 
99
   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
 
100
   {XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"}
 
101
};
 
102
 
 
103
static XF86AttributeRec TextureAttributes[] =
 
104
{
 
105
   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
 
106
   {XvSettable | XvGettable, 0, 1, "XV_FILTER_QUALITY"}
 
107
};
 
108
 
 
109
static XF86ImageRec OverlayImages[] =
 
110
{
 
111
  XVIMAGE_YUY2, XVIMAGE_UYVY, XVIMAGE_YV12, XVIMAGE_I420
 
112
};
 
113
 
 
114
static XF86ImageRec TextureImages[] =
 
115
{
 
116
  XVIMAGE_YV12, XVIMAGE_I420
 
117
};
 
118
 
 
119
/*
 
120
 * COMMON SETUP FUNCTIONS
 
121
 */
 
122
 
 
123
void TDFXInitVideo(ScreenPtr pScreen)
 
124
{
 
125
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 
126
    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
 
127
    XF86VideoAdaptorPtr newAdaptor = NULL;
 
128
    TDFXPtr pTDFX = TDFXPTR(pScrn);
 
129
    int num_adaptors;
 
130
 
 
131
    /* The hardware can't convert YUV->8 bit color */
 
132
    if(pTDFX->cpp == 1)
 
133
      return;
 
134
    
 
135
    if (!pTDFX->TextureXvideo) {
 
136
        /* Offscreen support for Overlay only */
 
137
        TDFXInitOffscreenImages(pScreen);
 
138
 
 
139
        /* Overlay adaptor */
 
140
        newAdaptor = TDFXSetupImageVideoOverlay(pScreen);
 
141
    } else {
 
142
        /* Texture adaptor */
 
143
        newAdaptor = TDFXSetupImageVideoTexture(pScreen);
 
144
    }
 
145
 
 
146
    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
 
147
 
 
148
    if(newAdaptor) {
 
149
        if (!num_adaptors) {
 
150
            num_adaptors = 1;
 
151
            adaptors = &newAdaptor;
 
152
        } else {
 
153
            newAdaptors = 
 
154
                malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
 
155
            if(newAdaptors) {
 
156
                memcpy(newAdaptors, adaptors, num_adaptors * 
 
157
                                                sizeof(XF86VideoAdaptorPtr));
 
158
                newAdaptors[num_adaptors] = newAdaptor;
 
159
                adaptors = newAdaptors;
 
160
                num_adaptors++;
 
161
            }
 
162
        }
 
163
    }
 
164
 
 
165
    if(num_adaptors)
 
166
        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
 
167
 
 
168
    if(newAdaptors)
 
169
        free(newAdaptors);
 
170
}
 
171
 
 
172
 
 
173
void TDFXCloseVideo (ScreenPtr pScreen)
 
174
{
 
175
}
 
176
 
 
177
 
 
178
static XF86VideoAdaptorPtr
 
179
TDFXAllocAdaptor(ScrnInfoPtr pScrn, int numberPorts)
 
180
{
 
181
    XF86VideoAdaptorPtr adapt;
 
182
    TDFXPtr pTDFX = TDFXPTR(pScrn);
 
183
    TDFXPortPrivPtr pPriv;
 
184
 
 
185
    if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
 
186
        return NULL;
 
187
 
 
188
    if(!(pPriv = calloc(1, sizeof(TDFXPortPrivRec) + (numberPorts * sizeof(DevUnion)))))
 
189
    {
 
190
        free(adapt);
 
191
        return NULL;
 
192
    }
 
193
 
 
194
    adapt->pPortPrivates = (DevUnion*)(&pPriv[1]);
 
195
    adapt->pPortPrivates[0].ptr = (pointer)pPriv;
 
196
 
 
197
    xvColorKey = MAKE_ATOM("XV_COLORKEY");
 
198
    xvFilterQuality = MAKE_ATOM("XV_FILTER_QUALITY");
 
199
 
 
200
    pPriv->colorKey = pTDFX->videoKey;
 
201
    pPriv->videoStatus = 0;
 
202
    pPriv->filterQuality = 1;
 
203
  
 
204
    return adapt;
 
205
}
 
206
 
 
207
 
 
208
static XF86VideoAdaptorPtr
 
209
TDFXSetupImageVideoOverlay(ScreenPtr pScreen)
 
210
{
 
211
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 
212
    TDFXPtr pTDFX = TDFXPTR(pScrn);
 
213
    TDFXPortPrivPtr pPriv;
 
214
    XF86VideoAdaptorPtr adapt;
 
215
 
 
216
    if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_OVERLAY_PORTS)))
 
217
        return NULL;
 
218
 
 
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;
 
241
 
 
242
    pTDFX->overlayAdaptor = adapt;
 
243
 
 
244
    pPriv = (TDFXPortPrivPtr)(adapt->pPortPrivates[0].ptr);
 
245
    REGION_NULL(pScreen, &(pPriv->clip));
 
246
 
 
247
    TDFXResetVideoOverlay(pScrn);
 
248
 
 
249
    return adapt;
 
250
}
 
251
 
 
252
static XF86VideoAdaptorPtr
 
253
TDFXSetupImageVideoTexture(ScreenPtr pScreen)
 
254
{
 
255
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 
256
    TDFXPtr pTDFX = TDFXPTR(pScrn);
 
257
    XF86VideoAdaptorPtr adapt;
 
258
    int i;
 
259
 
 
260
    if(!(adapt = TDFXAllocAdaptor(pScrn, TDFX_MAX_TEXTURE_PORTS)))
 
261
        return NULL;
 
262
 
 
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;
 
285
 
 
286
    for(i = 0; i < TDFX_MAX_TEXTURE_PORTS; i++)
 
287
        adapt->pPortPrivates[i].val = i;
 
288
 
 
289
    pTDFX->textureAdaptor = adapt;
 
290
 
 
291
    return adapt;
 
292
}
 
293
 
 
294
 
 
295
/*
 
296
 * MISCELLANEOUS ROUTINES
 
297
 */
 
298
 
 
299
static int
 
300
TDFXQueryImageAttributes(
 
301
    ScrnInfoPtr pScrn,
 
302
    int id,
 
303
    unsigned short *w, unsigned short *h,
 
304
    int *pitches, int *offsets
 
305
){
 
306
    int size, tmp;
 
307
 
 
308
    if(*w > 1024) *w = 1024;
 
309
    if(*h > 1024) *h = 1024;
 
310
 
 
311
    *w = (*w + 1) & ~1;
 
312
    if(offsets) offsets[0] = 0;
 
313
 
 
314
    switch(id) {
 
315
    case FOURCC_YV12:
 
316
    case FOURCC_I420:
 
317
        *h = (*h + 1) & ~1;
 
318
        size = (*w + 3) & ~3;
 
319
        if(pitches) pitches[0] = size;
 
320
        size *= *h;
 
321
        if(offsets) offsets[1] = size;
 
322
        tmp = ((*w >> 1) + 3) & ~3;
 
323
        if(pitches) pitches[1] = pitches[2] = tmp;
 
324
        tmp *= (*h >> 1);
 
325
        size += tmp;
 
326
        if(offsets) offsets[2] = size;
 
327
        size += tmp;
 
328
        break;
 
329
    case FOURCC_UYVY:
 
330
    case FOURCC_YUY2:
 
331
    default:
 
332
        size = *w << 1;
 
333
        if(pitches) pitches[0] = size;
 
334
        size *= *h;
 
335
        break;
 
336
    }
 
337
 
 
338
    return size;
 
339
}
 
340
 
 
341
 
 
342
static int
 
343
TDFXSetPortAttributeOverlay(
 
344
  ScrnInfoPtr pScrn,
 
345
  Atom attribute,
 
346
  INT32 value,
 
347
  pointer data
 
348
){
 
349
 
 
350
  TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
 
351
  TDFXPtr pTDFX = TDFXPTR(pScrn);
 
352
 
 
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))
 
360
           return BadValue;
 
361
        pPriv->filterQuality = value;
 
362
  } else return BadMatch;
 
363
 
 
364
  return Success;
 
365
}
 
366
 
 
367
static int
 
368
TDFXGetPortAttributeOverlay(
 
369
  ScrnInfoPtr pScrn,
 
370
  Atom attribute,
 
371
  INT32 *value,
 
372
  pointer data
 
373
){
 
374
  TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
 
375
 
 
376
  if(attribute == xvColorKey) {
 
377
        *value = pPriv->colorKey;
 
378
  } else if(attribute == xvFilterQuality) {
 
379
        *value = pPriv->filterQuality;
 
380
  } else return BadMatch;
 
381
 
 
382
  return Success;
 
383
}
 
384
 
 
385
 
 
386
static int 
 
387
TDFXSetPortAttributeTexture(
 
388
  ScrnInfoPtr pScrn, 
 
389
  Atom attribute,
 
390
  INT32 value, 
 
391
  pointer data
 
392
) {
 
393
  return Success;
 
394
}
 
395
 
 
396
 
 
397
static int 
 
398
TDFXGetPortAttributeTexture(
 
399
  ScrnInfoPtr pScrn, 
 
400
  Atom attribute,
 
401
  INT32 *value, 
 
402
  pointer data
 
403
){
 
404
  return Success;
 
405
}
 
406
 
 
407
 
 
408
static void
 
409
TDFXQueryBestSize(
 
410
  ScrnInfoPtr pScrn,
 
411
  Bool motion,
 
412
  short vid_w, short vid_h,
 
413
  short drw_w, short drw_h,
 
414
  unsigned int *p_w, unsigned int *p_h,
 
415
  pointer data
 
416
){
 
417
   if(vid_w > drw_w) drw_w = vid_w;
 
418
   if(vid_h > drw_h) drw_h = vid_h;
 
419
   
 
420
  *p_w = drw_w;
 
421
  *p_h = drw_h;
 
422
}
 
423
 
 
424
 
 
425
static void
 
426
TDFXCopyData(
 
427
  unsigned char *src,
 
428
  unsigned char *dst,
 
429
  int srcPitch,
 
430
  int dstPitch,
 
431
  int h,
 
432
  int w
 
433
){
 
434
#if X_BYTE_ORDER == X_BIG_ENDIAN
 
435
    w >>= 1;
 
436
    while(h--) {
 
437
      int i;
 
438
      for (i=0; i<w; i++)
 
439
       ((unsigned long *)dst)[i]=BE_WSWAP32(((unsigned long *)src)[i]);
 
440
       src += srcPitch;
 
441
       dst += dstPitch;
 
442
    }
 
443
#else
 
444
     w <<= 1;
 
445
     while(h--) {
 
446
        memcpy(dst, src, w);
 
447
        src += srcPitch;
 
448
        dst += dstPitch;
 
449
     }
 
450
#endif
 
451
}
 
452
 
 
453
static void
 
454
TDFXCopyMungedData(
 
455
   unsigned char *src1,
 
456
   unsigned char *src2,
 
457
   unsigned char *src3,
 
458
   unsigned char *dst1,
 
459
   int srcPitch,
 
460
   int srcPitch2,
 
461
   int dstPitch,
 
462
   int h,
 
463
   int w
 
464
){
 
465
   CARD32 *dst;
 
466
   CARD8 *s1, *s2, *s3;
 
467
   int i, j;
 
468
 
 
469
   w >>= 1;
 
470
 
 
471
   for(j = 0; j < h; j++) {
 
472
        dst = (CARD32*)dst1;
 
473
        s1 = src1;  s2 = src2;  s3 = src3;
 
474
        i = w;
 
475
        while(i > 4) {
 
476
           dst[0] = BE_WSWAP32(s1[0] | (s1[1] << 16) | (s3[0] << 8) |
 
477
                        (s2[0] << 24));
 
478
           dst[1] = BE_WSWAP32(s1[2] | (s1[3] << 16) | (s3[1] << 8) |
 
479
                        (s2[1] << 24));
 
480
           dst[2] = BE_WSWAP32(s1[4] | (s1[5] << 16) | (s3[2] << 8) |
 
481
                        (s2[2] << 24));
 
482
           dst[3] = BE_WSWAP32(s1[6] | (s1[7] << 16) | (s3[3] << 8) |
 
483
                        (s2[3] << 24));
 
484
           dst += 4; s2 += 4; s3 += 4; s1 += 8;
 
485
           i -= 4;
 
486
        }
 
487
        while(i--) {
 
488
           dst[0] = BE_WSWAP32(s1[0] | (s1[1] << 16) | (s3[0] << 8) |
 
489
                                (s2[0] << 24));
 
490
           dst++; s2++; s3++;
 
491
           s1 += 2;
 
492
        }
 
493
 
 
494
        dst1 += dstPitch;
 
495
        src1 += srcPitch;
 
496
        if(j & 1) {
 
497
            src2 += srcPitch2;
 
498
            src3 += srcPitch2;
 
499
        }
 
500
   }
 
501
}
 
502
 
 
503
 
 
504
/*
 
505
 * TEXTURE DRAWING FUNCTIONS
 
506
 */
 
507
 
 
508
 
 
509
static void
 
510
TDFXStopVideoTexture(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
 
511
{
 
512
  TDFXPtr pTDFX = TDFXPTR(pScrn);
 
513
 
 
514
  if (cleanup) {
 
515
     if(pTDFX->textureBuffer) {
 
516
        xf86FreeOffscreenArea(pTDFX->textureBuffer);
 
517
        pTDFX->textureBuffer = NULL;
 
518
     }
 
519
  }
 
520
}
 
521
 
 
522
 
 
523
static void
 
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)
 
529
{
 
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;
 
540
 
 
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);
 
555
}
 
556
 
 
557
 
 
558
static void
 
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,
 
564
                   FBAreaPtr fbarea)
 
565
{
 
566
   TDFXPtr pTDFX = TDFXPTR(pScrn);
 
567
   unsigned char *psrc, *pdst;
 
568
   int count;
 
569
   int baseaddr;
 
570
   INT32 yuvBaseAddr, yuvStride;
 
571
 
 
572
   /* Save these registers so I can restore them when we are done. */
 
573
   yuvBaseAddr = TDFXReadLongMMIO(pTDFX, YUVBASEADDR);
 
574
   yuvStride =   TDFXReadLongMMIO(pTDFX, YUVSTRIDE);
 
575
 
 
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);
 
580
 
 
581
   /* Copy Y plane (twice as much Y as U or V) */
 
582
   psrc = buf;
 
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));
 
586
 
 
587
   /* Copy V plane */
 
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);
 
592
 
 
593
   /* Copy U plane */
 
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);
 
598
 
 
599
   /* IDLE until the copy finished, timeout for safety */
 
600
   for (count = 0; count < 1000; count++) 
 
601
     if (!((TDFXReadLongMMIO(pTDFX, STATUS) & SST_BUSY)))
 
602
       break;
 
603
 
 
604
   /* Restore trashed registers */
 
605
   TDFXWriteLongMMIO(pTDFX, YUVBASEADDR, yuvBaseAddr);
 
606
   TDFXWriteLongMMIO(pTDFX, YUVSTRIDE, yuvStride);  
 
607
 
 
608
   /* Wait for it to happen */
 
609
   TDFXSendNOPFifo2D(pScrn);
 
610
}
 
611
 
 
612
 
 
613
static int 
 
614
TDFXPutImageTexture( 
 
615
             ScrnInfoPtr 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, 
 
622
             Bool sync,
 
623
             RegionPtr clipBoxes, pointer data,
 
624
             DrawablePtr pDraw
 
625
             )
 
626
{
 
627
   TDFXPtr pTDFX = TDFXPTR(pScrn);
 
628
   BoxPtr pbox;
 
629
   int nbox;
 
630
   int format;
 
631
 
 
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);
 
634
 
 
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;
 
639
 
 
640
   /* Get a buffer to store the packed YUV data */
 
641
   if (!(pTDFX->textureBuffer = TDFXAllocateMemoryArea(pScrn, pTDFX->textureBuffer, src_w, src_h)))
 
642
        return BadAlloc;
 
643
 
 
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);
 
648
 
 
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));
 
654
 
 
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++)
 
662
   {
 
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),
 
668
        pbox->x1, pbox->y1,
 
669
        pbox->x2, pbox->y2);
 
670
   }
 
671
 
 
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);
 
677
 
 
678
   /* Wait for it to happen */
 
679
   TDFXSendNOPFifo2D(pScrn);
 
680
 
 
681
   return Success;
 
682
}
 
683
 
 
684
 
 
685
/*
 
686
 * OVERLAY DRAWING FUNCTIONS
 
687
 */
 
688
 
 
689
 
 
690
static void
 
691
TDFXResetVideoOverlay(ScrnInfoPtr pScrn)
 
692
{
 
693
    TDFXPtr pTDFX = TDFXPTR(pScrn);
 
694
    TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
 
695
 
 
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);
 
702
}
 
703
 
 
704
 
 
705
static void
 
706
TDFXStopVideoOverlay(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
 
707
{
 
708
  TDFXPtr pTDFX = TDFXPTR(pScrn);
 
709
  TDFXPortPrivPtr pPriv = (TDFXPortPrivPtr)data;
 
710
 
 
711
  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
 
712
 
 
713
  if(cleanup) {
 
714
     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
 
715
        pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
 
716
        pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
 
717
     }
 
718
     if(pTDFX->overlayBuffer) {
 
719
        xf86FreeOffscreenLinear(pTDFX->overlayBuffer);
 
720
        pTDFX->overlayBuffer = NULL;
 
721
     }
 
722
     if(pTDFX->overlayBuffer2) {
 
723
        xf86FreeOffscreenLinear(pTDFX->overlayBuffer2);
 
724
        pTDFX->overlayBuffer2 = NULL;
 
725
     }
 
726
     pPriv->videoStatus = 0;
 
727
  } else {
 
728
     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
 
729
        pPriv->videoStatus |= OFF_TIMER;
 
730
        pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
 
731
     }
 
732
  }
 
733
}
 
734
 
 
735
 
 
736
/* * * * * *
 
737
 
 
738
Decoder...
 
739
 
 
740
VIDPROCCFG:  0x5c:  Video Processor Configuration register
 
741
 
 
742
#define VIDPROCCFGMASK          0xa2e3eb6c
 
743
  3 2         1         0
 
744
  10987654321098765432109876543210
 
745
  10100010111000111110101101101100
 
746
 
 
747
The "1" bits are the bits cleared to 0 in pTDFX->ModeReg.vidcfg
 
748
 
 
749
 
 
750
Then we or in 0x320:
 
751
 
 
752
      11
 
753
      109876543210
 
754
320 = 001100100000
 
755
    
 
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
 
769
 
 
770
SST_VIDEO_2X_MODE_EN: bit26: means 2 pixels per screen clock mode is on
 
771
 
 
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
 
779
 
 
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...?]
 
783
 
 
784
* * * * * */
 
785
 
 
786
static void
 
787
TDFXDisplayVideoOverlay(
 
788
    ScrnInfoPtr pScrn,
 
789
    int id,
 
790
    int offset,
 
791
    short width, short height,
 
792
    int pitch,
 
793
    int left, int right, int top,
 
794
    BoxPtr dstBox,
 
795
    short src_w, short src_h,
 
796
    short drw_w, short drw_h
 
797
){
 
798
    TDFXPtr pTDFX = TDFXPTR(pScrn);
 
799
    TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
 
800
    int dudx, dvdy;
 
801
 
 
802
    dudx = (src_w << 20) / drw_w;
 
803
    /* subtract 1 to eliminate garbage on last line */
 
804
    dvdy = (( src_h - 1 )<< 20) / drw_h; 
 
805
 
 
806
    offset += ((left >> 16) & ~1) << 1;
 
807
    left = (left & 0x0001ffff) << 3;
 
808
 
 
809
    pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
 
810
    pTDFX->ModeReg.vidcfg |= 0x00000320;
 
811
 
 
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);
 
821
 
 
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);
 
828
 
 
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);
 
835
}
 
836
 
 
837
 
 
838
#if 0
 
839
 
 
840
/* * * * *
 
841
 
 
842
TDFXSwapVideoOverlayBuffer tries to use the Avenger SWAPBUFFER
 
843
capability to change frames without tearing.
 
844
 
 
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.
 
848
 
 
849
NOTE: Work in progress - doesn't seem to sync to VSYNC, and only every
 
850
other frame gets displayed...
 
851
 
 
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
 
855
get it working later
 
856
 
 
857
  -- Steve Davies 2002-10-04
 
858
  -- <steve@daviesfam.org>
 
859
 
 
860
* * * * * */
 
861
 
 
862
static void
 
863
TDFXSwapVideoOverlayBuffer(
 
864
    ScrnInfoPtr pScrn,
 
865
    int offset,
 
866
    int left
 
867
){
 
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);
 
876
}
 
877
 
 
878
#endif
 
879
 
 
880
static int
 
881
TDFXPutImageOverlay(
 
882
  ScrnInfoPtr pScrn,
 
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,
 
889
  Bool Sync,
 
890
  RegionPtr clipBoxes, pointer data,
 
891
  DrawablePtr pDraw
 
892
){
 
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;
 
900
   int dstPitch;
 
901
   int top, left, npixels, nlines, bpp;
 
902
   BoxRec dstBox;
 
903
   CARD32 tmp;
 
904
 
 
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);
 
907
 
 
908
   /*
 
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".
 
912
    *
 
913
    * offset - byte offset to the first line of the destination.
 
914
    *
 
915
    * dst_start - byte address to the first displayed pel.
 
916
    *
 
917
    */
 
918
 
 
919
   if(src_w > drw_w) drw_w = src_w;
 
920
   if(src_h > drw_h) drw_h = src_h;
 
921
 
 
922
   /* Clip */
 
923
   xa = src_x;
 
924
   xb = src_x + src_w;
 
925
   ya = src_y;
 
926
   yb = src_y + src_h;
 
927
 
 
928
   dstBox.x1 = drw_x;
 
929
   dstBox.x2 = drw_x + drw_w;
 
930
   dstBox.y1 = drw_y;
 
931
   dstBox.y2 = drw_y + drw_h;
 
932
 
 
933
   if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb,
 
934
                             clipBoxes, width, height))
 
935
        return Success;
 
936
 
 
937
   dstBox.x1 -= pScrn->frameX0;
 
938
   dstBox.x2 -= pScrn->frameX0;
 
939
   dstBox.y1 -= pScrn->frameY0;
 
940
   dstBox.y2 -= pScrn->frameY0;
 
941
 
 
942
   bpp = pScrn->bitsPerPixel >> 3;
 
943
 
 
944
   switch(id) {
 
945
   case FOURCC_YV12:
 
946
   case FOURCC_I420:
 
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;
 
953
        break;
 
954
   case FOURCC_UYVY:
 
955
   case FOURCC_YUY2:
 
956
   default:
 
957
        dstPitch = ((width << 1) + 3) & ~3;
 
958
        new_size = ((dstPitch * height) + bpp - 1) / bpp;
 
959
        srcPitch = (width << 1);
 
960
        break;
 
961
   }
 
962
 
 
963
   if(!(pTDFX->overlayBuffer = TDFXAllocateMemoryLinear(pScrn, pTDFX->overlayBuffer, new_size)))
 
964
        return BadAlloc;
 
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");
 
970
 
 
971
   /* copy data */
 
972
   top = ya >> 16;
 
973
   left = (xa >> 16) & ~1;
 
974
   npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left;
 
975
 
 
976
   /* Get buffer offset */
 
977
   if (pTDFX->whichOverlayBuffer == 0)
 
978
     offset = (pTDFX->overlayBuffer->offset * bpp) + (top * dstPitch) + pTDFX->fbOffset;
 
979
   else
 
980
     offset = (pTDFX->overlayBuffer2->offset * bpp) + (top * dstPitch) + pTDFX->fbOffset;
 
981
 
 
982
   /* Flip to other buffer for next time */
 
983
   pTDFX->whichOverlayBuffer ^= 1;
 
984
 
 
985
   dst_start = pTDFX->FbBase + offset;
 
986
 
 
987
   switch(id) {
 
988
    case FOURCC_YV12:
 
989
    case FOURCC_I420:
 
990
        top &= ~1;
 
991
        dst_start += left << 1;
 
992
        tmp = ((top >> 1) * srcPitch2) + (left >> 1);
 
993
        s2offset += tmp;
 
994
        s3offset += tmp;
 
995
        if(id == FOURCC_I420) {
 
996
           tmp = s2offset;
 
997
           s2offset = s3offset;
 
998
           s3offset = tmp;
 
999
        }
 
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);
 
1005
        break;
 
1006
    case FOURCC_UYVY:
 
1007
    case FOURCC_YUY2:
 
1008
    default:
 
1009
        left <<= 1;
 
1010
        buf += (top * srcPitch) + left;
 
1011
        nlines = ((yb + 0xffff) >> 16) - top;
 
1012
        dst_start += left;
 
1013
        TDFXTRACE("TDFXPutImageOverlay: using copydata\n");
 
1014
        TDFXCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
 
1015
        break;
 
1016
    }
 
1017
 
 
1018
    if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
 
1019
        REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
 
1020
        xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
 
1021
    }
 
1022
 
 
1023
    TDFXDisplayVideoOverlay(pScrn, id, offset, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
 
1024
 
 
1025
    pPriv->videoStatus = CLIENT_VIDEO_ON;
 
1026
 
 
1027
    pTDFX->VideoTimerCallback = TDFXVideoTimerCallback;
 
1028
 
 
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)
 
1036
    );
 
1037
 
 
1038
    return Success;
 
1039
}
 
1040
 
 
1041
 
 
1042
static void
 
1043
TDFXVideoTimerCallback(ScrnInfoPtr pScrn, Time time)
 
1044
{
 
1045
    TDFXPtr pTDFX = TDFXPTR(pScrn);
 
1046
    TDFXPortPrivPtr pPriv = pTDFX->overlayAdaptor->pPortPrivates[0].ptr;
 
1047
 
 
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;
 
1055
            }
 
1056
        } else
 
1057
        if(pPriv->videoStatus & FREE_TIMER) {
 
1058
            if(pPriv->freeTime < time) {
 
1059
                if(pTDFX->overlayBuffer) {
 
1060
                   xf86FreeOffscreenLinear(pTDFX->overlayBuffer);
 
1061
                   pTDFX->overlayBuffer = NULL;
 
1062
                }
 
1063
                if(pTDFX->overlayBuffer2) {
 
1064
                   xf86FreeOffscreenLinear(pTDFX->overlayBuffer2);
 
1065
                   pTDFX->overlayBuffer2 = NULL;
 
1066
                }
 
1067
                pPriv->videoStatus = 0;
 
1068
                pTDFX->VideoTimerCallback = NULL;
 
1069
            }
 
1070
        }
 
1071
    } else  /* shouldn't get here */
 
1072
        pTDFX->VideoTimerCallback = NULL;
 
1073
}
 
1074
 
 
1075
 
 
1076
/*
 
1077
 * MEMORY MANAGEMENT
 
1078
 */
 
1079
 
 
1080
 
 
1081
static FBAreaPtr
 
1082
TDFXAllocateMemoryArea (ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height)
 
1083
{
 
1084
  TDFXPtr pTDFX = TDFXPTR(pScrn);
 
1085
  ScreenPtr pScreen;
 
1086
  FBAreaPtr new_area;
 
1087
 
 
1088
  if (area) {
 
1089
    if ((area->box.x2 - area->box.x1 >= width) &&
 
1090
        (area->box.y2 - area->box.y1 >= height))
 
1091
      return area;
 
1092
 
 
1093
    if (xf86ResizeOffscreenArea(area, width, height))
 
1094
      return area;
 
1095
 
 
1096
    xf86FreeOffscreenArea(area);
 
1097
  }
 
1098
 
 
1099
  pScreen = xf86ScrnToScreen(pScrn);
 
1100
 
 
1101
  new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL);
 
1102
 
 
1103
  if (!new_area) {
 
1104
    int max_width, max_height;
 
1105
 
 
1106
    xf86QueryLargestOffscreenArea(pScreen, &max_width, &max_height, pTDFX->cpp, 0, PRIORITY_EXTREME);
 
1107
 
 
1108
    if (max_width < width || max_height < height)
 
1109
      return NULL;
 
1110
 
 
1111
    xf86PurgeUnlockedOffscreenAreas(pScreen);
 
1112
    new_area = xf86AllocateOffscreenArea(pScreen, width, height, pTDFX->cpp, NULL, NULL, NULL);
 
1113
  }
 
1114
 
 
1115
  return new_area;
 
1116
}
 
1117
 
 
1118
 
 
1119
static FBLinearPtr
 
1120
TDFXAllocateMemoryLinear (ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
 
1121
{
 
1122
   ScreenPtr pScreen;
 
1123
   FBLinearPtr new_linear;
 
1124
 
 
1125
   if(linear) {
 
1126
        if(linear->size >= size)
 
1127
           return linear;
 
1128
 
 
1129
        if(xf86ResizeOffscreenLinear(linear, size))
 
1130
           return linear;
 
1131
 
 
1132
        xf86FreeOffscreenLinear(linear);
 
1133
   }
 
1134
 
 
1135
   pScreen = xf86ScrnToScreen(pScrn);
 
1136
 
 
1137
   new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
 
1138
 
 
1139
   if(!new_linear) {
 
1140
        int max_size;
 
1141
 
 
1142
        xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, PRIORITY_EXTREME);
 
1143
 
 
1144
        if(max_size < size)
 
1145
           return NULL;
 
1146
 
 
1147
        xf86PurgeUnlockedOffscreenAreas(pScreen);
 
1148
        new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, NULL, NULL, NULL);
 
1149
   }
 
1150
 
 
1151
   return new_linear;
 
1152
}
 
1153
 
 
1154
/****************** Offscreen stuff ***************/
 
1155
 
 
1156
typedef struct {
 
1157
  FBLinearPtr linear;
 
1158
  Bool isOn;
 
1159
} OffscreenPrivRec, * OffscreenPrivPtr;
 
1160
 
 
1161
static int 
 
1162
TDFXAllocateSurface(
 
1163
    ScrnInfoPtr pScrn,
 
1164
    int id,
 
1165
    unsigned short w,   
 
1166
    unsigned short h,
 
1167
    XF86SurfacePtr surface
 
1168
){
 
1169
    TDFXPtr pTDFX = TDFXPTR(pScrn);
 
1170
    FBLinearPtr linear;
 
1171
    int pitch, size, bpp;
 
1172
    OffscreenPrivPtr pPriv;
 
1173
 
 
1174
    if((w > 2048) || (h > 2048))
 
1175
        return BadAlloc;
 
1176
 
 
1177
    w = (w + 1) & ~1;
 
1178
    pitch = ((w << 1) + 15) & ~15;
 
1179
    bpp = pScrn->bitsPerPixel >> 3;
 
1180
    size = ((pitch * h) + bpp - 1) / bpp;
 
1181
 
 
1182
    if(!(linear = TDFXAllocateMemoryLinear(pScrn, NULL, size)))
 
1183
        return BadAlloc;
 
1184
 
 
1185
    surface->width = w;
 
1186
    surface->height = h;
 
1187
 
 
1188
    if(!(surface->pitches = malloc(sizeof(int)))) {
 
1189
        xf86FreeOffscreenLinear(linear);
 
1190
        return BadAlloc;
 
1191
    }
 
1192
    if(!(surface->offsets = malloc(sizeof(int)))) {
 
1193
        free(surface->pitches);
 
1194
        xf86FreeOffscreenLinear(linear);
 
1195
        return BadAlloc;
 
1196
    }
 
1197
    if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) {
 
1198
        free(surface->pitches);
 
1199
        free(surface->offsets);
 
1200
        xf86FreeOffscreenLinear(linear);
 
1201
        return BadAlloc;
 
1202
    }
 
1203
 
 
1204
    pPriv->linear = linear;
 
1205
    pPriv->isOn = FALSE;
 
1206
 
 
1207
    surface->pScrn = pScrn;
 
1208
    surface->id = id;   
 
1209
    surface->pitches[0] = pitch;
 
1210
    surface->offsets[0] = pTDFX->fbOffset + (linear->offset * bpp);
 
1211
    surface->devPrivate.ptr = (pointer)pPriv;
 
1212
 
 
1213
    return Success;
 
1214
}
 
1215
 
 
1216
static int 
 
1217
TDFXStopSurface(
 
1218
    XF86SurfacePtr surface
 
1219
){
 
1220
    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
 
1221
 
 
1222
    if(pPriv->isOn) {
 
1223
        TDFXPtr pTDFX = TDFXPTR(surface->pScrn);
 
1224
        pTDFX->ModeReg.vidcfg &= ~VIDPROCCFGMASK;
 
1225
        pTDFX->writeLong(pTDFX, VIDPROCCFG, pTDFX->ModeReg.vidcfg);
 
1226
        pPriv->isOn = FALSE;
 
1227
    }
 
1228
 
 
1229
    return Success;
 
1230
}
 
1231
 
 
1232
 
 
1233
static int 
 
1234
TDFXFreeSurface(
 
1235
    XF86SurfacePtr surface
 
1236
){
 
1237
    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
 
1238
 
 
1239
    if(pPriv->isOn)
 
1240
        TDFXStopSurface(surface);
 
1241
    xf86FreeOffscreenLinear(pPriv->linear);
 
1242
    free(surface->pitches);
 
1243
    free(surface->offsets);
 
1244
    free(surface->devPrivate.ptr);
 
1245
 
 
1246
    return Success;
 
1247
}
 
1248
 
 
1249
static int
 
1250
TDFXGetSurfaceAttribute(
 
1251
    ScrnInfoPtr pScrn,
 
1252
    Atom attribute,
 
1253
    INT32 *value
 
1254
){
 
1255
    return TDFXGetPortAttributeOverlay(pScrn, attribute, value, 
 
1256
                        (pointer)(GET_PORT_PRIVATE(pScrn)));
 
1257
}
 
1258
 
 
1259
static int
 
1260
TDFXSetSurfaceAttribute(
 
1261
    ScrnInfoPtr pScrn,
 
1262
    Atom attribute,
 
1263
    INT32 value
 
1264
){
 
1265
    return TDFXSetPortAttributeOverlay(pScrn, attribute, value, 
 
1266
                        (pointer)(GET_PORT_PRIVATE(pScrn)));
 
1267
}
 
1268
 
 
1269
static int 
 
1270
TDFXDisplaySurface(
 
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,
 
1276
    RegionPtr clipBoxes
 
1277
){
 
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;
 
1283
    BoxRec dstBox;
 
1284
 
 
1285
    x1 = src_x;
 
1286
    x2 = src_x + src_w;
 
1287
    y1 = src_y;
 
1288
    y2 = src_y + src_h;
 
1289
 
 
1290
    dstBox.x1 = drw_x;
 
1291
    dstBox.x2 = drw_x + drw_w;
 
1292
    dstBox.y1 = drw_y;
 
1293
    dstBox.y2 = drw_y + drw_h;
 
1294
 
 
1295
    if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 
 
1296
                              surface->width, surface->height))
 
1297
    {
 
1298
        return Success;
 
1299
    }
 
1300
 
 
1301
    dstBox.x1 -= pScrn->frameX0;
 
1302
    dstBox.x2 -= pScrn->frameX0;
 
1303
    dstBox.y1 -= pScrn->frameY0;
 
1304
    dstBox.y2 -= pScrn->frameY0;
 
1305
 
 
1306
#if 0
 
1307
    TDFXResetVideoOverlay(pScrn);
 
1308
#endif
 
1309
 
 
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);
 
1313
 
 
1314
    xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
 
1315
 
 
1316
    pPriv->isOn = TRUE;
 
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;
 
1324
    }
 
1325
 
 
1326
    return Success;
 
1327
}
 
1328
 
 
1329
static void 
 
1330
TDFXInitOffscreenImages(ScreenPtr pScreen)
 
1331
{
 
1332
    XF86OffscreenImagePtr offscreenImages;
 
1333
 
 
1334
    /* need to free this someplace */
 
1335
    if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec))))
 
1336
        return;
 
1337
 
 
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;
 
1351
    
 
1352
    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
 
1353
}