~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/hw/xfree86/drivers/glint/pm3_video.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2001 by Alan Hourihane, Sychdyn, North Wales.
 
3
 *
 
4
 * Permission to use, copy, modify, distribute, and sell this software and its
 
5
 * documentation for any purpose is hereby granted without fee, provided that
 
6
 * the above copyright notice appear in all copies and that both that
 
7
 * copyright notice and this permission notice appear in supporting
 
8
 * documentation, and that the name of Alan Hourihane not be used in
 
9
 * advertising or publicity pertaining to distribution of the software without
 
10
 * specific, written prior permission.  Alan Hourihane makes no representations
 
11
 * about the suitability of this software for any purpose.  It is provided
 
12
 * "as is" without express or implied warranty.
 
13
 *
 
14
 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
15
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
16
 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
17
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
18
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
19
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
20
 * PERFORMANCE OF THIS SOFTWARE.
 
21
 *
 
22
 * Authors: Alan Hourihane, alanh@fairlite.demon.co.uk
 
23
 *          Sven Luther <luther@dpt-info.u-strasbg.fr>
 
24
 */
 
25
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/glint/pm3_video.c,v 1.11 2002/05/22 08:12:02 alanh Exp $ */
 
26
 
 
27
#include "xf86.h"
 
28
#include "xf86_OSproc.h"
 
29
#include "xf86Resources.h"
 
30
#include "xf86_ansic.h"
 
31
#include "compiler.h"
 
32
#include "xf86PciInfo.h"
 
33
#include "xf86Pci.h"
 
34
#include "xf86fbman.h"
 
35
#include "regionstr.h"
 
36
 
 
37
#include "glint.h"
 
38
#include "glint_regs.h"
 
39
#include "pm3_regs.h"
 
40
#include "Xv.h"
 
41
#include "xaa.h"
 
42
#include "xaalocal.h"
 
43
#include "dixstruct.h"
 
44
#include "fourcc.h"
 
45
 
 
46
#define OFF_DELAY       200  /* milliseconds */
 
47
#define FREE_DELAY      60000
 
48
 
 
49
#define OFF_TIMER       0x01
 
50
#define FREE_TIMER      0x02
 
51
#define CLIENT_VIDEO_ON 0x04
 
52
 
 
53
#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
 
54
 
 
55
#ifndef XvExtension
 
56
void Permedia3InitVideo(ScreenPtr pScreen) {}
 
57
void Permedia3ResetVideo(ScrnInfoPtr pScrn) {}
 
58
#else
 
59
 
 
60
static XF86VideoAdaptorPtr Permedia3SetupImageVideo(ScreenPtr);
 
61
static void Permedia3InitOffscreenImages(ScreenPtr);
 
62
static void Permedia3StopVideo(ScrnInfoPtr, pointer, Bool);
 
63
static int Permedia3SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
 
64
static int Permedia3GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
 
65
static void Permedia3QueryBestSize(ScrnInfoPtr, Bool,
 
66
        short, short, short, short, unsigned int *, unsigned int *, pointer);
 
67
static int Permedia3PutImage( ScrnInfoPtr, 
 
68
        short, short, short, short, short, short, short, short,
 
69
        int, unsigned char*, short, short, Bool, RegionPtr, pointer);
 
70
static int Permedia3QueryImageAttributes(ScrnInfoPtr, 
 
71
        int, unsigned short *, unsigned short *,  int *, int *);
 
72
static void Permedia3VideoTimerCallback(ScrnInfoPtr pScrn, Time time);
 
73
 
 
74
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
 
75
 
 
76
static Atom xvColorKey, xvDoubleBuffer, xvAutopaintColorKey, xvFilter;
 
77
 
 
78
void Permedia3InitVideo(ScreenPtr pScreen)
 
79
{
 
80
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 
81
    XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
 
82
    XF86VideoAdaptorPtr newAdaptor = NULL;
 
83
    GLINTPtr pGlint = GLINTPTR(pScrn);
 
84
    int num_adaptors;
 
85
        
 
86
    /* Because of bugs in the PM3 when uploading images via the
 
87
     * bypass to the framebuffer, we always have to use the accelerator.
 
88
     */
 
89
    if (pGlint->NoAccel)
 
90
        return;
 
91
 
 
92
    newAdaptor = Permedia3SetupImageVideo(pScreen);
 
93
    Permedia3InitOffscreenImages(pScreen);
 
94
 
 
95
    num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
 
96
 
 
97
    if(newAdaptor) {
 
98
        if(!num_adaptors) {
 
99
            num_adaptors = 1;
 
100
            adaptors = &newAdaptor;
 
101
        } else {
 
102
            newAdaptors =  /* need to free this someplace */
 
103
                xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
 
104
            if(newAdaptors) {
 
105
                memcpy(newAdaptors, adaptors, num_adaptors * 
 
106
                                        sizeof(XF86VideoAdaptorPtr));
 
107
                newAdaptors[num_adaptors] = newAdaptor;
 
108
                adaptors = newAdaptors;
 
109
                num_adaptors++;
 
110
            }
 
111
        }
 
112
    }
 
113
 
 
114
    if(num_adaptors)
 
115
        xf86XVScreenInit(pScreen, adaptors, num_adaptors);
 
116
 
 
117
    if(newAdaptors)
 
118
        xfree(newAdaptors);
 
119
}
 
120
 
 
121
/* client libraries expect an encoding */
 
122
static XF86VideoEncodingRec DummyEncoding[1] =
 
123
{
 
124
 {
 
125
   0,
 
126
   "XV_IMAGE",
 
127
   2047, 2047,
 
128
   {1, 1}
 
129
 }
 
130
};
 
131
 
 
132
#define NUM_FORMATS 4
 
133
 
 
134
static XF86VideoFormatRec Formats[NUM_FORMATS] = 
 
