1fda9279dSmrg/* 2fda9279dSmrg * Copyright 2008 Ben Skeggs 3fda9279dSmrg * 4fda9279dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5fda9279dSmrg * copy of this software and associated documentation files (the "Software"), 6fda9279dSmrg * to deal in the Software without restriction, including without limitation 7fda9279dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8fda9279dSmrg * and/or sell copies of the Software, and to permit persons to whom the 9fda9279dSmrg * Software is furnished to do so, subject to the following conditions: 10fda9279dSmrg * 11fda9279dSmrg * The above copyright notice and this permission notice shall be included in 12fda9279dSmrg * all copies or substantial portions of the Software. 13fda9279dSmrg * 14fda9279dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15fda9279dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16fda9279dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17fda9279dSmrg * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18fda9279dSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19fda9279dSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20fda9279dSmrg * SOFTWARE. 21fda9279dSmrg */ 22fda9279dSmrg 23fda9279dSmrg#ifdef HAVE_CONFIG_H 24fda9279dSmrg#include "config.h" 25fda9279dSmrg#endif 26fda9279dSmrg 27479f40c1Smrg#include "xorg-config.h" 28fda9279dSmrg#include "xf86xv.h" 29fda9279dSmrg#include <X11/extensions/Xv.h> 30fda9279dSmrg#include "exa.h" 31fda9279dSmrg#include "damage.h" 32fda9279dSmrg#include "dixstruct.h" 33fda9279dSmrg#include "fourcc.h" 34fda9279dSmrg 35fda9279dSmrg#include "nv_include.h" 36fda9279dSmrg#include "nvc0_accel.h" 37fda9279dSmrg 38fda9279dSmrgextern Atom xvSyncToVBlank, xvSetDefaults; 39fda9279dSmrg 40fda9279dSmrgstatic Bool 41fda9279dSmrgnvc0_xv_check_image_put(PixmapPtr ppix) 42fda9279dSmrg{ 43fda9279dSmrg switch (ppix->drawable.bitsPerPixel) { 44fda9279dSmrg case 32: 45fda9279dSmrg case 24: 46fda9279dSmrg case 16: 47fda9279dSmrg case 15: 48fda9279dSmrg break; 49fda9279dSmrg default: 50fda9279dSmrg return FALSE; 51fda9279dSmrg } 52fda9279dSmrg 53fda9279dSmrg if (!nv50_style_tiled_pixmap(ppix)) 54fda9279dSmrg return FALSE; 55fda9279dSmrg 56fda9279dSmrg return TRUE; 57fda9279dSmrg} 58fda9279dSmrg 59fda9279dSmrgint 60fda9279dSmrgnvc0_xv_image_put(ScrnInfoPtr pScrn, 61fda9279dSmrg struct nouveau_bo *src, int packed_y, int uv, 62fda9279dSmrg int id, int src_pitch, BoxPtr dstBox, 63fda9279dSmrg int x1, int y1, int x2, int y2, 64fda9279dSmrg uint16_t width, uint16_t height, 65fda9279dSmrg uint16_t src_w, uint16_t src_h, 66fda9279dSmrg uint16_t drw_w, uint16_t drw_h, 67fda9279dSmrg RegionPtr clipBoxes, PixmapPtr ppix, 68fda9279dSmrg NVPortPrivPtr pPriv) 69fda9279dSmrg{ 70fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 71fda9279dSmrg struct nouveau_bo *dst = nouveau_pixmap_bo(ppix); 72fda9279dSmrg struct nouveau_pushbuf_refn refs[] = { 73fda9279dSmrg { pNv->scratch, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR }, 74fda9279dSmrg { src, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD }, 75fda9279dSmrg { dst, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR }, 76fda9279dSmrg }; 77fda9279dSmrg struct nouveau_pushbuf *push = pNv->pushbuf; 78fda9279dSmrg float X1, X2, Y1, Y2; 79fda9279dSmrg BoxPtr pbox; 80fda9279dSmrg int nbox; 81fda9279dSmrg 82fda9279dSmrg if (!nvc0_xv_check_image_put(ppix)) 83fda9279dSmrg return BadMatch; 84fda9279dSmrg 85fda9279dSmrg if (!PUSH_SPACE(push, 256)) 86fda9279dSmrg return BadImplementation; 87fda9279dSmrg 88fda9279dSmrg BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 8); 89fda9279dSmrg PUSH_DATA (push, dst->offset >> 32); 90fda9279dSmrg PUSH_DATA (push, dst->offset); 91fda9279dSmrg PUSH_DATA (push, ppix->drawable.width); 92fda9279dSmrg PUSH_DATA (push, ppix->drawable.height); 9322d74663Smrg switch (ppix->drawable.depth) { 94fda9279dSmrg case 32: PUSH_DATA (push, NV50_SURFACE_FORMAT_BGRA8_UNORM); break; 9522d74663Smrg case 30: PUSH_DATA (push, NV50_SURFACE_FORMAT_RGB10_A2_UNORM); break; 96fda9279dSmrg case 24: PUSH_DATA (push, NV50_SURFACE_FORMAT_BGRX8_UNORM); break; 97fda9279dSmrg case 16: PUSH_DATA (push, NV50_SURFACE_FORMAT_B5G6R5_UNORM); break; 98fda9279dSmrg case 15: PUSH_DATA (push, NV50_SURFACE_FORMAT_BGR5_X1_UNORM); break; 99fda9279dSmrg } 100fda9279dSmrg PUSH_DATA (push, dst->config.nvc0.tile_mode); 101fda9279dSmrg PUSH_DATA (push, 1); 102fda9279dSmrg PUSH_DATA (push, 0); 103fda9279dSmrg 104fda9279dSmrg BEGIN_NVC0(push, NVC0_3D(BLEND_ENABLE(0)), 1); 105fda9279dSmrg PUSH_DATA (push, 0); 106fda9279dSmrg 107fda9279dSmrg PUSH_DATAu(push, pNv->scratch, TIC_OFFSET, 16); 108fda9279dSmrg if (id == FOURCC_YV12 || id == FOURCC_I420) { 1091090d90aSmrg PUSH_TIC(push, src, packed_y, width, height, 0, 1101090d90aSmrg NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM | 111fda9279dSmrg NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM | 112fda9279dSmrg NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | 113fda9279dSmrg NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | 114fda9279dSmrg NV50TIC_0_0_FMT_8); 1151090d90aSmrg PUSH_TIC(push, src, uv, width >> 1, height >> 1, 0, 1161090d90aSmrg NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM | 117fda9279dSmrg NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | 118fda9279dSmrg NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | 119fda9279dSmrg NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | 120fda9279dSmrg NV50TIC_0_0_FMT_8_8); 121fda9279dSmrg } else { 1221090d90aSmrg unsigned format; 1231090d90aSmrg if (id == FOURCC_UYVY) { 1241090d90aSmrg format = NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM | 125fda9279dSmrg NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM | 126fda9279dSmrg NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | 127fda9279dSmrg NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | 1281090d90aSmrg NV50TIC_0_0_FMT_8_8; 1291090d90aSmrg } else { 1301090d90aSmrg format = NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM | 131fda9279dSmrg NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM | 132fda9279dSmrg NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | 133fda9279dSmrg NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | 1341090d90aSmrg NV50TIC_0_0_FMT_8_8; 1351090d90aSmrg } 1361090d90aSmrg PUSH_TIC(push, src, packed_y, width, height, 0, format); 1371090d90aSmrg 1381090d90aSmrg if (id == FOURCC_UYVY) { 1391090d90aSmrg format = NV50TIC_0_0_MAPA_C2 | NV50TIC_0_0_TYPEA_UNORM | 140fda9279dSmrg NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | 141fda9279dSmrg NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | 142fda9279dSmrg NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | 1431090d90aSmrg NV50TIC_0_0_FMT_8_8_8_8; 1441090d90aSmrg } else { 1451090d90aSmrg format = NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | 146fda9279dSmrg NV50TIC_0_0_MAPB_C1 | NV50TIC_0_0_TYPEB_UNORM | 147fda9279dSmrg NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | 148fda9279dSmrg NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | 1491090d90aSmrg NV50TIC_0_0_FMT_8_8_8_8; 1501090d90aSmrg } 1511090d90aSmrg PUSH_TIC(push, src, packed_y, width >> 1, height, 0, format); 152fda9279dSmrg } 153fda9279dSmrg 154fda9279dSmrg PUSH_DATAu(push, pNv->scratch, TSC_OFFSET, 16); 155fda9279dSmrg PUSH_DATA (push, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE | 156fda9279dSmrg NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE | 157fda9279dSmrg NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE); 158fda9279dSmrg PUSH_DATA (push, NV50TSC_1_1_MAGF_LINEAR | 159fda9279dSmrg NV50TSC_1_1_MINF_LINEAR | 160fda9279dSmrg NV50TSC_1_1_MIPF_NONE); 161fda9279dSmrg PUSH_DATA (push, 0x00000000); 162fda9279dSmrg PUSH_DATA (push, 0x00000000); 163fda9279dSmrg PUSH_DATA (push, 0x00000000); 164fda9279dSmrg PUSH_DATA (push, 0x00000000); 165fda9279dSmrg PUSH_DATA (push, 0x00000000); 166fda9279dSmrg PUSH_DATA (push, 0x00000000); 167fda9279dSmrg PUSH_DATA (push, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE | 168fda9279dSmrg NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE | 169fda9279dSmrg NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE); 170fda9279dSmrg PUSH_DATA (push, NV50TSC_1_1_MAGF_LINEAR | 171fda9279dSmrg NV50TSC_1_1_MINF_LINEAR | 172fda9279dSmrg NV50TSC_1_1_MIPF_NONE); 173fda9279dSmrg PUSH_DATA (push, 0x00000000); 174fda9279dSmrg PUSH_DATA (push, 0x00000000); 175fda9279dSmrg PUSH_DATA (push, 0x00000000); 176fda9279dSmrg PUSH_DATA (push, 0x00000000); 177fda9279dSmrg PUSH_DATA (push, 0x00000000); 178fda9279dSmrg PUSH_DATA (push, 0x00000000); 179fda9279dSmrg 180fda9279dSmrg BEGIN_NVC0(push, NVC0_3D(SP_START_ID(5)), 1); 181fda9279dSmrg PUSH_DATA (push, PFP_NV12); 182fda9279dSmrg 183fda9279dSmrg BEGIN_NVC0(push, NVC0_3D(TSC_FLUSH), 1); 184fda9279dSmrg PUSH_DATA (push, 0); 185fda9279dSmrg BEGIN_NVC0(push, NVC0_3D(TIC_FLUSH), 1); 186fda9279dSmrg PUSH_DATA (push, 0); 187fda9279dSmrg BEGIN_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 1); 188fda9279dSmrg PUSH_DATA (push, 0); 189fda9279dSmrg 190fda9279dSmrg PUSH_DATAu(push, pNv->scratch, PVP_DATA, 11); 191fda9279dSmrg PUSH_DATAf(push, 1.0); 192fda9279dSmrg PUSH_DATAf(push, 0.0); 193fda9279dSmrg PUSH_DATAf(push, 0.0); 194fda9279dSmrg PUSH_DATAf(push, 0.0); 195fda9279dSmrg PUSH_DATAf(push, 1.0); 196fda9279dSmrg PUSH_DATAf(push, 0.0); 197fda9279dSmrg PUSH_DATAf(push, 0.0); 198fda9279dSmrg PUSH_DATAf(push, 0.0); 199fda9279dSmrg PUSH_DATAf(push, 1.0); 200fda9279dSmrg PUSH_DATAf(push, 1.0 / width); 201fda9279dSmrg PUSH_DATAf(push, 1.0 / height); 202fda9279dSmrg 203fda9279dSmrg if (pPriv->SyncToVBlank) { 204fda9279dSmrg NVC0SyncToVBlank(ppix, dstBox); 205fda9279dSmrg } 206fda9279dSmrg 207fda9279dSmrg /* These are fixed point values in the 16.16 format. */ 208fda9279dSmrg X1 = (float)(x1>>16)+(float)(x1&0xFFFF)/(float)0x10000; 209fda9279dSmrg Y1 = (float)(y1>>16)+(float)(y1&0xFFFF)/(float)0x10000; 210fda9279dSmrg X2 = (float)(x2>>16)+(float)(x2&0xFFFF)/(float)0x10000; 211fda9279dSmrg Y2 = (float)(y2>>16)+(float)(y2&0xFFFF)/(float)0x10000; 212fda9279dSmrg 213fda9279dSmrg pbox = REGION_RECTS(clipBoxes); 214fda9279dSmrg nbox = REGION_NUM_RECTS(clipBoxes); 215fda9279dSmrg while(nbox--) { 216fda9279dSmrg float tx1=X1+(float)(pbox->x1 - dstBox->x1)*(X2-X1)/(float)(drw_w); 217fda9279dSmrg float tx2=X1+(float)(pbox->x2 - dstBox->x1)*(src_w)/(float)(drw_w); 218fda9279dSmrg float ty1=Y1+(float)(pbox->y1 - dstBox->y1)*(Y2-Y1)/(float)(drw_h); 219fda9279dSmrg float ty2=Y1+(float)(pbox->y2 - dstBox->y1)*(src_h)/(float)(drw_h); 220fda9279dSmrg int sx1=pbox->x1; 221fda9279dSmrg int sx2=pbox->x2; 222fda9279dSmrg int sy1=pbox->y1; 223fda9279dSmrg int sy2=pbox->y2; 224fda9279dSmrg 225fda9279dSmrg if (nouveau_pushbuf_space(push, 64, 0, 0) || 226fda9279dSmrg nouveau_pushbuf_refn (push, refs, 3)) 227fda9279dSmrg return BadImplementation; 228fda9279dSmrg 2291090d90aSmrg if (pNv->dev->chipset >= 0x110) { 2301090d90aSmrg BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 2311090d90aSmrg PUSH_DATA (push, 256); 2321090d90aSmrg PUSH_DATA (push, (pNv->scratch->offset + PVP_DATA) >> 32); 2331090d90aSmrg PUSH_DATA (push, (pNv->scratch->offset + PVP_DATA)); 2341090d90aSmrg BEGIN_1IC0(push, NVC0_3D(CB_POS), 24 + 1); 2351090d90aSmrg PUSH_DATA (push, 0x80); 2361090d90aSmrg 2371090d90aSmrg PUSH_DATAf(push, sx1); 2381090d90aSmrg PUSH_DATAf(push, sy1); 2391090d90aSmrg PUSH_DATAf(push, 0); 2401090d90aSmrg PUSH_DATAf(push, 1); 2411090d90aSmrg PUSH_DATAf(push, tx1); 2421090d90aSmrg PUSH_DATAf(push, ty1); 2431090d90aSmrg PUSH_DATAf(push, 0); 2441090d90aSmrg PUSH_DATAf(push, 0); 2451090d90aSmrg 2461090d90aSmrg PUSH_DATAf(push, sx2+(sx2-sx1)); 2471090d90aSmrg PUSH_DATAf(push, sy1); 2481090d90aSmrg PUSH_DATAf(push, 0); 2491090d90aSmrg PUSH_DATAf(push, 1); 2501090d90aSmrg PUSH_DATAf(push, tx2+(tx2-tx1)); 2511090d90aSmrg PUSH_DATAf(push, ty1); 2521090d90aSmrg PUSH_DATAf(push, 0); 2531090d90aSmrg PUSH_DATAf(push, 0); 2541090d90aSmrg 2551090d90aSmrg PUSH_DATAf(push, sx1); 2561090d90aSmrg PUSH_DATAf(push, sy2+(sy2-sy1)); 2571090d90aSmrg PUSH_DATAf(push, 0); 2581090d90aSmrg PUSH_DATAf(push, 1); 2591090d90aSmrg PUSH_DATAf(push, tx1); 2601090d90aSmrg PUSH_DATAf(push, ty2+(ty2-ty1)); 2611090d90aSmrg PUSH_DATAf(push, 0); 2621090d90aSmrg PUSH_DATAf(push, 0); 2631090d90aSmrg } 2641090d90aSmrg 265fda9279dSmrg BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(0)), 2); 266fda9279dSmrg PUSH_DATA (push, sx2 << NVC0_3D_SCISSOR_HORIZ_MAX__SHIFT | sx1); 267fda9279dSmrg PUSH_DATA (push, sy2 << NVC0_3D_SCISSOR_VERT_MAX__SHIFT | sy1 ); 268fda9279dSmrg 269fda9279dSmrg BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 270fda9279dSmrg PUSH_DATA (push, NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES); 2711090d90aSmrg if (pNv->dev->chipset < 0x110) { 2721090d90aSmrg PUSH_VTX1s(push, tx1, ty1, sx1, sy1); 2731090d90aSmrg PUSH_VTX1s(push, tx2+(tx2-tx1), ty1, sx2+(sx2-sx1), sy1); 2741090d90aSmrg PUSH_VTX1s(push, tx1, ty2+(ty2-ty1), sx1, sy2+(sy2-sy1)); 2751090d90aSmrg } else { 2761090d90aSmrg BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2); 2771090d90aSmrg PUSH_DATA (push, 0); 2781090d90aSmrg PUSH_DATA (push, 3); 2791090d90aSmrg } 280fda9279dSmrg BEGIN_NVC0(push, NVC0_3D(VERTEX_END_GL), 1); 281fda9279dSmrg PUSH_DATA (push, 0); 282fda9279dSmrg 283fda9279dSmrg pbox++; 284fda9279dSmrg } 285fda9279dSmrg 286fda9279dSmrg PUSH_KICK(push); 287fda9279dSmrg return Success; 288fda9279dSmrg} 289fda9279dSmrg 290fda9279dSmrgvoid 291fda9279dSmrgnvc0_xv_csc_update(NVPtr pNv, float yco, float *off, float *uco, float *vco) 292fda9279dSmrg{ 293fda9279dSmrg struct nouveau_pushbuf *push = pNv->pushbuf; 294fda9279dSmrg 295fda9279dSmrg if (nouveau_pushbuf_space(push, 64, 0, 0) || 296fda9279dSmrg nouveau_pushbuf_refn (push, &(struct nouveau_pushbuf_refn) { 297fda9279dSmrg pNv->scratch, NOUVEAU_BO_WR | 298fda9279dSmrg NOUVEAU_BO_VRAM }, 1)) 299fda9279dSmrg return; 300fda9279dSmrg 301fda9279dSmrg BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 302fda9279dSmrg PUSH_DATA (push, 256); 303fda9279dSmrg PUSH_DATA (push, (pNv->scratch->offset + PFP_DATA) >> 32); 304fda9279dSmrg PUSH_DATA (push, (pNv->scratch->offset + PFP_DATA)); 305fda9279dSmrg BEGIN_NVC0(push, NVC0_3D(CB_POS), 11); 306fda9279dSmrg PUSH_DATA (push, 0); 307fda9279dSmrg PUSH_DATAf(push, yco); 308fda9279dSmrg PUSH_DATAf(push, off[0]); 309fda9279dSmrg PUSH_DATAf(push, off[1]); 310fda9279dSmrg PUSH_DATAf(push, off[2]); 311fda9279dSmrg PUSH_DATAf(push, uco[0]); 312fda9279dSmrg PUSH_DATAf(push, uco[1]); 313fda9279dSmrg PUSH_DATAf(push, uco[2]); 314fda9279dSmrg PUSH_DATAf(push, vco[0]); 315fda9279dSmrg PUSH_DATAf(push, vco[1]); 316fda9279dSmrg PUSH_DATAf(push, vco[2]); 317fda9279dSmrg} 318