radeon_textured_video.c revision c73da4db
1/*
2 * Copyright 2008 Alex Deucher
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 *
24 * Based on radeon_exa_render.c and kdrive ati_video.c by Eric Anholt, et al.
25 *
26 */
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include <stdlib.h>
33#include <string.h>
34#include <stdio.h>
35#include <math.h>
36
37#include "radeon.h"
38#include "radeon_reg.h"
39#include "radeon_macros.h"
40#include "radeon_probe.h"
41#include "radeon_video.h"
42
43#include <X11/extensions/Xv.h>
44#include "fourcc.h"
45
46extern void
47R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);
48
49#ifdef XF86DRM_MODE
50extern void
51EVERGREENDisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);
52#endif
53
54extern Bool
55R600CopyToVRAM(ScrnInfoPtr pScrn,
56	       char *src, int src_pitch,
57	       uint32_t dst_pitch, uint32_t dst_mc_addr, uint32_t dst_width, uint32_t dst_height, int bpp,
58	       int x, int y, int w, int h);
59
60#define IMAGE_MAX_WIDTH		2048
61#define IMAGE_MAX_HEIGHT	2048
62
63#define IMAGE_MAX_WIDTH_R500	4096
64#define IMAGE_MAX_HEIGHT_R500	4096
65
66#define IMAGE_MAX_WIDTH_R600	8192
67#define IMAGE_MAX_HEIGHT_R600	8192
68
69#define IMAGE_MAX_WIDTH_EG	16384
70#define IMAGE_MAX_HEIGHT_EG	16384
71
72static Bool
73RADEONTilingEnabled(ScrnInfoPtr pScrn, PixmapPtr pPix)
74{
75    RADEONInfoPtr info = RADEONPTR(pScrn);
76
77#ifdef USE_EXA
78    if (info->useEXA) {
79	if (info->tilingEnabled && exaGetPixmapOffset(pPix) == 0)
80	    return TRUE;
81	else
82	    return FALSE;
83    } else
84#endif
85	{
86	    if (info->tilingEnabled && ((pPix->devPrivate.ptr - info->FB) == 0))
87		return TRUE;
88	    else
89		return FALSE;
90	}
91}
92
93static __inline__ uint32_t F_TO_DW(float val)
94{
95    union {
96	float f;
97	uint32_t l;
98    } tmp;
99    tmp.f = val;
100    return tmp.l;
101}
102
103/* Borrowed from Mesa */
104static __inline__ uint32_t F_TO_24(float val)
105{
106	float mantissa;
107	int exponent;
108	uint32_t float24 = 0;
109
110	if (val == 0.0)
111		return 0;
112
113	mantissa = frexpf(val, &exponent);
114
115	/* Handle -ve */
116	if (mantissa < 0) {
117		float24 |= (1 << 23);
118		mantissa = mantissa * -1.0;
119	}
120	/* Handle exponent, bias of 63 */
121	exponent += 62;
122	float24 |= (exponent << 16);
123	/* Kill 7 LSB of mantissa */
124	float24 |= (F_TO_DW(mantissa) & 0x7FFFFF) >> 7;
125
126	return float24;
127}
128
129static __inline__ uint32_t float4touint(float fr, float fg, float fb, float fa)
130{
131    unsigned ur = fr * 255.0 + 0.5;
132    unsigned ug = fg * 255.0 + 0.5;
133    unsigned ub = fb * 255.0 + 0.5;
134    unsigned ua = fa * 255.0 + 0.5;
135    return (ua << 24) | (ur << 16) | (ug << 8) | ub;
136}
137
138/* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces
139   note the difference to the parameters used in overlay are due
140   to 10bit vs. float calcs */
141static REF_TRANSFORM trans[2] =
142{
143    {1.1643, 0.0, 1.5960, -0.3918, -0.8129, 2.0172, 0.0}, /* BT.601 */
144    {1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0}  /* BT.709 */
145};
146
147#define ACCEL_MMIO
148#define ACCEL_PREAMBLE()	unsigned char *RADEONMMIO = info->MMIO
149#define BEGIN_ACCEL(n)		RADEONWaitForFifo(pScrn, (n))
150#define OUT_ACCEL_REG(reg, val)	OUTREG(reg, val)
151#define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val))
152#define OUT_RELOC(x, read, write) do {} while(0)
153#define FINISH_ACCEL()
154
155#include "radeon_textured_videofuncs.c"
156
157#undef ACCEL_MMIO
158#undef ACCEL_PREAMBLE
159#undef BEGIN_ACCEL
160#undef OUT_ACCEL_REG
161#undef OUT_ACCEL_REG_F
162#undef OUT_RELOC
163#undef FINISH_ACCEL
164
165#ifdef XF86DRI
166
167#define ACCEL_CP
168#define ACCEL_PREAMBLE()						\
169    RING_LOCALS;							\
170    RADEONCP_REFRESH(pScrn, info)
171#define BEGIN_ACCEL(n)		BEGIN_RING(2*(n))
172#define OUT_ACCEL_REG(reg, val)	OUT_RING_REG(reg, val)
173#define OUT_ACCEL_REG_F(reg, val)	OUT_ACCEL_REG(reg, F_TO_DW(val))
174#define FINISH_ACCEL()		ADVANCE_RING()
175#define OUT_RING_F(x) OUT_RING(F_TO_DW(x))
176#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write)
177
178#include "radeon_textured_videofuncs.c"
179
180#undef ACCEL_CP
181#undef ACCEL_PREAMBLE
182#undef BEGIN_ACCEL
183#undef OUT_ACCEL_REG
184#undef OUT_ACCEL_REG_F
185#undef FINISH_ACCEL
186#undef OUT_RING_F
187
188#endif /* XF86DRI */
189
190static void
191R600CopyData(
192    ScrnInfoPtr pScrn,
193    unsigned char *src,
194    unsigned char *dst,
195    unsigned int srcPitch,
196    unsigned int dstPitch,
197    unsigned int h,
198    unsigned int w,
199    unsigned int cpp
200){
201    RADEONInfoPtr info = RADEONPTR( pScrn );
202
203    if (cpp == 2) {
204	w *= 2;
205	cpp = 1;
206    }
207
208    if (info->DMAForXv) {
209	uint32_t dst_mc_addr = dst - (unsigned char *)info->FB + info->fbLocation;
210
211	R600CopyToVRAM(pScrn,
212		       (char *)src, srcPitch,
213		       dstPitch, dst_mc_addr, w, h, cpp * 8,
214		       0, 0, w, h);
215    } else {
216	if (srcPitch == dstPitch)
217	    memcpy(dst, src, srcPitch * h);
218	else {
219	    while (h--) {
220		memcpy(dst, src, srcPitch);
221		src += srcPitch;
222		dst += dstPitch;
223	    }
224	}
225    }
226}
227
228static int
229RADEONPutImageTextured(ScrnInfoPtr pScrn,
230		       short src_x, short src_y,
231		       short drw_x, short drw_y,
232		       short src_w, short src_h,
233		       short drw_w, short drw_h,
234		       int id,
235		       unsigned char *buf,
236		       short width,
237		       short height,
238		       Bool sync,
239		       RegionPtr clipBoxes,
240		       pointer data,
241		       DrawablePtr pDraw)
242{
243    ScreenPtr pScreen = pScrn->pScreen;
244    RADEONInfoPtr info = RADEONPTR(pScrn);
245    RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)data;
246    INT32 x1, x2, y1, y2;
247    int srcPitch, srcPitch2, dstPitch, dstPitch2 = 0;
248    int s2offset, s3offset, tmp;
249    int d2line, d3line;
250    int top, nlines, size;
251    BoxRec dstBox;
252    int dst_width = width, dst_height = height;
253    int aligned_height;
254    int h_align;
255    /* make the compiler happy */
256    s2offset = s3offset = srcPitch2 = 0;
257
258#ifdef XF86DRM_MODE
259    if (info->cs)
260        h_align = drmmode_get_height_align(pScrn, 0);
261    else
262#endif
263        h_align = 1;
264
265    /* Clip */
266    x1 = src_x;
267    x2 = src_x + src_w;
268    y1 = src_y;
269    y2 = src_y + src_h;
270
271    dstBox.x1 = drw_x;
272    dstBox.x2 = drw_x + drw_w;
273    dstBox.y1 = drw_y;
274    dstBox.y2 = drw_y + drw_h;
275
276    if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height))
277	return Success;
278
279    if ((x1 >= x2) || (y1 >= y2))
280	return Success;
281
282    /* Bicubic filter setup */
283    pPriv->bicubic_enabled = (pPriv->bicubic_state != BICUBIC_OFF);
284    if (!(IS_R300_3D || IS_R500_3D)) {
285	pPriv->bicubic_enabled = FALSE;
286	pPriv->bicubic_state = BICUBIC_OFF;
287    }
288    if (pPriv->bicubic_enabled && (pPriv->bicubic_state == BICUBIC_AUTO)) {
289	/*
290	 * Applying the bicubic filter with a scale of less than 200%
291	 * results in a blurred picture, so disable the filter.
292	 */
293	if ((src_w > drw_w / 2) || (src_h > drw_h / 2))
294	    pPriv->bicubic_enabled = FALSE;
295    }
296
297#ifdef XF86DRM_MODE
298    if (info->cs) {
299	if (info->ChipFamily >= CHIP_FAMILY_R600)
300	    pPriv->hw_align = drmmode_get_base_align(pScrn, 2, 0);
301	else
302	    pPriv->hw_align = 64;
303    } else
304#endif
305    {
306	if (info->ChipFamily >= CHIP_FAMILY_R600)
307	    pPriv->hw_align = 256;
308	else
309	    pPriv->hw_align = 64;
310    }
311
312    aligned_height = RADEON_ALIGN(dst_height, h_align);
313
314    switch(id) {
315    case FOURCC_YV12:
316    case FOURCC_I420:
317	srcPitch = RADEON_ALIGN(width, 4);
318	srcPitch2 = RADEON_ALIGN(width >> 1, 4);
319        if (pPriv->bicubic_state != BICUBIC_OFF) {
320	    dstPitch = RADEON_ALIGN(dst_width << 1, pPriv->hw_align);
321	    dstPitch2 = 0;
322	} else {
323	    dstPitch = RADEON_ALIGN(dst_width, pPriv->hw_align);
324	    dstPitch2 = RADEON_ALIGN(dstPitch >> 1, pPriv->hw_align);
325	}
326	break;
327    case FOURCC_UYVY:
328    case FOURCC_YUY2:
329    default:
330	dstPitch = RADEON_ALIGN(dst_width << 1, pPriv->hw_align);
331	srcPitch = (width << 1);
332	srcPitch2 = 0;
333	break;
334    }
335
336    size = dstPitch * aligned_height + 2 * dstPitch2 * RADEON_ALIGN(((aligned_height + 1) >> 1), h_align);
337    size = RADEON_ALIGN(size, pPriv->hw_align);
338
339    if (size != pPriv->size) {
340	RADEONFreeVideoMemory(pScrn, pPriv);
341    }
342
343    if (pPriv->video_memory == NULL) {
344	pPriv->video_offset = radeon_legacy_allocate_memory(pScrn,
345							    &pPriv->video_memory,
346							    size, pPriv->hw_align,
347							    RADEON_GEM_DOMAIN_GTT);
348	if (pPriv->video_offset == 0)
349	    return BadAlloc;
350
351	if (info->cs) {
352	    pPriv->src_bo[0] = pPriv->video_memory;
353	    radeon_legacy_allocate_memory(pScrn, (void*)&pPriv->src_bo[1], size,
354					  pPriv->hw_align,
355					  RADEON_GEM_DOMAIN_GTT);
356	}
357    }
358
359    /* Bicubic filter loading */
360    if (pPriv->bicubic_enabled) {
361	if (info->bicubic_offset == 0)
362	    pPriv->bicubic_enabled = FALSE;
363	pPriv->bicubic_src_offset = info->bicubic_offset;
364    }
365
366    if (pDraw->type == DRAWABLE_WINDOW)
367	pPriv->pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr)pDraw);
368    else
369	pPriv->pPixmap = (PixmapPtr)pDraw;
370
371#ifdef USE_EXA
372    if (info->useEXA) {
373	/* Force the pixmap into framebuffer so we can draw to it. */
374	info->exa_force_create = TRUE;
375	exaMoveInPixmap(pPriv->pPixmap);
376	info->exa_force_create = FALSE;
377    }
378#endif
379
380    if (!info->useEXA &&
381	(((char *)pPriv->pPixmap->devPrivate.ptr < (char *)info->FB) ||
382	 ((char *)pPriv->pPixmap->devPrivate.ptr >= (char *)info->FB +
383	  info->FbMapSize))) {
384	/* If the pixmap wasn't in framebuffer, then we have no way in XAA to
385	 * force it there. So, we simply refuse to draw and fail.
386	 */
387	return BadAlloc;
388    }
389
390    /* copy data */
391    top = (y1 >> 16) & ~1;
392    nlines = ((y2 + 0xffff) >> 16) - top;
393
394    pPriv->src_offset = pPriv->video_offset;
395    if (info->cs) {
396	struct radeon_bo *src_bo;
397	int ret;
398
399	pPriv->currentBuffer ^= 1;
400
401	src_bo = pPriv->src_bo[pPriv->currentBuffer];
402
403	ret = radeon_bo_map(src_bo, 1);
404	if (ret)
405	    return BadAlloc;
406
407	pPriv->src_addr = src_bo->ptr;
408    } else {
409	pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset);
410	RADEONWaitForIdleMMIO(pScrn);
411    }
412    pPriv->src_pitch = dstPitch;
413
414    pPriv->planeu_offset = dstPitch * aligned_height;
415    pPriv->planeu_offset = RADEON_ALIGN(pPriv->planeu_offset, pPriv->hw_align);
416    pPriv->planev_offset = pPriv->planeu_offset + dstPitch2 * RADEON_ALIGN(((aligned_height + 1) >> 1), h_align);
417    pPriv->planev_offset = RADEON_ALIGN(pPriv->planev_offset, pPriv->hw_align);
418
419    pPriv->size = size;
420    pPriv->pDraw = pDraw;
421
422    switch(id) {
423    case FOURCC_YV12:
424    case FOURCC_I420:
425	s2offset = srcPitch * (RADEON_ALIGN(height, 2));
426	s3offset = s2offset + (srcPitch2 * ((height + 1) >> 1));
427	s2offset += ((top >> 1) * srcPitch2);
428	s3offset += ((top >> 1) * srcPitch2);
429	if (pPriv->bicubic_state != BICUBIC_OFF) {
430	    if (id == FOURCC_I420) {
431		tmp = s2offset;
432		s2offset = s3offset;
433		s3offset = tmp;
434	    }
435	    RADEONCopyMungedData(pScrn, buf + (top * srcPitch),
436				 buf + s2offset, buf + s3offset, pPriv->src_addr + (top * dstPitch),
437				 srcPitch, srcPitch2, dstPitch, nlines, width);
438	} else {
439	    if (id == FOURCC_YV12) {
440		tmp = s2offset;
441		s2offset = s3offset;
442		s3offset = tmp;
443	    }
444	    d2line = pPriv->planeu_offset + ((top >> 1) * dstPitch2);
445	    d3line = pPriv->planev_offset + ((top >> 1) * dstPitch2);
446
447	    if (info->ChipFamily >= CHIP_FAMILY_R600) {
448		R600CopyData(pScrn, buf + (top * srcPitch), pPriv->src_addr + (top * dstPitch),
449			     srcPitch, dstPitch, nlines, width, 1);
450		R600CopyData(pScrn, buf + s2offset,  pPriv->src_addr + d2line,
451			     srcPitch2, dstPitch2, (nlines + 1) >> 1, width >> 1, 1);
452		R600CopyData(pScrn, buf + s3offset, pPriv->src_addr + d3line,
453			     srcPitch2, dstPitch2, (nlines + 1) >> 1, width >> 1, 1);
454	    } else {
455		RADEONCopyData(pScrn, buf + (top * srcPitch), pPriv->src_addr + (top * dstPitch),
456			       srcPitch, dstPitch, nlines, width, 1);
457		RADEONCopyData(pScrn, buf + s2offset,  pPriv->src_addr + d2line,
458			       srcPitch2, dstPitch2, (nlines + 1) >> 1, width >> 1, 1);
459		RADEONCopyData(pScrn, buf + s3offset, pPriv->src_addr + d3line,
460			       srcPitch2, dstPitch2, (nlines + 1) >> 1, width >> 1, 1);
461	    }
462	}
463	break;
464    case FOURCC_UYVY:
465    case FOURCC_YUY2:
466    default:
467	if (info->ChipFamily >= CHIP_FAMILY_R600)
468	    R600CopyData(pScrn, buf + (top * srcPitch),
469			 pPriv->src_addr + (top * dstPitch),
470			 srcPitch, dstPitch, nlines, width, 2);
471	else
472	    RADEONCopyData(pScrn, buf + (top * srcPitch),
473			   pPriv->src_addr + (top * dstPitch),
474			   srcPitch, dstPitch, nlines, width, 2);
475	break;
476    }
477
478    /* update cliplist */
479    if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
480	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
481    }
482
483    pPriv->id = id;
484    pPriv->src_w = src_w;
485    pPriv->src_h = src_h;
486    pPriv->src_x = src_x;
487    pPriv->src_y = src_y;
488    pPriv->drw_x = drw_x;
489    pPriv->drw_y = drw_y;
490    pPriv->dst_w = drw_w;
491    pPriv->dst_h = drw_h;
492    pPriv->w = width;
493    pPriv->h = height;
494
495#if defined(XF86DRM_MODE)
496    if (info->cs)
497	radeon_bo_unmap(pPriv->src_bo[pPriv->currentBuffer]);
498#endif
499#ifdef XF86DRI
500    if (info->directRenderingEnabled) {
501#ifdef XF86DRM_MODE
502	if (info->cs && IS_EVERGREEN_3D)
503	    EVERGREENDisplayTexturedVideo(pScrn, pPriv);
504	else
505#endif
506	  if (IS_R600_3D)
507	    R600DisplayTexturedVideo(pScrn, pPriv);
508	else if (IS_R500_3D)
509	    R500DisplayTexturedVideoCP(pScrn, pPriv);
510	else if (IS_R300_3D)
511	    R300DisplayTexturedVideoCP(pScrn, pPriv);
512	else if (IS_R200_3D)
513	    R200DisplayTexturedVideoCP(pScrn, pPriv);
514	else
515	    RADEONDisplayTexturedVideoCP(pScrn, pPriv);
516    } else
517#endif
518    {
519	if (IS_R500_3D)
520	    R500DisplayTexturedVideoMMIO(pScrn, pPriv);
521	else if (IS_R300_3D)
522	    R300DisplayTexturedVideoMMIO(pScrn, pPriv);
523	else if (IS_R200_3D)
524	    R200DisplayTexturedVideoMMIO(pScrn, pPriv);
525	else
526	    RADEONDisplayTexturedVideoMMIO(pScrn, pPriv);
527    }
528
529    return Success;
530}
531
532/* client libraries expect an encoding */
533static XF86VideoEncodingRec DummyEncoding[1] =
534{
535    {
536	0,
537	"XV_IMAGE",
538	IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
539	{1, 1}
540    }
541};
542
543static XF86VideoEncodingRec DummyEncodingR500[1] =
544{
545    {
546	0,
547	"XV_IMAGE",
548	IMAGE_MAX_WIDTH_R500, IMAGE_MAX_HEIGHT_R500,
549	{1, 1}
550    }
551};
552
553static XF86VideoEncodingRec DummyEncodingR600[1] =
554{
555    {
556	0,
557	"XV_IMAGE",
558	IMAGE_MAX_WIDTH_R600, IMAGE_MAX_HEIGHT_R600,
559	{1, 1}
560    }
561};
562
563static XF86VideoEncodingRec DummyEncodingEG[1] =
564{
565    {
566	0,
567	"XV_IMAGE",
568	IMAGE_MAX_WIDTH_EG, IMAGE_MAX_HEIGHT_EG,
569	{1, 1}
570    }
571};
572
573#define NUM_FORMATS 3
574
575static XF86VideoFormatRec Formats[NUM_FORMATS] =
576{
577    {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
578};
579
580#define NUM_ATTRIBUTES 2
581
582static XF86AttributeRec Attributes[NUM_ATTRIBUTES+1] =
583{
584    {XvSettable | XvGettable, 0, 1, "XV_VSYNC"},
585    {XvSettable | XvGettable, -1, 1, "XV_CRTC"},
586    {0, 0, 0, NULL}
587};
588
589#define NUM_ATTRIBUTES_R200 7
590
591static XF86AttributeRec Attributes_r200[NUM_ATTRIBUTES_R200+1] =
592{
593    {XvSettable | XvGettable, 0, 1, "XV_VSYNC"},
594    {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
595    {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
596    {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
597    {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
598    {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
599    {XvSettable | XvGettable, -1, 1, "XV_CRTC"},
600    {0, 0, 0, NULL}
601};
602
603#define NUM_ATTRIBUTES_R300 9
604
605static XF86AttributeRec Attributes_r300[NUM_ATTRIBUTES_R300+1] =
606{
607    {XvSettable | XvGettable, 0, 2, "XV_BICUBIC"},
608    {XvSettable | XvGettable, 0, 1, "XV_VSYNC"},
609    {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
610    {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
611    {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
612    {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
613    {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"},
614    {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
615    {XvSettable | XvGettable, -1, 1, "XV_CRTC"},
616    {0, 0, 0, NULL}
617};
618
619#define NUM_ATTRIBUTES_R500 8
620
621static XF86AttributeRec Attributes_r500[NUM_ATTRIBUTES_R500+1] =
622{
623    {XvSettable | XvGettable, 0, 2, "XV_BICUBIC"},
624    {XvSettable | XvGettable, 0, 1, "XV_VSYNC"},
625    {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
626    {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
627    {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
628    {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
629    {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
630    {XvSettable | XvGettable, -1, 1, "XV_CRTC"},
631    {0, 0, 0, NULL}
632};
633
634#define NUM_ATTRIBUTES_R600 7
635
636static XF86AttributeRec Attributes_r600[NUM_ATTRIBUTES_R600+1] =
637{
638    {XvSettable | XvGettable, 0, 1, "XV_VSYNC"},
639    {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
640    {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
641    {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
642    {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
643    {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
644    {XvSettable | XvGettable, -1, 1, "XV_CRTC"},
645    {0, 0, 0, NULL}
646};
647
648static XF86AttributeRec Attributes_eg[NUM_ATTRIBUTES_R600+1] =
649{
650    {XvSettable | XvGettable, 0, 1, "XV_VSYNC"},
651    {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
652    {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
653    {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
654    {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
655    {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
656    {XvSettable | XvGettable, -1, 5, "XV_CRTC"},
657    {0, 0, 0, NULL}
658};
659
660static Atom xvBicubic;
661static Atom xvVSync;
662static Atom xvBrightness, xvContrast, xvSaturation, xvHue;
663static Atom xvGamma, xvColorspace;
664static Atom xvCRTC;
665
666#define NUM_IMAGES 4
667
668static XF86ImageRec Images[NUM_IMAGES] =
669{
670    XVIMAGE_YUY2,
671    XVIMAGE_YV12,
672    XVIMAGE_I420,
673    XVIMAGE_UYVY
674};
675
676int
677RADEONGetTexPortAttribute(ScrnInfoPtr  pScrn,
678		       Atom	    attribute,
679		       INT32	    *value,
680		       pointer	    data)
681{
682    RADEONInfoPtr	info = RADEONPTR(pScrn);
683    RADEONPortPrivPtr	pPriv = (RADEONPortPrivPtr)data;
684
685    if (info->accelOn) RADEON_SYNC(info, pScrn);
686
687    if (attribute == xvBicubic)
688	*value = pPriv->bicubic_state;
689    else if (attribute == xvVSync)
690	*value = pPriv->vsync;
691    else if (attribute == xvBrightness)
692	*value = pPriv->brightness;
693    else if (attribute == xvContrast)
694	*value = pPriv->contrast;
695    else if (attribute == xvSaturation)
696	*value = pPriv->saturation;
697    else if (attribute == xvHue)
698	*value = pPriv->hue;
699    else if (attribute == xvGamma)
700	*value = pPriv->gamma;
701    else if(attribute == xvColorspace)
702	*value = pPriv->transform_index;
703    else if(attribute == xvCRTC) {
704	int		c;
705	xf86CrtcConfigPtr	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
706	for (c = 0; c < xf86_config->num_crtc; c++)
707	    if (xf86_config->crtc[c] == pPriv->desired_crtc)
708		break;
709	if (c == xf86_config->num_crtc)
710	    c = -1;
711	*value = c;
712    } else
713	return BadMatch;
714
715    return Success;
716}
717
718int
719RADEONSetTexPortAttribute(ScrnInfoPtr  pScrn,
720		       Atom	    attribute,
721		       INT32	    value,
722		       pointer	    data)
723{
724    RADEONInfoPtr	info = RADEONPTR(pScrn);
725    RADEONPortPrivPtr	pPriv = (RADEONPortPrivPtr)data;
726
727    RADEON_SYNC(info, pScrn);
728
729    if (attribute == xvBicubic)
730	pPriv->bicubic_state = ClipValue (value, 0, 2);
731    else if (attribute == xvVSync)
732	pPriv->vsync = ClipValue (value, 0, 1);
733    else if (attribute == xvBrightness)
734	pPriv->brightness = ClipValue (value, -1000, 1000);
735    else if (attribute == xvContrast)
736	pPriv->contrast = ClipValue (value, -1000, 1000);
737    else if (attribute == xvSaturation)
738	pPriv->saturation = ClipValue (value, -1000, 1000);
739    else if (attribute == xvHue)
740	pPriv->hue = ClipValue (value, -1000, 1000);
741    else if (attribute == xvGamma)
742	pPriv->gamma = ClipValue (value, 100, 10000);
743    else if(attribute == xvColorspace)
744	pPriv->transform_index = ClipValue (value, 0, 1);
745    else if(attribute == xvCRTC) {
746	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
747	if ((value < -1) || (value > xf86_config->num_crtc))
748	    return BadValue;
749	if (value < 0)
750	    pPriv->desired_crtc = NULL;
751	else
752	    pPriv->desired_crtc = xf86_config->crtc[value];
753    } else
754	return BadMatch;
755
756    return Success;
757}
758
759Bool radeon_load_bicubic_texture(ScrnInfoPtr pScrn)
760{
761    RADEONInfoPtr    info = RADEONPTR(pScrn);
762
763    /* Bicubic filter loading */
764    info->bicubic_offset = radeon_legacy_allocate_memory(pScrn,
765							 &info->bicubic_memory,
766							 sizeof(bicubic_tex_512), 64,
767							 RADEON_GEM_DOMAIN_VRAM);
768    if (info->bicubic_offset == 0)
769	return FALSE;
770
771    if (info->cs)
772	info->bicubic_bo = info->bicubic_memory;
773
774    /* Upload bicubic filter tex */
775    if (info->ChipFamily < CHIP_FAMILY_R600) {
776	uint8_t *bicubic_addr;
777	int ret;
778	if (info->cs) {
779	    ret = radeon_bo_map(info->bicubic_bo, 1);
780	    if (ret)
781		return FALSE;
782
783	    bicubic_addr = info->bicubic_bo->ptr;
784	} else
785	    bicubic_addr = (uint8_t *)(info->FB + info->bicubic_offset);
786
787	RADEONCopySwap(bicubic_addr, (uint8_t *)bicubic_tex_512, 1024,
788#if X_BYTE_ORDER == X_BIG_ENDIAN
789		       RADEON_HOST_DATA_SWAP_16BIT
790#else
791		       RADEON_HOST_DATA_SWAP_NONE
792#endif
793);
794	if (info->cs)
795	    radeon_bo_unmap(info->bicubic_bo);
796    }
797    return TRUE;
798}
799
800#if 0
801/* XXX */
802static void radeon_unload_bicubic_texture(ScrnInfoPtr pScrn)
803{
804    RADEONInfoPtr    info = RADEONPTR(pScrn);
805
806    if (info->bicubic_memory != NULL) {
807	radeon_legacy_free_memory(pScrn, info->bicubic_memory);
808	info->bicubic_memory = NULL;
809    }
810
811}
812#endif
813
814XF86VideoAdaptorPtr
815RADEONSetupImageTexturedVideo(ScreenPtr pScreen)
816{
817    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
818    RADEONInfoPtr    info = RADEONPTR(pScrn);
819    RADEONPortPrivPtr pPortPriv;
820    XF86VideoAdaptorPtr adapt;
821    int i;
822    int num_texture_ports = 16;
823
824    adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports *
825		   (sizeof(RADEONPortPrivRec) + sizeof(DevUnion)));
826    if (adapt == NULL)
827	return NULL;
828
829    xvBicubic         = MAKE_ATOM("XV_BICUBIC");
830    xvVSync           = MAKE_ATOM("XV_VSYNC");
831    xvBrightness      = MAKE_ATOM("XV_BRIGHTNESS");
832    xvContrast        = MAKE_ATOM("XV_CONTRAST");
833    xvSaturation      = MAKE_ATOM("XV_SATURATION");
834    xvHue             = MAKE_ATOM("XV_HUE");
835    xvGamma           = MAKE_ATOM("XV_GAMMA");
836    xvColorspace      = MAKE_ATOM("XV_COLORSPACE");
837    xvCRTC            = MAKE_ATOM("XV_CRTC");
838
839    adapt->type = XvWindowMask | XvInputMask | XvImageMask;
840    adapt->flags = 0;
841    adapt->name = "Radeon Textured Video";
842    adapt->nEncodings = 1;
843    if (IS_EVERGREEN_3D)
844	adapt->pEncodings = DummyEncodingEG;
845    else if (IS_R600_3D)
846	adapt->pEncodings = DummyEncodingR600;
847    else if (IS_R500_3D)
848	adapt->pEncodings = DummyEncodingR500;
849    else
850	adapt->pEncodings = DummyEncoding;
851    adapt->nFormats = NUM_FORMATS;
852    adapt->pFormats = Formats;
853    adapt->nPorts = num_texture_ports;
854    adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
855
856    pPortPriv =
857	(RADEONPortPrivPtr)(&adapt->pPortPrivates[num_texture_ports]);
858
859    if (IS_EVERGREEN_3D) {
860	adapt->pAttributes = Attributes_eg;
861	adapt->nAttributes = NUM_ATTRIBUTES_R600;
862    }
863    else if (IS_R600_3D) {
864	adapt->pAttributes = Attributes_r600;
865	adapt->nAttributes = NUM_ATTRIBUTES_R600;
866    }
867    else if (IS_R500_3D) {
868	adapt->pAttributes = Attributes_r500;
869	adapt->nAttributes = NUM_ATTRIBUTES_R500;
870    }
871    else if (IS_R300_3D) {
872	adapt->pAttributes = Attributes_r300;
873	adapt->nAttributes = NUM_ATTRIBUTES_R300;
874    }
875    else if (IS_R200_3D) {
876	adapt->pAttributes = Attributes_r200;
877	adapt->nAttributes = NUM_ATTRIBUTES_R200;
878    }
879    else {
880	adapt->pAttributes = Attributes;
881	adapt->nAttributes = NUM_ATTRIBUTES;
882    }
883    adapt->pImages = Images;
884    adapt->nImages = NUM_IMAGES;
885    adapt->PutVideo = NULL;
886    adapt->PutStill = NULL;
887    adapt->GetVideo = NULL;
888    adapt->GetStill = NULL;
889    adapt->StopVideo = RADEONStopVideo;
890    adapt->SetPortAttribute = RADEONSetTexPortAttribute;
891    adapt->GetPortAttribute = RADEONGetTexPortAttribute;
892    adapt->QueryBestSize = RADEONQueryBestSize;
893    adapt->PutImage = RADEONPutImageTextured;
894    adapt->ReputImage = NULL;
895    adapt->QueryImageAttributes = RADEONQueryImageAttributes;
896
897    for (i = 0; i < num_texture_ports; i++) {
898	RADEONPortPrivPtr pPriv = &pPortPriv[i];
899
900	pPriv->textured = TRUE;
901	pPriv->videoStatus = 0;
902	pPriv->currentBuffer = 0;
903	pPriv->doubleBuffer = 0;
904	pPriv->bicubic_state = BICUBIC_OFF;
905	pPriv->vsync = TRUE;
906	pPriv->brightness = 0;
907	pPriv->contrast = 0;
908	pPriv->saturation = 0;
909	pPriv->hue = 0;
910	pPriv->gamma = 1000;
911	pPriv->transform_index = 0;
912	pPriv->desired_crtc = NULL;
913
914	/* gotta uninit this someplace, XXX: shouldn't be necessary for textured */
915	REGION_NULL(pScreen, &pPriv->clip);
916	adapt->pPortPrivates[i].ptr = (pointer) (pPriv);
917    }
918
919    if (IS_R500_3D || IS_R300_3D)
920	radeon_load_bicubic_texture(pScrn);
921
922    info->xv_max_width = adapt->pEncodings->width;
923    info->xv_max_height = adapt->pEncodings->height;
924
925    return adapt;
926}
927
928