135
{
 
136
  {8, PseudoColor},  {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
 
137
};
 
138
 
 
139
#define NUM_ATTRIBUTES 4 
 
140
 
 
141
static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
 
142
{
 
143
   {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
 
144
   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
 
145
   {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
 
146
   {XvSettable | XvGettable, 0, 2, "XV_FILTER"},
 
147
};
 
148
 
 
149
/*
 
150
 *  FOURCC from http://www.webartz.com/fourcc
 
151
 *  Generic GUID for legacy FOURCC XXXXXXXX-0000-0010-8000-00AA00389B71
 
152
 */
 
153
#define LE4CC(a,b,c,d) (((CARD32)(a)&0xFF)|(((CARD32)(b)&0xFF)<<8)|(((CARD32)(c)&0xFF)<<16)|(((CARD32)(d)&0xFF)<<24))
 
154
#define GUID4CC(a,b,c,d) { a,b,c,d,0,0,0,0x10,0x80,0,0,0xAA,0,0x38,0x9B,0x71 }
 
155
 
 
156
#define NoOrder LSBFirst
 
157
 
 
158
#define NUM_IMAGES 15
 
159
 
 
160
static XF86ImageRec Images[NUM_IMAGES] =
 
161
{
 
162
    /* Planar YVU 4:2:0 (emulated) */
 
163
    { LE4CC('Y','V','1','2'), XvYUV, NoOrder, GUID4CC('Y','V','1','2'),
 
164
      12, XvPlanar, 3, 0, 0, 0, 0,
 
165
      8, 8, 8,  1, 2, 2,  1, 2, 2, "YVU", XvTopToBottom },
 
166
 
 
167
    /* Packed YUYV 4:2:2 */
 
168
    { LE4CC('Y','U','Y','2'), XvYUV, NoOrder, GUID4CC('Y','U','Y','2'),
 
169
      16, XvPacked, 1, 0, 0, 0, 0,
 
170
      8, 8, 8,  1, 2, 2,  1, 1, 1, "YUYV", XvTopToBottom },
 
171
 
 
172
    /* Packed UYVY 4:2:2 */
 
173
    { LE4CC('U','Y','V','Y'), XvYUV, NoOrder, GUID4CC('U','Y','V','Y'),
 
174
      16, XvPacked, 1, 0, 0, 0, 0,
 
175
      8, 8, 8,  1, 2, 2,  1, 1, 1, "UYVY", XvTopToBottom },
 
176
 
 
177
    /* Packed YUVA 4:4:4 */
 
178
    { LE4CC('Y','U','V','A') /* XXX not registered */, XvYUV, LSBFirst, { 0 },
 
179
      32, XvPacked, 1, 0, 0, 0, 0,
 
180
      8, 8, 8,  1, 1, 1,  1, 1, 1, "YUVA", XvTopToBottom },
 
181
 
 
182
    /* Packed VUYA 4:4:4 */
 
183
    { LE4CC('V','U','Y','A') /* XXX not registered */, XvYUV, LSBFirst, { 0 },
 
184
      32, XvPacked, 1, 0, 0, 0, 0,
 
185
      8, 8, 8,  1, 1, 1,  1, 1, 1, "VUYA", XvTopToBottom },
 
186
 
 
187
    /* RGBA 8:8:8:8 */
 
188
    { 0x41, XvRGB, LSBFirst, { 0 },
 
189
      32, XvPacked, 1, 24, 0x0000FF, 0x00FF00, 0xFF0000, 
 
190
      0, 0, 0,  0, 0, 0,  0, 0, 0, "RGBA", XvTopToBottom },
 
191
 
 
192
    /* RGB 5:6:5 */
 
193
    { 0x42, XvRGB, LSBFirst, { 0 },
 
194
      16, XvPacked, 1, 16, 0x001F, 0x07E0, 0xF800, 
 
195
      0, 0, 0,  0, 0, 0,  0, 0, 0, "RGB", XvTopToBottom },
 
196
 
 
197
    /* RGBA 5:5:5:1 */
 
198
    { 0x43, XvRGB, LSBFirst, { 0 },
 
199
      16, XvPacked, 1, 15, 0x001F, 0x03E0, 0x7C00, 
 
200
      0, 0, 0,  0, 0, 0,  0, 0, 0, "RGBA", XvTopToBottom },
 
201
 
 
202
    /* RGBA 4:4:4:4 */
 
203
    { 0x44, XvRGB, LSBFirst, { 0 },
 
204
      16, XvPacked, 1, 12, 0x000F, 0x00F0, 0x0F00, 
 
205
      0, 0, 0,  0, 0, 0,  0, 0, 0, "RGBA", XvTopToBottom },
 
206
 
 
207
    /* RGB 3:3:2 */
 
208
    { 0x46, XvRGB, NoOrder, { 0 },
 
209
      8, XvPacked, 1, 8, 0x07, 0x38, 0xC0, 
 
210
      0, 0, 0,  0, 0, 0,  0, 0, 0, "RGB", XvTopToBottom },
 
211
 
 
212
    /* BGRA 8:8:8:8 */
 
213
    { 0x47, XvRGB, LSBFirst, { 0 },
 
214
      32, XvPacked, 1, 24, 0xFF0000, 0x00FF00, 0x0000FF,
 
215
      0, 0, 0,  0, 0, 0,  0, 0, 0, "BGRA", XvTopToBottom },
 
216
 
 
217
    /* BGR 5:6:5 */
 
218
    { 0x48, XvRGB, LSBFirst, { 0 },
 
219
      16, XvPacked, 1, 16, 0xF800, 0x07E0, 0x001F,
 
220
      0, 0, 0,  0, 0, 0,  0, 0, 0, "BGR", XvTopToBottom },
 
221
 
 
222
    /* BGRA 5:5:5:1 */
 
223
    { 0x49, XvRGB, LSBFirst, { 0 },
 
224
      16, XvPacked, 1, 15, 0x7C00, 0x03E0, 0x001F,
 
225
      0, 0, 0,  0, 0, 0,  0, 0, 0, "BGRA", XvTopToBottom },
 
226
 
 
227
    /* BGRA 4:4:4:4 */
 
228
    { 0x4A, XvRGB, LSBFirst, { 0 },
 
229
      16, XvPacked, 1, 12, 0x0F00, 0x00F0, 0x000F,
 
230
      0, 0, 0,  0, 0, 0,  0, 0, 0, "BGRA", XvTopToBottom },
 
231
 
 
232
    /* BGR 2:3:3 */
 
233
    { 0x4C, XvRGB, NoOrder, { 0 },
 
234
      8, XvPacked, 1, 8, 0xC0, 0x38, 0x07,
 
235
      0, 0, 0,  0, 0, 0,  0, 0, 0, "BGR", XvTopToBottom },
 
236
};
 
237
 
 
238
#define MAX_BUFFERS 2
 
239
 
 
240
typedef struct {
 
241
   FBAreaPtr    area[MAX_BUFFERS];
 
242
   RegionRec    clip;
 
243
   CARD32       colorKey;
 
244
   CARD32       videoStatus;
 
245
   Time         offTime;
 
246
   Time         freeTime;
 
247
   int          Video_Shift;
 
248
   int          Format;
 
249
   Bool         ramdacOn;
 
250
   Bool         doubleBuffer;
 
251
   Bool         autopaintColorKey;
 
252
   int          Filter;
 
253
   int          sx, sy;
 
254
   int          offset[MAX_BUFFERS];
 
255
   int          buffer;
 
256
} GLINTPortPrivRec, *GLINTPortPrivPtr;
 
257
 
 
258
#define GET_PORT_PRIVATE(pScrn) \
 
259
   (GLINTPortPrivPtr)((GLINTPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
 
260
 
 
261
#define RAMDAC_WRITE(data,index)                                \
 
262
do{                                                             \
 
263
        GLINT_WRITE_REG(((index)>>8)&0xff, PM3RD_IndexHigh);    \
 
264
        GLINT_WRITE_REG((index)&0xff, PM3RD_IndexLow);          \
 
265
        GLINT_WRITE_REG(data, PM3RD_IndexedData);               \
 
266
}while(0)
 
267
 
 
268
void Permedia3ResetVideo(ScrnInfoPtr pScrn) 
 
269
{
 
270
    GLINTPtr pGlint = GLINTPTR(pScrn);
 
271
    GLINTPortPrivPtr pPriv = pGlint->adaptor->pPortPrivates[0].ptr;
 
272
 
 
273
    GLINT_WAIT(15);
 
274
    GLINT_WRITE_REG(0xfff0|(0xffff<<16), PM3VideoOverlayFifoControl);
 
275
    GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE, PM3VideoOverlayMode);
 
276
    pPriv->ramdacOn = FALSE;
 
277
    RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE, PM3RD_VideoOverlayControl);
 
278
    RAMDAC_WRITE((pPriv->colorKey&0xff0000)>>16, PM3RD_VideoOverlayKeyR);
 
279
    RAMDAC_WRITE((pPriv->colorKey&0x00ff00)>>8, PM3RD_VideoOverlayKeyG);
 
280
    RAMDAC_WRITE(pPriv->colorKey&0x0000ff, PM3RD_VideoOverlayKeyB);
 
281
    GLINT_WRITE_REG(PM3VideoOverlayUpdate_ENABLE, PM3VideoOverlayUpdate);
 
282
}
 
283
 
 
284
 
 
285
static XF86VideoAdaptorPtr 
 
286
Permedia3SetupImageVideo(ScreenPtr pScreen)
 
287
{
 
288
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 
289
    GLINTPtr pGlint = GLINTPTR(pScrn);
 
290
    XF86VideoAdaptorPtr adapt;
 
291
    GLINTPortPrivPtr pPriv;
 
292
 
 
293
    if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
 
294
                            sizeof(GLINTPortPrivRec) +
 
295
                            sizeof(DevUnion))))
 
296
        return NULL;
 
297
 
 
298
    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
 
299
    adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
 
300
    adapt->name = "Permedia3 Backend Scaler";
 
301
    adapt->nEncodings = 1;
 
302
    adapt->pEncodings = DummyEncoding;
 
303
    adapt->nFormats = NUM_FORMATS;
 
304
    adapt->pFormats = Formats;
 
305
    adapt->nPorts = 1;
 
306
    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
 
307
    pPriv = (GLINTPortPrivPtr)(&adapt->pPortPrivates[1]);
 
308
    adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
 
309
    adapt->pAttributes = Attributes;
 
310
    adapt->nImages = NUM_IMAGES;
 
311
    adapt->nAttributes = NUM_ATTRIBUTES;
 
312
    adapt->pImages = Images;
 
313
    adapt->PutVideo = NULL;
 
314
    adapt->PutStill = NULL;
 
315
    adapt->GetVideo = NULL;
 
316
    adapt->GetStill = NULL;
 
317
    adapt->StopVideo = Permedia3StopVideo;
 
318
    adapt->SetPortAttribute = Permedia3SetPortAttribute;
 
319
    adapt->GetPortAttribute = Permedia3GetPortAttribute;
 
320
    adapt->QueryBestSize = Permedia3QueryBestSize;
 
321
    adapt->PutImage = Permedia3PutImage;
 
322
    adapt->QueryImageAttributes = Permedia3QueryImageAttributes;
 
323
 
 
324
    /* FIXME : depth 15 and 16 doesn't work here */
 
325
    pPriv->colorKey = pGlint->videoKey;
 
326
    pPriv->videoStatus = 0;
 
327
    pPriv->buffer = 0; /* double buffer (or maybe triple later) */
 
328
    pPriv->doubleBuffer = TRUE;
 
329
    pPriv->autopaintColorKey = TRUE;
 
330
    pPriv->Filter = PM3VideoOverlayMode_FILTER_FULL;
 
331
    
 
332
    /* gotta uninit this someplace */
 
333
    REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); 
 
