2
* Copyright 2001 by Alan Hourihane, Sychdyn, North Wales.
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.
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.
22
* Authors: Alan Hourihane, alanh@fairlite.demon.co.uk
23
* Sven Luther <luther@dpt-info.u-strasbg.fr>
25
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/glint/pm3_video.c,v 1.11 2002/05/22 08:12:02 alanh Exp $ */
28
#include "xf86_OSproc.h"
29
#include "xf86Resources.h"
30
#include "xf86_ansic.h"
32
#include "xf86PciInfo.h"
34
#include "xf86fbman.h"
35
#include "regionstr.h"
38
#include "glint_regs.h"
43
#include "dixstruct.h"
46
#define OFF_DELAY 200 /* milliseconds */
47
#define FREE_DELAY 60000
49
#define OFF_TIMER 0x01
50
#define FREE_TIMER 0x02
51
#define CLIENT_VIDEO_ON 0x04
53
#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
56
void Permedia3InitVideo(ScreenPtr pScreen) {}
57
void Permedia3ResetVideo(ScrnInfoPtr pScrn) {}
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);
74
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
76
static Atom xvColorKey, xvDoubleBuffer, xvAutopaintColorKey, xvFilter;
78
void Permedia3InitVideo(ScreenPtr pScreen)
80
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
81
XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
82
XF86VideoAdaptorPtr newAdaptor = NULL;
83
GLINTPtr pGlint = GLINTPTR(pScrn);
86
/* Because of bugs in the PM3 when uploading images via the
87
* bypass to the framebuffer, we always have to use the accelerator.
92
newAdaptor = Permedia3SetupImageVideo(pScreen);
93
Permedia3InitOffscreenImages(pScreen);
95
num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
100
adaptors = &newAdaptor;
102
newAdaptors = /* need to free this someplace */
103
xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*));
105
memcpy(newAdaptors, adaptors, num_adaptors *
106
sizeof(XF86VideoAdaptorPtr));
107
newAdaptors[num_adaptors] = newAdaptor;
108
adaptors = newAdaptors;
115
xf86XVScreenInit(pScreen, adaptors, num_adaptors);
121
/* client libraries expect an encoding */
122
static XF86VideoEncodingRec DummyEncoding[1] =
132
#define NUM_FORMATS 4
134
static XF86VideoFormatRec Formats[NUM_FORMATS] =
136
{8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
139
#define NUM_ATTRIBUTES 4
141
static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
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"},
150
* FOURCC from http://www.webartz.com/fourcc
151
* Generic GUID for legacy FOURCC XXXXXXXX-0000-0010-8000-00AA00389B71
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 }
156
#define NoOrder LSBFirst
158
#define NUM_IMAGES 15
160
static XF86ImageRec Images[NUM_IMAGES] =
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
238
#define MAX_BUFFERS 2
241
FBAreaPtr area[MAX_BUFFERS];
251
Bool autopaintColorKey;
254
int offset[MAX_BUFFERS];
256
} GLINTPortPrivRec, *GLINTPortPrivPtr;
258
#define GET_PORT_PRIVATE(pScrn) \
259
(GLINTPortPrivPtr)((GLINTPTR(pScrn))->adaptor->pPortPrivates[0].ptr)
261
#define RAMDAC_WRITE(data,index) \
263
GLINT_WRITE_REG(((index)>>8)&0xff, PM3RD_IndexHigh); \
264
GLINT_WRITE_REG((index)&0xff, PM3RD_IndexLow); \
265
GLINT_WRITE_REG(data, PM3RD_IndexedData); \
268
void Permedia3ResetVideo(ScrnInfoPtr pScrn)
270
GLINTPtr pGlint = GLINTPTR(pScrn);
271
GLINTPortPrivPtr pPriv = pGlint->adaptor->pPortPrivates[0].ptr;
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);
285
static XF86VideoAdaptorPtr
286
Permedia3SetupImageVideo(ScreenPtr pScreen)
288
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
289
GLINTPtr pGlint = GLINTPTR(pScrn);
290
XF86VideoAdaptorPtr adapt;
291
GLINTPortPrivPtr pPriv;
293
if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
294
sizeof(GLINTPortPrivRec) +
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;
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;
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;
332
/* gotta uninit this someplace */
333
REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
335
pGlint->adaptor = adapt;
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");
342
Permedia3ResetVideo(pScrn);
349
RegionsEqual(RegionPtr A, RegionPtr B)
354
num = REGION_NUM_RECTS(A);
355
if(num != REGION_NUM_RECTS(B))
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))
364
dataA = (int*)REGION_RECTS(A);
365
dataB = (int*)REGION_RECTS(B);
368
if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
378
Permedia3StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown)
380
GLINTPtr pGlint = GLINTPTR(pScrn);
381
GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data;
384
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
387
if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
388
pPriv->ramdacOn = FALSE;
390
RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE,
391
PM3RD_VideoOverlayControl);
392
GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE,
393
PM3VideoOverlayMode);
395
for (i = 0; i < (pPriv->doubleBuffer ? 2 : 1); i++) {
397
xf86FreeOffscreenArea(pPriv->area[i]);
398
pPriv->area[i] = NULL;
401
pPriv->videoStatus = 0;
403
if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
404
pPriv->videoStatus |= OFF_TIMER;
405
pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
411
Permedia3SetPortAttribute(
417
GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data;
418
GLINTPtr pGlint = GLINTPTR(pScrn);
420
if (attribute == xvDoubleBuffer)
422
if ((value < 0) || (value > 1))
424
pPriv->doubleBuffer = value;
426
else if (attribute == xvColorKey)
428
pPriv->colorKey = value;
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);
435
else if (attribute == xvAutopaintColorKey)
437
if ((value < 0) || (value > 1))
439
pPriv->autopaintColorKey = value;
441
else if (attribute == xvFilter)
443
if ((value < 0) || (value > 2))
447
pPriv->Filter = PM3VideoOverlayMode_FILTER_OFF;
450
pPriv->Filter = PM3VideoOverlayMode_FILTER_FULL;
453
pPriv->Filter = PM3VideoOverlayMode_FILTER_PARTIAL;
464
Permedia3GetPortAttribute(
470
GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data;
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;
487
Permedia3QueryBestSize(
490
short vid_w, short vid_h,
491
short drw_w, short drw_h,
492
unsigned int *p_w, unsigned int *p_h,
495
if(vid_w > (drw_w << 3))
497
if(vid_h > (drw_h << 3))
505
HWCopySetup(ScrnInfoPtr pScrn, int x, int y, int w, int h)
507
GLINTPtr pGlint = GLINTPTR(pScrn);
510
GLINT_WRITE_REG(0xffffffff, FBHardwareWriteMask);
512
PM3Config2D_ForegroundROPEnable |
513
PM3Config2D_ForegroundROP(GXcopy) |
514
PM3Config2D_FBWriteEnable,
517
PM3RectanglePosition_XOffset(x) |
518
PM3RectanglePosition_YOffset(y),
519
PM3RectanglePosition);
521
PM3Render2D_SpanOperation |
522
PM3Render2D_XPositive |
523
PM3Render2D_YPositive |
524
PM3Render2D_Operation_SyncOnHostData |
525
PM3Render2D_Width(w) | PM3Render2D_Height(h),
530
HWCopyYV12(ScrnInfoPtr pScrn, CARD8 *Y, int w, int h)
532
GLINTPtr pGlint = GLINTPTR(pScrn);
535
CARD8 *U = V + (size >> 2);
538
int dwords, i, x = 0;
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) |
550
for (i = pGlint->FIFOSize - 1; i; i--, Y += 2, x++) {
562
*dst++ = Y[0] + (U[x] << 8) + (Y[1] << 16) + (V[x] << 24);
564
dwords -= pGlint->FIFOSize - 1;
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) |
572
for (i = dwords; i; i--, Y += 2, x++) {
584
*dst++ = Y[0] + (U[x] << 8) + (Y[1] << 16) + (V[x] << 24);
590
HWCopyFlat(ScrnInfoPtr pScrn, CARD8 *src, int w, int h)
592
GLINTPtr pGlint = GLINTPTR(pScrn);
593
GLINTPortPrivPtr pPriv = pGlint->adaptor->pPortPrivates[0].ptr;
594
int pitch = pScrn->displayWidth;
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) |
605
(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
606
(CARD32*)src, pGlint->FIFOSize - 1);
607
dwords -= (pGlint->FIFOSize - 1);
608
src += (pGlint->FIFOSize << 2) - 4;
611
GLINT_WAIT(dwords + 1);
612
GLINT_WRITE_REG(((dwords - 1) << 16)|(0x15 << 4) |0x05, OutputFIFO);
614
(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
615
(CARD32*)src, dwords);
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) |
626
(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
627
(CARD32*)src, pGlint->FIFOSize - 1);
628
dwords -= (pGlint->FIFOSize - 1);
629
src += (pGlint->FIFOSize << 2) - 4;
632
GLINT_WAIT(dwords + 1);
633
GLINT_WRITE_REG(((dwords-1)<<16)|(0x15<<4) | 0x05, OutputFIFO);
635
(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
636
(CARD32*)src, dwords);
638
src = tmp_src + (w << pPriv->Video_Shift);
644
Permedia3AllocateMemory(ScrnInfoPtr pScrn, FBAreaPtr area, int width, int height)
650
if ((area->box.x2 - area->box.x1 >= width) &&
651
(area->box.y2 - area->box.y1 >= height))
654
if (xf86ResizeOffscreenArea(area, width, height))
657
xf86FreeOffscreenArea(area);
660
pScreen = screenInfo.screens[pScrn->scrnIndex];
662
new_area = xf86AllocateOffscreenArea(pScreen, width, height, pScrn->bitsPerPixel / 8, NULL, NULL, NULL);
665
int max_width, max_height;
667
xf86QueryLargestOffscreenArea(pScreen, &max_width, &max_height, pScrn->bitsPerPixel / 8, 0, PRIORITY_EXTREME);
669
if (max_width < width || max_height < height)
672
xf86PurgeUnlockedOffscreenAreas(pScreen);
673
new_area = xf86AllocateOffscreenArea(pScreen, width, height, pScrn->bitsPerPixel / 8, NULL, NULL, NULL);
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
695
/* Notice, have to check that we dont overflow the deltas here ... */
697
compute_scale_factor(
698
short* src_w, short* dst_w,
699
unsigned int* shrink_delta, unsigned int* zoom_delta)
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 ! */
706
if (*src_w >= *dst_w) {
709
*shrink_delta = (((*src_w << 16) / *dst_w) + 0x0f) & 0x0ffffff0;
711
if ( ((*shrink_delta * *dst_w) >> 16) & 0x03 )
712
*shrink_delta += 0x10;
716
*zoom_delta = (((*src_w << 16) / *dst_w) + 0x0f) & 0x0001fff0;
717
*shrink_delta = 1<<16;
718
if ( ((*zoom_delta * *dst_w) >> 16) & 0x03 )
724
Permedia3DisplayVideo(
728
short width, short height,
729
int x1, int y1, int x2, int y2,
731
short src_w, short src_h,
732
short drw_w, short drw_h
734
GLINTPtr pGlint = GLINTPTR(pScrn);
735
GLINTPortPrivPtr portPriv = pGlint->adaptor->pPortPrivates[0].ptr;
736
unsigned int shrink, zoom;
737
unsigned int newx1, newx2;
739
/* Let's overlay only to visible parts of the screen */
740
if (dstBox->x1 == 0) {
741
x1 = drw_w - dstBox->x2;
744
if (dstBox->x2 == pScrn->frameX1) {
745
x2 = drw_w - (dstBox->x2 - dstBox->x1);
746
drw_w = (dstBox->x2 - dstBox->x1);
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);
755
/* We do a long wait here - for everything that needs to be written */
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);
769
PM3VideoOverlayOrigin_XORIGIN(x1) |
770
PM3VideoOverlayOrigin_YORIGIN(y1),
771
PM3VideoOverlayOrigin);
772
/* Scale the source to the destinationsize */
773
if (src_h == drw_h) {
775
PM3VideoOverlayYDelta_NONE,
776
PM3VideoOverlayYDelta);
779
PM3VideoOverlayYDelta_DELTA(src_h,drw_h),
780
PM3VideoOverlayYDelta);
782
if (src_w == drw_w) {
783
GLINT_WRITE_REG(1<<16, PM3VideoOverlayShrinkXDelta);
784
GLINT_WRITE_REG(1<<16, PM3VideoOverlayZoomXDelta);
786
GLINT_WRITE_REG(shrink, PM3VideoOverlayShrinkXDelta);
787
GLINT_WRITE_REG(zoom, PM3VideoOverlayZoomXDelta);
789
GLINT_WRITE_REG(portPriv->buffer, PM3VideoOverlayIndex);
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);
801
GLINT_WRITE_REG(portPriv->Video_Shift << 5 |
804
PM3VideoOverlayMode_BUFFERSYNC_MANUAL |
805
PM3VideoOverlayMode_FLIP_VIDEO |
806
PM3VideoOverlayMode_ENABLE,
807
PM3VideoOverlayMode);
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;
817
GLINT_WRITE_REG(PM3VideoOverlayUpdate_ENABLE,
818
PM3VideoOverlayUpdate);
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,
831
RegionPtr clipBoxes, pointer data
834
GLINTPtr pGlint = GLINTPTR(pScrn);
836
GLINTPortPrivPtr pPriv = (GLINTPortPrivPtr)data;
837
INT32 x1, x2, y1, y2;
841
Bool copy_flat = TRUE;
844
/* Let's find the image format and Video_Shift values */
846
case LE4CC('Y','V','1','2'):
847
pPriv->Format = FORMAT_YUV422;
848
pPriv->Video_Shift = 1;
851
case LE4CC('Y','U','Y','2'):
852
pPriv->Format = FORMAT_YUV422;
853
pPriv->Video_Shift = 1;
855
case LE4CC('U','Y','V','Y'):
856
pPriv->Format = FORMAT_VUY422;
857
pPriv->Video_Shift = 1;
859
case LE4CC('Y','U','V','A'):
860
pPriv->Format = FORMAT_YUV444;
861
pPriv->Video_Shift = 2;
863
case LE4CC('V','U','Y','A'):
864
pPriv->Format = FORMAT_VUY444;
865
pPriv->Video_Shift = 2;
867
case 0x41: /* RGBA 8:8:8:8 */
868
pPriv->Format = FORMAT_RGB8888;
869
pPriv->Video_Shift = 2;
871
case 0x42: /* RGB 5:6:5 */
872
pPriv->Format = FORMAT_RGB565;
873
pPriv->Video_Shift = 1;
875
case 0x43: /* RGB 1:5:5:5 */
876
pPriv->Format = FORMAT_RGB5551;
877
pPriv->Video_Shift = 1;
879
case 0x44: /* RGB 4:4:4:4 */
880
pPriv->Format = FORMAT_RGB4444;
881
pPriv->Video_Shift = 1;
883
case 0x46: /* RGB 2:3:3 */
884
pPriv->Format = FORMAT_RGB332;
885
pPriv->Video_Shift = 0;
887
case 0x47: /* BGRA 8:8:8:8 */
888
pPriv->Format = FORMAT_BGR8888;
889
pPriv->Video_Shift = 2;
891
case 0x48: /* BGR 5:6:5 */
892
pPriv->Format = FORMAT_BGR565;
893
pPriv->Video_Shift = 1;
895
case 0x49: /* BGR 1:5:5:5 */
896
pPriv->Format = FORMAT_BGR5551;
897
pPriv->Video_Shift = 1;
899
case 0x4A: /* BGR 4:4:4:4 */
900
pPriv->Format = FORMAT_BGR4444;
901
pPriv->Video_Shift = 1;
903
case 0x4C: /* BGR 2:3:3 */
904
pPriv->Format = FORMAT_BGR332;
905
pPriv->Video_Shift = 0;
918
dstBox.x2 = drw_x + drw_w;
920
dstBox.y2 = drw_y + drw_h;
922
if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
926
dstBox.x1 -= pScrn->frameX0;
927
dstBox.x2 -= pScrn->frameX0;
928
dstBox.y1 -= pScrn->frameY0;
929
dstBox.y2 -= pScrn->frameY0;
931
bpp = pScrn->bitsPerPixel >> 3;
932
pitch = bpp * pScrn->displayWidth;
934
w_bpp = (width << pPriv->Video_Shift) >> (pScrn->bitsPerPixel >> 4);
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)))
941
pPriv->offset[i] = (pPriv->area[i]->box.x1 * bpp) +
942
(pPriv->area[i]->box.y1 * pitch);
945
HWCopySetup(pScrn, pPriv->area[pPriv->buffer]->box.x1,
946
pPriv->area[pPriv->buffer]->box.y1, w_bpp, height);
949
HWCopyFlat(pScrn, buf, width, height);
951
HWCopyYV12(pScrn, buf, width, height);
953
/* paint the color key */
954
if(pPriv->autopaintColorKey && !RegionsEqual(&pPriv->clip, clipBoxes)) {
955
/* update cliplist */
956
REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
959
GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE,
960
PM3VideoOverlayMode);
961
pPriv->ramdacOn = FALSE;
963
xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
966
Permedia3Sync(pScrn);
968
Permedia3DisplayVideo(pScrn, id, pPriv->offset[pPriv->buffer], width,height,
969
x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
971
/* Switch buffer on next run - double buffer */
972
if (pPriv->doubleBuffer) {
979
pPriv->videoStatus = CLIENT_VIDEO_ON;
985
Permedia3QueryImageAttributes(
988
unsigned short *w, unsigned short *h,
989
int *pitches, int *offsets
993
if(*w > 2047) *w = 2047;
994
if(*h > 2047) *h = 2047;
997
if(offsets) offsets[0] = 0;
1000
case FOURCC_YV12: /* YV12 */
1002
size = (*w + 3) & ~3;
1003
if(pitches) pitches[0] = size;
1005
if(offsets) offsets[1] = size;
1006
tmp = ((*w >> 1) + 3) & ~3;
1007
if(pitches) pitches[1] = pitches[2] = tmp;
1010
if(offsets) offsets[2] = size;
1013
default: /* RGB15, RGB16, YUY2 */
1015
if(pitches) pitches[0] = size;
1023
/****************** Offscreen stuff ***************/
1031
} OffscreenPrivRec, * OffscreenPrivPtr;
1034
Permedia3AllocateSurface(
1039
XF86SurfacePtr surface
1043
OffscreenPrivPtr pPriv;
1045
if((w > 2047) || (h > 2047))
1049
bpp = pScrn->bitsPerPixel >> 3;
1050
fbpitch = bpp * pScrn->displayWidth;
1052
if(!(area = Permedia3AllocateMemory(pScrn, NULL, w, h)))
1056
surface->height = h;
1058
if(!(surface->offsets = xalloc(sizeof(int)))) {
1059
xf86FreeOffscreenArea(area);
1062
if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {
1063
xfree(surface->offsets);
1064
xf86FreeOffscreenArea(area);
1069
pPriv->isOn = FALSE;
1071
surface->pScrn = pScrn;
1073
surface->offsets[0] = (area->box.x1 * bpp) + (area->box.y1 * fbpitch);
1074
surface->devPrivate.ptr = (pointer)pPriv;
1080
Permedia3StopSurface(
1081
XF86SurfacePtr surface
1083
OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1086
GLINTPtr pGlint = GLINTPTR(surface->pScrn);
1087
pPriv->ramdacOn = FALSE;
1089
RAMDAC_WRITE(PM3RD_VideoOverlayControl_DISABLE,
1090
PM3RD_VideoOverlayControl);
1091
GLINT_WRITE_REG(PM3VideoOverlayMode_DISABLE,
1092
PM3VideoOverlayMode);
1093
pPriv->isOn = FALSE;
1100
Permedia3FreeSurface(
1101
XF86SurfacePtr surface
1103
OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;
1106
Permedia3StopSurface(surface);
1107
xf86FreeOffscreenArea(pPriv->area);
1108
xfree(surface->pitches);
1109
xfree(surface->offsets);
1110
xfree(surface->devPrivate.ptr);
1116
Permedia3GetSurfaceAttribute(
1121
return Permedia3GetPortAttribute(pScrn, attribute, value,
1122
(pointer)(GET_PORT_PRIVATE(pScrn)));
1126
Permedia3SetSurfaceAttribute(
1131
return Permedia3SetPortAttribute(pScrn, attribute, value,
1132
(pointer)(GET_PORT_PRIVATE(pScrn)));
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,
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;
1157
dstBox.x2 = drw_x + drw_w;
1159
dstBox.y2 = drw_y + drw_h;
1161
if(!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes,
1162
surface->width, surface->height))
1167
dstBox.x1 -= pScrn->frameX0;
1168
dstBox.x2 -= pScrn->frameX0;
1169
dstBox.y1 -= pScrn->frameY0;
1170
dstBox.y2 -= pScrn->frameY0;
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;
1178
case LE4CC('Y','U','Y','2'):
1179
pPriv->Format = FORMAT_YUV422;
1180
pPriv->Video_Shift = 1;
1182
case LE4CC('U','Y','V','Y'):
1183
pPriv->Format = FORMAT_VUY422;
1184
pPriv->Video_Shift = 1;
1186
case LE4CC('Y','U','V','A'):
1187
pPriv->Format = FORMAT_YUV444;
1188
pPriv->Video_Shift = 2;
1190
case LE4CC('V','U','Y','A'):
1191
pPriv->Format = FORMAT_VUY444;
1192
pPriv->Video_Shift = 2;
1194
case 0x41: /* RGBA 8:8:8:8 */
1195
pPriv->Format = FORMAT_RGB8888;
1196
pPriv->Video_Shift = 2;
1198
case 0x42: /* RGB 5:6:5 */
1199
pPriv->Format = FORMAT_RGB565;
1200
pPriv->Video_Shift = 1;
1202
case 0x43: /* RGB 1:5:5:5 */
1203
pPriv->Format = FORMAT_RGB5551;
1204
pPriv->Video_Shift = 1;
1206
case 0x44: /* RGB 4:4:4:4 */
1207
pPriv->Format = FORMAT_RGB4444;
1208
pPriv->Video_Shift = 1;
1210
case 0x46: /* RGB 2:3:3 */
1211
pPriv->Format = FORMAT_RGB332;
1212
pPriv->Video_Shift = 0;
1214
case 0x47: /* BGRA 8:8:8:8 */
1215
pPriv->Format = FORMAT_BGR8888;
1216
pPriv->Video_Shift = 2;
1218
case 0x48: /* BGR 5:6:5 */
1219
pPriv->Format = FORMAT_BGR565;
1220
pPriv->Video_Shift = 1;
1222
case 0x49: /* BGR 1:5:5:5 */
1223
pPriv->Format = FORMAT_BGR5551;
1224
pPriv->Video_Shift = 1;
1226
case 0x4A: /* BGR 4:4:4:4 */
1227
pPriv->Format = FORMAT_BGR4444;
1228
pPriv->Video_Shift = 1;
1230
case 0x4C: /* BGR 2:3:3 */
1231
pPriv->Format = FORMAT_BGR332;
1232
pPriv->Video_Shift = 0;
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);
1242
xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes);
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;
1258
Permedia3InitOffscreenImages(ScreenPtr pScreen)
1260
XF86OffscreenImagePtr offscreenImages;
1262
/* need to free this someplace */
1263
if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
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;
1280
xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
1284
Permedia3VideoTimerCallback(ScrnInfoPtr pScrn, Time time)
1286
GLINTPtr pGlint = GLINTPTR(pScrn);
1287
GLINTPortPrivPtr pPriv = pGlint->adaptor->pPortPrivates[0].ptr;
1290
if(pPriv->videoStatus & TIMER_MASK) {
1291
if(pPriv->videoStatus & OFF_TIMER) {
1292
if(pPriv->offTime < time) {
1293
pPriv->ramdacOn = FALSE;
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;
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;
1310
pPriv->videoStatus = 0;
1311
pGlint->VideoTimerCallback = NULL;
1314
} else /* shouldn't get here */
1315
pGlint->VideoTimerCallback = NULL;
1318
#endif /* !XvExtension */