334
 
 
335
    pGlint->adaptor = adapt;
 
336
 
 
337
    xvDoubleBuffer      = MAKE_ATOM("XV_DOUBLE_BUFFER");
 
338
    xvColorKey          = MAKE_ATOM("XV_COLORKEY");
 
339
    xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
 
340
    xvFilter            = MAKE_ATOM("XV_FILTER");
 
341
 
 
342
    Permedia3ResetVideo(pScrn);
 
343
 
 
344
    return adapt;
 
345
}
 
346
 
 
347
 
 
348
static Bool
 
349
RegionsEqual(RegionPtr A, RegionPtr B)
 
350
{
 
351
    int *dataA, *dataB;
 
352
    int num;
 
353
 
 
354
    num = REGION_NUM_RECTS(A);
 
355
    if(num != REGION_NUM_RECTS(B))
 
356
        return FALSE;
 
357
 
 
358
    if((A->extents.x1 != B->extents.x1) ||
 
359
       (A->extents.x2 != B->extents.x2) ||
 
360
       (A->extents.y1 != B->extents.y1) ||
 
361
       (A->extents.y2 != B->extents.y2))
 
362
        return FALSE;
 
363
 
 
364
    dataA = (int*)REGION_RECTS(A);
 
365
    dataB = (int*)REGION_RECTS(B);
 
366
 
 
367
    while(num--) {
 
368
        if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
 
369
           return FALSE;
 
370
        dataA += 2; 
 
371
        dataB += 2;
 
372
    }
 
373
 
 
374
    return TRUE;
 
375
}
 
376
 
 
377
static void 
 
378
Permedia3StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
 
379
{
 
380
  GLINTPtr pGlint = GLINTPTR(pScrn);
 
381
  GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data;
 
382
  int i;
 
383
 
 
384
  REGION_EMPTY(pScrn->pScreen, &pPriv->clip);   
 
385
 
 
386
  if(shutdown) {
 
387
     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
 
388
        pPriv->ramdacOn = FALSE;
 
389
        GLINT_WAIT(4);
 
390
        RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE,
 
391
                PM3RD_VideoOverlayControl);
 
392
        GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE,
 
393
                PM3VideoOverlayMode);
 
394
     }
 
395
     for (i = 0; i < (pPriv->doubleBuffer ? 2 : 1); i++) {
 
396
        if(pPriv->area[i]) {
 
397
           xf86FreeOffscreenArea(pPriv->area[i]);
 
398
           pPriv->area[i] = NULL;
 
399
        }
 
400
     }
 
401
     pPriv->videoStatus = 0;
 
402
  } else {
 
403
     if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
 
404
        pPriv->videoStatus |= OFF_TIMER;
 
405
        pPriv->offTime = currentTime.milliseconds + OFF_DELAY; 
 
406
     }
 
407
  }
 
408
}
 
409
 
 
410
static int 
 
411
Permedia3SetPortAttribute(
 
412
  ScrnInfoPtr pScrn, 
 
413
  Atom attribute,
 
414
  INT32 value, 
 
415
  pointer data
 
416
){
 
417
    GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data;
 
418
    GLINTPtr pGlint = GLINTPTR(pScrn);
 
419
 
 
420
    if (attribute == xvDoubleBuffer)
 
421
    {
 
422
        if ((value < 0) || (value > 1))
 
423
            return BadValue;
 
424
        pPriv->doubleBuffer = value;
 
425
    }
 
426
    else if (attribute == xvColorKey)
 
427
    {
 
428
        pPriv->colorKey = value;
 
429
        GLINT_WAIT(9);
 
430
        RAMDAC_WRITE((value & 0xff0000)>>16, PM3RD_VideoOverlayKeyR);
 
431
        RAMDAC_WRITE((value & 0x00ff00)>>8, PM3RD_VideoOverlayKeyG);
 
432
        RAMDAC_WRITE((value & 0x0000ff), PM3RD_VideoOverlayKeyB);
 
433
        REGION_EMPTY(pScrn->pScreen, &pPriv->clip);   
 
434
    }
 
435
    else if (attribute == xvAutopaintColorKey)
 
436
    {
 
437
        if ((value < 0) || (value > 1))
 
438
            return BadValue;
 
439
        pPriv->autopaintColorKey = value;
 
440
    }
 
441
    else if (attribute == xvFilter)
 
442
    {
 
443
        if ((value < 0) || (value > 2))
 
444
            return BadValue;
 
445
        switch (value) {
 
446
            case 0:
 
447
                pPriv->Filter = PM3VideoOverlayMode_FILTER_OFF;
 
448
                break;
 
449
            case 1:
 
450
                pPriv->Filter = PM3VideoOverlayMode_FILTER_FULL;
 
451
                break;
 
452
            case 2:
 
453
                pPriv->Filter = PM3VideoOverlayMode_FILTER_PARTIAL;
 
454
                break;
 
455
        }
 
456
    }
 
457
    else
 
458
        return BadMatch;
 
459
 
 
460
  return Success;
 
461
}
 
462
 
 
463
static int 
 
464
Permedia3GetPortAttribute(
 
465
  ScrnInfoPtr pScrn, 
 
466
  Atom attribute,
 
467
  INT32 *value, 
 
468
  pointer data
 
469
){
 
470
    GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data;
 
471
 
 
472
    if (attribute == xvDoubleBuffer)
 
473
        *value = (pPriv->doubleBuffer) ? 1 : 0;
 
474
    else if (attribute == xvColorKey)
 
475
        *value = pPriv->colorKey;
 
476
    else if (attribute == xvAutopaintColorKey)
 
477
        *value = (pPriv->autopaintColorKey) ? 1 : 0;
 
478
    else if (attribute == xvFilter)
 
479
        *value = pPriv->Filter >> 14;
 
480
    else
 
481
        return BadMatch;
 
482
 
 
483
    return Success;
 
484
}
 
485
 
 
486
static void 
 
487
Permedia3QueryBestSize(
 
488
  ScrnInfoPtr pScrn, 
 
489
  Bool motion,
 
490
  short vid_w, short vid_h, 
 
491
  short drw_w, short drw_h, 
 
492
  unsigned int *p_w, unsigned int *p_h, 
 
493
  pointer data
 
494
){
 
495
    if(vid_w > (drw_w << 3))
 
496
        drw_w = vid_w >> 3;
 
497
    if(vid_h > (drw_h << 3))
 
498
        drw_h = vid_h >> 3;
 
499
 
 
500
    *p_w = drw_w;
 
501
    *p_h = drw_h; 
 
502
}
 
503
 
 
504
static void
 
505
HWCopySetup(ScrnInfoPtr pScrn, int x, int y, int w, int h)
 
506
{
 
507
    GLINTPtr pGlint = GLINTPTR(pScrn);
 
508
 
 
509
    GLINT_WAIT(4);
 
510
    GLINT_WRITE_REG(0xffffffff, FBHardwareWriteMask);
 
511
    GLINT_WRITE_REG(
 
512
        PM3Config2D_ForegroundROPEnable |
 
513
        PM3Config2D_ForegroundROP(GXcopy) |
 
514
        PM3Config2D_FBWriteEnable,
 
515
        PM3Config2D);
 
516
    GLINT_WRITE_REG(
 
517
        PM3RectanglePosition_XOffset(x) |
 
518
        PM3RectanglePosition_YOffset(y),
 
519
        PM3RectanglePosition);
 
520
    GLINT_WRITE_REG(
 
521
        PM3Render2D_SpanOperation |
 
522
        PM3Render2D_XPositive |
 
523
        PM3Render2D_YPositive |
 
524
        PM3Render2D_Operation_SyncOnHostData |
 
525
        PM3Render2D_Width(w) | PM3Render2D_Height(h),
 
526
        PM3Render2D);
 
527
}
 
528
 
 
529
static void
 
530
HWCopyYV12(ScrnInfoPtr pScrn, CARD8 *Y, int w, int h)
 
531
{
 
532
    GLINTPtr pGlint = GLINTPTR(pScrn);
 
533
    int size = w * h;
 
534
    CARD8 *V = Y + size;
 
535
    CARD8 *U = V + (size >> 2);
 
536
    CARD32 *dst;
 
537
    int pass2 = 0;
 
538
    int dwords, i, x = 0;
 
539
 
 
540
    dwords = size >> 1;
 
541
 
 
542
    w >>= 1;
 
543
 
 
544
    while (dwords >= pGlint->FIFOSize) {
 
545
        dst = (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4);
 
546
        GLINT_WAIT(pGlint->FIFOSize);
 
547
        /* (0x15 << 4) | 0x05 is the TAG for FBSourceData */
 
548
        GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) |
 
549
            0x05, OutputFIFO);
 
550
        for (i = pGlint->FIFOSize - 1; i; i--, Y += 2, x++) {
 
551
            if (x == w) {
 
552
                x = 0;
 
553
                if (pass2 == 0)
 
554
                    pass2 = 1;
 
555
                else
 
556
                if (pass2 == 1) {
 
557
                    pass2 = 0;
 
558
                    U += w;
 
559
                    V += w;
 
560
                }
 
561
            }
 
562
            *dst++ = Y[0] + (U[x] << 8) + (Y[1] << 16) + (V[x] << 24);
 
563
        }
 
564
        dwords -= pGlint->FIFOSize - 1;
 
565
    }
 
566
    if (dwords) {
 
567
        dst = (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4);
 
568
        GLINT_WAIT(dwords + 1);
 
569
        /* (0x15 << 4) | 0x05 is the TAG for FBSourceData */
 
570
        GLINT_WRITE_REG(((dwords - 1) << 16) | (0x15 << 4) |
 
571
            0x05, OutputFIFO);
 
572
        for (i = dwords; i; i--, Y += 2, x++) {
 
573
            if (x == w) {
 
574
                x = 0;
 
575
                if (pass2 == 0)
 
576
                    pass2 = 1;
 
577
                else
 
578
                if (pass2 == 1) {
 
579
                    pass2 = 0;
 
580
                    U += w;
 
581
                    V += w;
 
582
                }
 
583
            }
 
584
            *dst++ = Y[0] + (U[x] << 8) + (Y[1] << 16) + (V[x] << 24);
 
585
        }
 
586
    }
 
587
}
 
588
 
 
589
static void
 
590
HWCopyFlat(ScrnInfoPtr pScrn, CARD8 *src, int w, int h)
 
591
{
 
592
    GLINTPtr pGlint = GLINTPTR(pScrn);
 
593
    GLINTPortPrivPtr pPriv = pGlint->adaptor->pPortPrivates[0].ptr;
 
594
    int pitch = pScrn->displayWidth;
 
595
    CARD8 *tmp_src;
 
596
    int dwords;
 
597
 
 
598
    if (w == pitch) {
 
599
        dwords = (w * h) >> (2 - pPriv->Video_Shift);
 
600
        while(dwords >= pGlint->FIFOSize) {
 
601
            GLINT_WAIT(pGlint->FIFOSize);
 
602
            GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) |
 
603
                        0x05, OutputFIFO);
 
604
            GLINT_MoveDWORDS(
 
605
                (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
 
606
                (CARD32*)src, pGlint->FIFOSize - 1);
 
607
            dwords -= (pGlint->FIFOSize - 1);
 
608
            src += (pGlint->FIFOSize << 2) - 4;
 
609
        }
 
610
        if(dwords) {
 
611
            GLINT_WAIT(dwords + 1);
 
612
            GLINT_WRITE_REG(((dwords - 1) << 16)|(0x15 << 4) |0x05, OutputFIFO);
 
613
            GLINT_MoveDWORDS(
 
614
                (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
 
615
                (CARD32*)src, dwords);
 
616
        }
 
617
    } else {
 
618
        while (h--) {
 
619
            tmp_src = src;
 
620
            dwords = w >> (2 - pPriv->Video_Shift);
 
621
            while(dwords >= pGlint->FIFOSize) {
 
622
                GLINT_WAIT(pGlint->FIFOSize);
 
623
                GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) |
 
624
                        0x05, OutputFIFO);
 
625
                GLINT_MoveDWORDS(
 
626
                        (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
 
627
                        (CARD32*)src, pGlint->FIFOSize - 1);
 
628
                dwords -= (pGlint->FIFOSize - 1);
 
629
                src += (pGlint->FIFOSize << 2) - 4;
 
630
            }
 
631
            if(dwords) {
 
632
                GLINT_WAIT(dwords + 1);
 
633
                GLINT_WRITE_REG(((dwords-1)<<16)|(0x15<<4) | 0x05, OutputFIFO);
 
634
                GLINT_MoveDWORDS(
 
635
                        (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
 
636
                        (CARD32*)src, dwords);
 
637
            }
 
638
            src = tmp_src + (w << pPriv->Video_Shift);
 
639
        }
 
640
    }
 
641
}
 
642
 
 
643
static FBAreaPtr
 
644
Permedia3AllocateMemory(ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height)
 
645
{
 
646
  ScreenPtr pScreen;
 
647
  FBAreaPtr new_area;
 
648
 
 
649
  if (area) {
 
650
    if ((area->box.x2 - area->box.x1 >= width) &&
 
651
        (area->box.y2 - area->box.y1 >= height))
 
652
      return area;
 
653
 
 
654
    if (xf86ResizeOffscreenArea(area, width, height))
 
655
      return area;
 
656
 
 
657
    xf86FreeOffscreenArea(area);
 
658
  }
 
659
 
 
660
  pScreen = screenInfo.screens[pScrn->scrnIndex];
 
661
 
 
662
  new_area = xf86AllocateOffscreenArea(pScreen, width, height, pScrn->bitsPerPixel / 8, NULL, NULL, NULL);
 
663
 
 
664
  if (!new_area) {
 
665
    int max_width, max_height;
 
666
 
 
667
    xf86QueryLargestOffscreenArea(pScreen, &max_width, &max_height, pScrn->bitsPerPixel / 8, 0, PRIORITY_EXTREME);
 
668
 
 
669
    if (max_width < width || max_height < height)
 
670
      return NULL;
 
671
 
 
672
    xf86PurgeUnlockedOffscreenAreas(pScreen);
 
673
    new_area = xf86AllocateOffscreenArea(pScreen, width, height, pScrn->bitsPerPixel / 8, NULL, NULL, NULL);
 
674
  }
 
675
 
 
676
  return new_area;
 
677
}
 
678
 
 
679
#define FORMAT_RGB8888  PM3VideoOverlayMode_COLORFORMAT_RGB8888 
 
680
#define FORMAT_RGB4444  PM3VideoOverlayMode_COLORFORMAT_RGB4444
 
681
#define FORMAT_RGB5551  PM3VideoOverlayMode_COLORFORMAT_RGB5551
 
682
#define FORMAT_RGB565   PM3VideoOverlayMode_COLORFORMAT_RGB565
 
683
#define FORMAT_RGB332   PM3VideoOverlayMode_COLORFORMAT_RGB332
 
684
#define FORMAT_BGR8888  PM3VideoOverlayMode_COLORFORMAT_BGR8888
 
685
#define FORMAT_BGR4444  PM3VideoOverlayMode_COLORFORMAT_BGR4444
 
686
#define FORMAT_BGR5551  PM3VideoOverlayMode_COLORFORMAT_BGR5551
 
687
#define FORMAT_BGR565   PM3VideoOverlayMode_COLORFORMAT_BGR565
 
688
#define FORMAT_BGR332   PM3VideoOverlayMode_COLORFORMAT_BGR332
 
689
#define FORMAT_CI8      PM3VideoOverlayMode_COLORFORMAT_CI8
 
690
#define FORMAT_VUY444   PM3VideoOverlayMode_COLORFORMAT_VUY444
 
691
#define FORMAT_YUV444   PM3VideoOverlayMode_COLORFORMAT_YUV444
 
692
#define FORMAT_VUY422   PM3VideoOverlayMode_COLORFORMAT_VUY422
 
693
#define FORMAT_YUV422   PM3VideoOverlayMode_COLORFORMAT_YUV422
 
694
 
 
695
/* Notice, have to check that we dont overflow the deltas here ... */
 
696
static void
 
697
compute_scale_factor(
 
698
    short* src_w, short* dst_w,
 
699
    unsigned int* shrink_delta, unsigned int* zoom_delta)
 
700
{
 
701
    /* NOTE: If we don't return reasonable values here then the video
 
702
     * unit can potential shut off and won't display an image until re-enabled.
 
703
     * Seems as though the zoom_delta is o.k, and I've not had the problem.
 
704
     * The 'shrink_delta' is prone to this the most - FIXME ! */
 
705
 
 
706
    if (*src_w >= *dst_w) {
 
707
        *src_w &= ~0x3;
 
708
        *dst_w &= ~0x3;
 
709
        *shrink_delta = (((*src_w << 16) / *dst_w) + 0x0f) & 0x0ffffff0;
 
710
        *zoom_delta = 1<<16;
 
711
        if ( ((*shrink_delta * *dst_w) >> 16) & 0x03 )
 
712
            *shrink_delta += 0x10;
 
713
    } else {
 
714
        *src_w &= ~0x3;
 
715
        *dst_w &= ~0x3;
 
716
        *zoom_delta = (((*src_w << 16) / *dst_w) + 0x0f) & 0x0001fff0;
 
717
        *shrink_delta = 1<<16;
 
718
        if ( ((*zoom_delta * *dst_w) >> 16) & 0x03 )
 
719
            *zoom_delta += 0x10;
 
720
    }
 
721
}
 
722
 
 
723
static void
 
724
Permedia3DisplayVideo(
 
725
    ScrnInfoPtr pScrn,
 
726
    int id,
 
727
    int offset,
 
728
    short width, short height,
 
729
    int x1, int y1, int x2, int y2,
 
730
    BoxPtr dstBox,
 
731
    short src_w, short src_h,
 
732
    short drw_w, short drw_h
 
733
){
 
734
    GLINTPtr pGlint = GLINTPTR(pScrn);
 
735
    GLINTPortPrivPtr portPriv = pGlint->adaptor->pPortPrivates[0].ptr;
 
736
    unsigned int shrink, zoom;
 
737
    unsigned int newx1, newx2;
 
738
 
 
739
    /* Let's overlay only to visible parts of the screen */
 
740
    if (dstBox->x1 == 0) {
 
741
        x1 = drw_w - dstBox->x2;
 
742
        drw_w = dstBox->x2;
 
743
    }
 
744
    if (dstBox->x2 == pScrn->frameX1) {
 
745
        x2 = drw_w - (dstBox->x2 - dstBox->x1);
 
746
        drw_w = (dstBox->x2 - dstBox->x1);
 
747
    }
 
748
 
 
749
    /* Let's adjust the width of source and dest to be compliant with 
 
750
     * the Permedia3 overlay unit requirement, and compute the X deltas. */
 
751
    newx1 = src_w; newx2 = drw_w;
 
752
    compute_scale_factor(&src_w, &drw_w, &shrink, &zoom);
 
753
    dstBox->x2 -= (newx2 - drw_w);
 
754
 
 
755
    /* We do a long wait here - for everything that needs to be written */
 
756
    GLINT_WAIT(39);
 
757
    GLINT_WRITE_REG(offset>>portPriv->Video_Shift,
 
758
        portPriv->buffer ? PM3VideoOverlayBase1 : PM3VideoOverlayBase0);
 
759
    /* Let's set the source pitch. */
 
760
    GLINT_WRITE_REG(PM3VideoOverlayStride_STRIDE(pScrn->displayWidth<< 
 
761
        (pScrn->bitsPerPixel>>4) >>portPriv->Video_Shift), 
 
762
        PM3VideoOverlayStride);
 
763
    /* Let's set the position and size of the visible part of the source. */
 
764
    GLINT_WRITE_REG(PM3VideoOverlayWidth_WIDTH(src_w),
 
765
        PM3VideoOverlayWidth);
 
766
    GLINT_WRITE_REG(PM3VideoOverlayHeight_HEIGHT(src_h),
 
767
        PM3VideoOverlayHeight);
 
768
    GLINT_WRITE_REG(
 
769
        PM3VideoOverlayOrigin_XORIGIN(x1) |
 
770
        PM3VideoOverlayOrigin_YORIGIN(y1),
 
771
        PM3VideoOverlayOrigin);
 
772
    /* Scale the source to the destinationsize */
 
773
    if (src_h == drw_h) {
 
774
        GLINT_WRITE_REG(
 
775
            PM3VideoOverlayYDelta_NONE,
 
776
            PM3VideoOverlayYDelta);
 
777
    } else {
 
778
        GLINT_WRITE_REG(
 
779
            PM3VideoOverlayYDelta_DELTA(src_h,drw_h),
 
780
            PM3VideoOverlayYDelta);
 
781
    }
 
782
    if (src_w == drw_w) {
 
783
        GLINT_WRITE_REG(1<<16, PM3VideoOverlayShrinkXDelta);
 
784
        GLINT_WRITE_REG(1<<16, PM3VideoOverlayZoomXDelta);
 
785
    } else {
 
786
        GLINT_WRITE_REG(shrink, PM3VideoOverlayShrinkXDelta);
 
787
        GLINT_WRITE_REG(zoom, PM3VideoOverlayZoomXDelta);
 
788
    }
 
789
    GLINT_WRITE_REG(portPriv->buffer, PM3VideoOverlayIndex);
 
790
 
 
791
    /* Now set the ramdac video overlay region and mode */
 
792
    RAMDAC_WRITE((dstBox->x1&0xff), PM3RD_VideoOverlayXStartLow);
 
793
    RAMDAC_WRITE((dstBox->x1&0xf00)>>8, PM3RD_VideoOverlayXStartHigh);
 
794
    RAMDAC_WRITE((dstBox->x2&0xff), PM3RD_VideoOverlayXEndLow);
 
795
    RAMDAC_WRITE((dstBox->x2&0xf00)>>8,PM3RD_VideoOverlayXEndHigh);
 
796
    RAMDAC_WRITE((dstBox->y1&0xff), PM3RD_VideoOverlayYStartLow); 
 
797
    RAMDAC_WRITE((dstBox->y1&0xf00)>>8, PM3RD_VideoOverlayYStartHigh);
 
798
    RAMDAC_WRITE((dstBox->y2&0xff), PM3RD_VideoOverlayYEndLow); 
 
799
    RAMDAC_WRITE((dstBox->y2&0xf00)>>8,PM3RD_VideoOverlayYEndHigh);
 
800
 
 
801
    GLINT_WRITE_REG(portPriv->Video_Shift << 5 |
 
802
        portPriv->Format |
 
803
        portPriv->Filter |
 
804
        PM3VideoOverlayMode_BUFFERSYNC_MANUAL |
 
805
        PM3VideoOverlayMode_FLIP_VIDEO |
 
806
        PM3VideoOverlayMode_ENABLE,
 
807
        PM3VideoOverlayMode);
 
808
 
 
809
    if (!portPriv->ramdacOn) {
 
810
        RAMDAC_WRITE(PM3RD_VideoOverlayControl_ENABLE |
 
811
                PM3RD_VideoOverlayControl_KEY_COLOR |
 
812
                PM3RD_VideoOverlayControl_MODE_MAINKEY |
 
813
                PM3RD_VideoOverlayControl_DIRECTCOLOR_ENABLED,
 
814
                PM3RD_VideoOverlayControl);
 
815
        portPriv->ramdacOn = TRUE;
 
816
    }
 
817
    GLINT_WRITE_REG(PM3VideoOverlayUpdate_ENABLE,
 
818
        PM3VideoOverlayUpdate);
 
819
}
 
820
 
 
821
static int 
 
822
Permedia3PutImage( 
 
823
  ScrnInfoPtr pScrn, 
 
824
  short src_x, short src_y, 
 
825
  short drw_x, short drw_y,
 
826
  short src_w, short src_h, 
 
827
  short drw_w, short drw_h,
 
828
  int id, unsigned char* buf, 
 
829
  short width, short height, 
 
830
  Bool sync,
 
831
  RegionPtr clipBoxes, pointer data
 
832
){
 
833
#if 0
 
834
   GLINTPtr pGlint = GLINTPTR(pScrn);
 
835
#endif
 
836
   GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data;
 
837
   INT32 x1, x2, y1, y2;
 
838
   int pitch;
 
839
   int i;
 
840
   int w_bpp, bpp;
 
841
   Bool copy_flat = TRUE;
 
842
   BoxRec dstBox;
 
843
 
 
844
   /* Let's find the image format and Video_Shift values */
 
845
   switch (id) {
 
846
        case LE4CC('Y','V','1','2'):
 
847
            pPriv->Format = FORMAT_YUV422;
 
848
            pPriv->Video_Shift = 1;
 
849
            copy_flat = FALSE;
 
850
            break;
 
851
        case LE4CC('Y','U','Y','2'):
 
852
            pPriv->Format = FORMAT_YUV422;
 
853
            pPriv->Video_Shift = 1;
 
854
            break;
 
855
        case LE4CC('U','Y','V','Y'):
 
856
            pPriv->Format = FORMAT_VUY422;
 
857
            pPriv->Video_Shift = 1;
 
858
            break;
 
859
        case LE4CC('Y','U','V','A'):
 
860
            pPriv->Format = FORMAT_YUV444;
 
861
            pPriv->Video_Shift = 2;
 
862
            break;
 
863
        case LE4CC('V','U','Y','A'):
 
864
            pPriv->Format = FORMAT_VUY444;
 
865
            pPriv->Video_Shift = 2;
 
866
            break;
 
867
        case 0x41: /* RGBA 8:8:8:8 */
 
868
            pPriv->Format = FORMAT_RGB8888;
 
869
            pPriv->Video_Shift = 2;
 
870
            break;
 
871
        case 0x42: /* RGB 5:6:5 */
 
872
            pPriv->Format = FORMAT_RGB565;
 
873
            pPriv->Video_Shift = 1;
 
874
            break;
 
875
        case 0x43: /* RGB 1:5:5:5 */
 
876
            pPriv->Format = FORMAT_RGB5551;
 
877
            pPriv->Video_Shift = 1;
 
878
            break;
 
879
        case 0x44: /* RGB 4:4:4:4 */
 
880
            pPriv->Format = FORMAT_RGB4444;
 
881
            pPriv->Video_Shift = 1;
 
882
            break;
 
883
        case 0x46: /* RGB 2:3:3 */
 
884
            pPriv->Format = FORMAT_RGB332;
 
885
            pPriv->Video_Shift = 0;
 
886
            break;
 
887
        case 0x47: /* BGRA 8:8:8:8 */
 
888
            pPriv->Format = FORMAT_BGR8888;
 
889
            pPriv->Video_Shift = 2;
 
890
            break;
 
891
        case 0x48: /* BGR 5:6:5 */
 
892
            pPriv->Format = FORMAT_BGR565;
 
893
            pPriv->Video_Shift = 1;
 
894
            break;
 
895
        case 0x49: /* BGR 1:5:5:5 */
 
896
            pPriv->Format = FORMAT_BGR5551;
 
897
            pPriv->Video_Shift = 1;
 
898
            break;
 
899
        case 0x4A: /* BGR 4:4:4:4 */
 
900
            pPriv->Format = FORMAT_BGR4444;
 
901
            pPriv->Video_Shift = 1;
 
902
            break;
 
903
        case 0x4C: /* BGR 2:3:3 */
 
904
            pPriv->Format = FORMAT_BGR332;
 
905
            pPriv->Video_Shift = 0;
 
906
            break;
 
907
        default:
 
908
            return XvBadAlloc;
 
909
    }
 
910
 
 
911
    /* Clip */
 
912
    x1 = src_x;
 
913
    x2 = src_x + src_w;
 
914
    y1 = src_y;
 
915
    y2 = src_y + src_h;
 
916
 
 
917
    dstBox.x1 = drw_x;
 
918
    dstBox.x2 = drw_x + drw_w;
 
919
    dstBox.y1 = drw_y;
 
920
    dstBox.y2 = drw_y + drw_h;
 
921
 
 
922
    if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 
 
923
                              width, height))
 
924
        return Success;
 
925
 
 
926
    dstBox.x1 -= pScrn->frameX0;
 
927
    dstBox.x2 -= pScrn->frameX0;
 
928
    dstBox.y1 -= pScrn->frameY0;
 
929
    dstBox.y2 -= pScrn->frameY0;
 
930
 
 
931
    bpp = pScrn->bitsPerPixel >> 3;
 
932
    pitch = bpp * pScrn->displayWidth;
 
933
 
 
934
    w_bpp = (width << pPriv->Video_Shift) >> (pScrn->bitsPerPixel >> 4);
 
935
 
 
936
    for (i = 0; i < (pPriv->doubleBuffer ? 2 : 1); i++) {
 
937
      if (!(pPriv->area[i] = 
 
938
                Permedia3AllocateMemory(pScrn,pPriv->area[i],w_bpp,src_h)))
 
939
        return BadAlloc;
 
940
 
 
941
      pPriv->offset[i] = (pPriv->area[i]->box.x1 * bpp) + 
 
942
                                        (pPriv->area[i]->box.y1 * pitch);
 
943
    }
 
944
 
 
945
    HWCopySetup(pScrn, pPriv->area[pPriv->buffer]->box.x1, 
 
946
                       pPriv->area[pPriv->buffer]->box.y1, w_bpp, height);
 
947
 
 
948
    if (copy_flat) 
 
949
        HWCopyFlat(pScrn, buf, width, height);
 
950
    else 
 
951
        HWCopyYV12(pScrn, buf, width, height);
 
952
 
 
953
    /* paint the color key */
 
954
    if(pPriv->autopaintColorKey && !RegionsEqual(&pPriv->clip, clipBoxes)) {
 
955
        /* update cliplist */
 
956
        REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
 
957
#if 0
 
958
        GLINT_WAIT(1);
 
959
        GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE,
 
960
                                                PM3VideoOverlayMode);
 
961
        pPriv->ramdacOn = FALSE;
 
962
#endif
 
963
        xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
 
964
    }
 
965
 
 
966
    Permedia3Sync(pScrn);
 
967
 
 
968
    Permedia3DisplayVideo(pScrn, id, pPriv->offset[pPriv->buffer], width,height,
 
969
             x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
 
970
 
 
971
    /* Switch buffer on next run - double buffer */
 
972
    if (pPriv->doubleBuffer) {
 
973
        if (!pPriv->buffer)
 
974
            pPriv->buffer = 1;
 
975
        else
 
976
            pPriv->buffer = 0;
 
977
    }
 
978
 
 
979
    pPriv->videoStatus = CLIENT_VIDEO_ON;
 
980
 
 
981
    return Success;
 
982
}
 
983
 
 
984
static int 
 
985
Permedia3QueryImageAttributes(
 
986
  ScrnInfoPtr pScrn, 
 
987
  int id, 
 
988
  unsigned short *w, unsigned short *h, 
 
989
  int *pitches, int *offsets
 
990
){
 
991
    int size, tmp;
 
992
 
 
993
    if(*w > 2047) *w = 2047;
 
994
    if(*h > 2047) *h = 2047;
 
995
 
 
996
    *w = (*w + 1) & ~1;
 
997
    if(offsets) offsets[0] = 0;
 
998
 
 
999
    switch(id) {
 
1000
    case FOURCC_YV12:           /* YV12 */
 
1001
        *h = (*h + 1) & ~1;
 
1002
        size = (*w + 3) & ~3;
 
1003
        if(pitches) pitches[0] = size;
 
1004
        size *= *h;
 
1005
        if(offsets) offsets[1] = size;
 
1006
        tmp = ((*w >> 1) + 3) & ~3;
 
1007
        if(pitches) pitches[1] = pitches[2] = tmp;
 
1008
        tmp *= (*h >> 1);
 
1009
        size += tmp;
 
1010
        if(offsets) offsets[2] = size;
 
1011
        size += tmp;
 
1012
        break;
 
1013
    default:                    /* RGB15, RGB16, YUY2 */
 
1014
        size = *w << 1;
 
1015
        if(pitches) pitches[0] = size;
 
1016
        size *= *h;
 
1017
        break;
 
1018
    }
 
1019
 
 
1020
    return size;
 
1021
}
 
1022
 
 
1023
/****************** Offscreen stuff ***************/
 
1024
 
 
1025
typedef struct {
 
1026
  FBAreaPtr area;
 
1027
  Bool isOn;
 
1028
  int Video_Shift;
 
1029
  int Format;
 
1030
  Bool ramdacOn;
 
1031
} OffscreenPrivRec, * OffscreenPrivPtr;
 
1032
 
 
1033
static int 
 
1034
Permedia3AllocateSurface(
 
1035
    ScrnInfoPtr pScrn,
 
1036
    int id,
 
1037
    unsigned short w,   
 
1038
    unsigned short h,
 
1039
    XF86SurfacePtr surface
 
1040
){
 
1041
    FBAreaPtr area;
 
1042
    int fbpitch, bpp;
 
1043
    OffscreenPrivPtr pPriv;
 
1044
 
 
1045
    if((w > 2047) || (h > 2047))
 
1046
        return BadAlloc;
 
1047
 
 
1048
    w = (w + 1) & ~1;
 
1049
    bpp = pScrn->bitsPerPixel >> 3;
 
1050
    fbpitch = bpp * pScrn->displayWidth;
 
1051
 
 
1052
    if(!(area = Permedia3AllocateMemory(pScrn, NULL, w, h)))
 
1053
        return BadAlloc;
 
1054
 
 
1055
    surface->width = w;
 
1056
    surface->height = h;
 
1057
 
 
1058
    if(!(surface->offsets = xalloc(sizeof(int)))) {
 
1059
        xf86FreeOffscreenArea(area);
 
1060
        return BadAlloc;
 
1061
    }
 
1062
    if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
 
1063
        xfree(surface->offsets);
 
1064
        xf86FreeOffscreenArea(area);
 
1065
        return BadAlloc;
 
1066
    }
 
1067
 
 
1068
    pPriv->area = area;
 
1069
    pPriv->isOn = FALSE;
 
1070
 
 
1071
    surface->pScrn = pScrn;
 
1072
    surface->id = id;   
 
1073
    surface->offsets[0] = (area->box.x1 * bpp) + (area->box.y1 * fbpitch);
 
1074
    surface->devPrivate.ptr = (pointer)pPriv;
 
1075
 
 
1076
    return Success;
 
1077
}
 
1078
 
 
1079
static int 
 
1080
Permedia3StopSurface(
 
1081
    XF86SurfacePtr surface
 
1082
){
 
1083
    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
 
1084
 
 
1085
    if(pPriv->isOn) {
 
1086
        GLINTPtr pGlint = GLINTPTR(surface->pScrn);
 
1087
        pPriv->ramdacOn = FALSE;
 
1088
        GLINT_WAIT(4);
 
1089
        RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE,
 
1090
                PM3RD_VideoOverlayControl);
 
1091
        GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE,
 
1092
                PM3VideoOverlayMode);
 
1093
        pPriv->isOn = FALSE;
 
1094
    }
 
1095
 
 
1096
    return Success;
 
1097
}
 
1098
 
 
1099
static int 
 
1100
Permedia3FreeSurface(
 
1101
    XF86SurfacePtr surface
 
1102
){
 
1103
    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
 
1104
 
 
1105
    if(pPriv->isOn)
 
1106
        Permedia3StopSurface(surface);
 
1107
    xf86FreeOffscreenArea(pPriv->area);
 
1108
    xfree(surface->pitches);
 
1109
    xfree(surface->offsets);
 
1110
    xfree(surface->devPrivate.ptr);
 
1111
 
 
1112
    return Success;
 
1113
}
 
1114
 
 
1115
static int
 
1116
Permedia3GetSurfaceAttribute(
 
1117
    ScrnInfoPtr pScrn,
 
1118
    Atom attribute,
 
1119
    INT32 *value
 
1120
){
 
1121
    return Permedia3GetPortAttribute(pScrn, attribute, value, 
 
1122
                        (pointer)(GET_PORT_PRIVATE(pScrn)));
 
1123
}
 
1124
 
 
1125
static int
 
1126
Permedia3SetSurfaceAttribute(
 
1127
    ScrnInfoPtr pScrn,
 
1128
    Atom attribute,
 
1129
    INT32 value
 
1130
){
 
1131
    return Permedia3SetPortAttribute(pScrn, attribute, value, 
 
1132
                        (pointer)(GET_PORT_PRIVATE(pScrn)));
 
1133
}
 
1134
 
 
1135
static int 
 
1136
Permedia3DisplaySurface(
 
1137
    XF86SurfacePtr surface,
 
1138
    short src_x, short src_y, 
 
1139
    short drw_x, short drw_y,
 
1140
    short src_w, short src_h, 
 
1141
    short drw_w, short drw_h,
 
1142
    RegionPtr clipBoxes
 
1143
){
 
1144
    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
 
1145
    ScrnInfoPtr pScrn = surface->pScrn;
 
1146
    GLINTPtr pGlint = GLINTPTR(pScrn);
 
1147
    GLINTPortPrivPtr portPriv = pGlint->adaptor->pPortPrivates[0].ptr;
 
1148
    INT32 x1, y1, x2, y2;
 
1149
    BoxRec dstBox;
 
1150
 
 
1151
    x1 = src_x;
 
1152
    x2 = src_x + src_w;
 
1153
    y1 = src_y;
 
1154
    y2 = src_y + src_h;
 
1155
 
 
1156
    dstBox.x1 = drw_x;
 
1157
    dstBox.x2 = drw_x + drw_w;
 
1158
    dstBox.y1 = drw_y;
 
1159
    dstBox.y2 = drw_y + drw_h;
 
1160
 
 
1161
    if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, 
 
1162
                    surface->width, surface->height))
 
1163
    {
 
1164
        return Success;
 
1165
    }
 
1166
 
 
1167
    dstBox.x1 -= pScrn->frameX0;
 
1168
    dstBox.x2 -= pScrn->frameX0;
 
1169
    dstBox.y1 -= pScrn->frameY0;
 
1170
    dstBox.y2 -= pScrn->frameY0;
 
1171
 
 
1172
   /* Let's find the image format and Video_Shift values */
 
1173
   switch (surface->id) {
 
1174
        case LE4CC('Y','V','1','2'):
 
1175
            pPriv->Format = FORMAT_YUV422;
 
1176
            pPriv->Video_Shift = 1;
 
1177
            break;
 
1178
        case LE4CC('Y','U','Y','2'):
 
1179
            pPriv->Format = FORMAT_YUV422;
 
1180
            pPriv->Video_Shift = 1;
 
1181
            break;
 
1182
        case LE4CC('U','Y','V','Y'):
 
1183
            pPriv->Format = FORMAT_VUY422;
 
1184
            pPriv->Video_Shift = 1;
 
1185
            break;
 
1186
        case LE4CC('Y','U','V','A'):
 
1187
            pPriv->Format = FORMAT_YUV444;
 
1188
            pPriv->Video_Shift = 2;
 
1189
            break;
 
1190
        case LE4CC('V','U','Y','A'):
 
1191
            pPriv->Format = FORMAT_VUY444;
 
1192
            pPriv->Video_Shift = 2;
 
1193
            break;
 
1194
        case 0x41: /* RGBA 8:8:8:8 */
 
1195
            pPriv->Format = FORMAT_RGB8888;
 
1196
            pPriv->Video_Shift = 2;
 
1197
            break;
 
1198
        case 0x42: /* RGB 5:6:5 */
 
1199
            pPriv->Format = FORMAT_RGB565;
 
1200
            pPriv->Video_Shift = 1;
 
1201
            break;
 
1202
        case 0x43: /* RGB 1:5:5:5 */
 
1203
            pPriv->Format = FORMAT_RGB5551;
 
1204
            pPriv->Video_Shift = 1;
 
1205
            break;
 
1206
        case 0x44: /* RGB 4:4:4:4 */
 
1207
            pPriv->Format = FORMAT_RGB4444;
 
1208
            pPriv->Video_Shift = 1;
 
1209
            break;
 
1210
        case 0x46: /* RGB 2:3:3 */
 
1211
            pPriv->Format = FORMAT_RGB332;
 
1212
            pPriv->Video_Shift = 0;
 
1213
            break;
 
1214
        case 0x47: /* BGRA 8:8:8:8 */
 
1215
            pPriv->Format = FORMAT_BGR8888;
 
1216
            pPriv->Video_Shift = 2;
 
1217
            break;
 
1218
        case 0x48: /* BGR 5:6:5 */
 
1219
            pPriv->Format = FORMAT_BGR565;
 
1220
            pPriv->Video_Shift = 1;
 
1221
            break;
 
1222
        case 0x49: /* BGR 1:5:5:5 */
 
1223
            pPriv->Format = FORMAT_BGR5551;
 
1224
            pPriv->Video_Shift = 1;
 
1225
            break;
 
1226
        case 0x4A: /* BGR 4:4:4:4 */
 
1227
            pPriv->Format = FORMAT_BGR4444;
 
1228
            pPriv->Video_Shift = 1;
 
1229
            break;
 
1230
        case 0x4C: /* BGR 2:3:3 */
 
1231
            pPriv->Format = FORMAT_BGR332;
 
1232
            pPriv->Video_Shift = 0;
 
1233
            break;
 
1234
        default:
 
1235
            return XvBadAlloc;
 
1236
    }
 
1237
 
 
1238
    Permedia3DisplayVideo(pScrn, surface->id, surface->offsets[0], 
 
1239
             surface->width, surface->height, 
 
1240
             x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
 
1241
 
 
1242
    xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
 
1243
 
 
1244
    pPriv->isOn = TRUE;
 
1245
    /* we've prempted the XvImage stream so set its free timer */
 
1246
    if(portPriv->videoStatus & CLIENT_VIDEO_ON) {
 
1247
        REGION_EMPTY(pScrn->pScreen, &portPriv->clip);   
 
1248
        UpdateCurrentTime();
 
1249
        portPriv->videoStatus = FREE_TIMER;
 
1250
        portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
 
1251
        pGlint->VideoTimerCallback = Permedia3VideoTimerCallback;
 
1252
    }
 
1253
 
 
1254
    return Success;
 
1255
}
 
1256
 
 
1257
static void 
 
1258
Permedia3InitOffscreenImages(ScreenPtr pScreen)
 
1259
{
 
1260
    XF86OffscreenImagePtr offscreenImages;
 
1261
 
 
1262
    /* need to free this someplace */
 
1263
    if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
 
1264
        return;
 
1265
 
 
1266
    offscreenImages[0].image = &Images[0];
 
1267
    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 
 
1268
                               VIDEO_CLIP_TO_VIEWPORT;
 
1269
    offscreenImages[0].alloc_surface = Permedia3AllocateSurface;
 
1270
    offscreenImages[0].free_surface = Permedia3FreeSurface;
 
1271
    offscreenImages[0].display = Permedia3DisplaySurface;
 
1272
    offscreenImages[0].stop = Permedia3StopSurface;
 
1273
    offscreenImages[0].setAttribute = Permedia3SetSurfaceAttribute;
 
1274
    offscreenImages[0].getAttribute = Permedia3GetSurfaceAttribute;
 
1275
    offscreenImages[0].max_width = 2047;
 
1276
    offscreenImages[0].max_height = 2047;
 
1277
    offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
 
1278
    offscreenImages[0].attributes = Attributes;
 
1279
    
 
1280
    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
 
1281
}
 
1282
 
 
1283
static void
 
1284
Permedia3VideoTimerCallback(ScrnInfoPtr pScrn, Time time)
 
1285
{
 
1286
    GLINTPtr pGlint = GLINTPTR(pScrn);
 
1287
    GLINTPortPrivPtr pPriv = pGlint->adaptor->pPortPrivates[0].ptr;
 
1288
    int i;
 
1289
 
 
1290
    if(pPriv->videoStatus & TIMER_MASK) {
 
1291
        if(pPriv->videoStatus & OFF_TIMER) {
 
1292
            if(pPriv->offTime < time) {
 
1293
                pPriv->ramdacOn = FALSE;
 
1294
                GLINT_WAIT(4);
 
1295
                RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE,
 
1296
                                        PM3RD_VideoOverlayControl);
 
1297
                GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE,
 
1298
                                        PM3VideoOverlayMode);
 
1299
                pPriv->videoStatus = FREE_TIMER;
 
1300
                pPriv->freeTime = time + FREE_DELAY;
 
1301
            }
 
1302
        } else {  /* FREE_TIMER */
 
1303
            if(pPriv->freeTime < time) {
 
1304
                for (i = 0; i < (pPriv->doubleBuffer ? 2 : 1); i++) {
 
1305
                   if(pPriv->area[i]) {
 
1306
                      xf86FreeOffscreenArea(pPriv->area[i]);
 
1307
                      pPriv->area[i] = NULL;
 
1308
                   }
 
1309
                }
 
1310
                pPriv->videoStatus = 0;
 
1311
                pGlint->VideoTimerCallback = NULL;
 
1312
            }
 
1313
        }
 
1314
    } else  /* shouldn't get here */
 
1315
        pGlint->VideoTimerCallback = NULL;
 
1316
}
 
1317
 
 
1318
#endif  /* !XvExtension */