1/* 2 * Copyright 2008 Ben Skeggs 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 shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include "config.h" 25#endif 26 27#include "xorg-config.h" 28#include "xf86xv.h" 29#include <X11/extensions/Xv.h> 30#include "exa.h" 31#include "damage.h" 32#include "dixstruct.h" 33#include "fourcc.h" 34 35#include "nv_include.h" 36#include "nvc0_accel.h" 37 38extern Atom xvSyncToVBlank, xvSetDefaults; 39 40static Bool 41nvc0_xv_check_image_put(PixmapPtr ppix) 42{ 43 switch (ppix->drawable.bitsPerPixel) { 44 case 32: 45 case 24: 46 case 16: 47 case 15: 48 break; 49 default: 50 return FALSE; 51 } 52 53 if (!nv50_style_tiled_pixmap(ppix)) 54 return FALSE; 55 56 return TRUE; 57} 58 59int 60nvc0_xv_image_put(ScrnInfoPtr pScrn, 61 struct nouveau_bo *src, int packed_y, int uv, 62 int id, int src_pitch, BoxPtr dstBox, 63 int x1, int y1, int x2, int y2, 64 uint16_t width, uint16_t height, 65 uint16_t src_w, uint16_t src_h, 66 uint16_t drw_w, uint16_t drw_h, 67 RegionPtr clipBoxes, PixmapPtr ppix, 68 NVPortPrivPtr pPriv) 69{ 70 NVPtr pNv = NVPTR(pScrn); 71 struct nouveau_bo *dst = nouveau_pixmap_bo(ppix); 72 struct nouveau_pushbuf_refn refs[] = { 73 { pNv->scratch, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR }, 74 { src, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD }, 75 { dst, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR }, 76 }; 77 struct nouveau_pushbuf *push = pNv->pushbuf; 78 float X1, X2, Y1, Y2; 79 BoxPtr pbox; 80 int nbox; 81 82 if (!nvc0_xv_check_image_put(ppix)) 83 return BadMatch; 84 85 if (!PUSH_SPACE(push, 256)) 86 return BadImplementation; 87 88 BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 8); 89 PUSH_DATA (push, dst->offset >> 32); 90 PUSH_DATA (push, dst->offset); 91 PUSH_DATA (push, ppix->drawable.width); 92 PUSH_DATA (push, ppix->drawable.height); 93 switch (ppix->drawable.depth) { 94 case 32: PUSH_DATA (push, NV50_SURFACE_FORMAT_BGRA8_UNORM); break; 95 case 30: PUSH_DATA (push, NV50_SURFACE_FORMAT_RGB10_A2_UNORM); break; 96 case 24: PUSH_DATA (push, NV50_SURFACE_FORMAT_BGRX8_UNORM); break; 97 case 16: PUSH_DATA (push, NV50_SURFACE_FORMAT_B5G6R5_UNORM); break; 98 case 15: PUSH_DATA (push, NV50_SURFACE_FORMAT_BGR5_X1_UNORM); break; 99 } 100 PUSH_DATA (push, dst->config.nvc0.tile_mode); 101 PUSH_DATA (push, 1); 102 PUSH_DATA (push, 0); 103 104 BEGIN_NVC0(push, NVC0_3D(BLEND_ENABLE(0)), 1); 105 PUSH_DATA (push, 0); 106 107 PUSH_DATAu(push, pNv->scratch, TIC_OFFSET, 16); 108 if (id == FOURCC_YV12 || id == FOURCC_I420) { 109 PUSH_TIC(push, src, packed_y, width, height, 0, 110 NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM | 111 NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM | 112 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | 113 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | 114 NV50TIC_0_0_FMT_8); 115 PUSH_TIC(push, src, uv, width >> 1, height >> 1, 0, 116 NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM | 117 NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | 118 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | 119 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | 120 NV50TIC_0_0_FMT_8_8); 121 } else { 122 unsigned format; 123 if (id == FOURCC_UYVY) { 124 format = NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM | 125 NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM | 126 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | 127 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | 128 NV50TIC_0_0_FMT_8_8; 129 } else { 130 format = NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM | 131 NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM | 132 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | 133 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | 134 NV50TIC_0_0_FMT_8_8; 135 } 136 PUSH_TIC(push, src, packed_y, width, height, 0, format); 137 138 if (id == FOURCC_UYVY) { 139 format = NV50TIC_0_0_MAPA_C2 | NV50TIC_0_0_TYPEA_UNORM | 140 NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | 141 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | 142 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | 143 NV50TIC_0_0_FMT_8_8_8_8; 144 } else { 145 format = NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | 146 NV50TIC_0_0_MAPB_C1 | NV50TIC_0_0_TYPEB_UNORM | 147 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | 148 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | 149 NV50TIC_0_0_FMT_8_8_8_8; 150 } 151 PUSH_TIC(push, src, packed_y, width >> 1, height, 0, format); 152 } 153 154 PUSH_DATAu(push, pNv->scratch, TSC_OFFSET, 16); 155 PUSH_DATA (push, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE | 156 NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE | 157 NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE); 158 PUSH_DATA (push, NV50TSC_1_1_MAGF_LINEAR | 159 NV50TSC_1_1_MINF_LINEAR | 160 NV50TSC_1_1_MIPF_NONE); 161 PUSH_DATA (push, 0x00000000); 162 PUSH_DATA (push, 0x00000000); 163 PUSH_DATA (push, 0x00000000); 164 PUSH_DATA (push, 0x00000000); 165 PUSH_DATA (push, 0x00000000); 166 PUSH_DATA (push, 0x00000000); 167 PUSH_DATA (push, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE | 168 NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE | 169 NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE); 170 PUSH_DATA (push, NV50TSC_1_1_MAGF_LINEAR | 171 NV50TSC_1_1_MINF_LINEAR | 172 NV50TSC_1_1_MIPF_NONE); 173 PUSH_DATA (push, 0x00000000); 174 PUSH_DATA (push, 0x00000000); 175 PUSH_DATA (push, 0x00000000); 176 PUSH_DATA (push, 0x00000000); 177 PUSH_DATA (push, 0x00000000); 178 PUSH_DATA (push, 0x00000000); 179 180 BEGIN_NVC0(push, NVC0_3D(SP_START_ID(5)), 1); 181 PUSH_DATA (push, PFP_NV12); 182 183 BEGIN_NVC0(push, NVC0_3D(TSC_FLUSH), 1); 184 PUSH_DATA (push, 0); 185 BEGIN_NVC0(push, NVC0_3D(TIC_FLUSH), 1); 186 PUSH_DATA (push, 0); 187 BEGIN_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 1); 188 PUSH_DATA (push, 0); 189 190 PUSH_DATAu(push, pNv->scratch, PVP_DATA, 11); 191 PUSH_DATAf(push, 1.0); 192 PUSH_DATAf(push, 0.0); 193 PUSH_DATAf(push, 0.0); 194 PUSH_DATAf(push, 0.0); 195 PUSH_DATAf(push, 1.0); 196 PUSH_DATAf(push, 0.0); 197 PUSH_DATAf(push, 0.0); 198 PUSH_DATAf(push, 0.0); 199 PUSH_DATAf(push, 1.0); 200 PUSH_DATAf(push, 1.0 / width); 201 PUSH_DATAf(push, 1.0 / height); 202 203 if (pPriv->SyncToVBlank) { 204 NVC0SyncToVBlank(ppix, dstBox); 205 } 206 207 /* These are fixed point values in the 16.16 format. */ 208 X1 = (float)(x1>>16)+(float)(x1&0xFFFF)/(float)0x10000; 209 Y1 = (float)(y1>>16)+(float)(y1&0xFFFF)/(float)0x10000; 210 X2 = (float)(x2>>16)+(float)(x2&0xFFFF)/(float)0x10000; 211 Y2 = (float)(y2>>16)+(float)(y2&0xFFFF)/(float)0x10000; 212 213 pbox = REGION_RECTS(clipBoxes); 214 nbox = REGION_NUM_RECTS(clipBoxes); 215 while(nbox--) { 216 float tx1=X1+(float)(pbox->x1 - dstBox->x1)*(X2-X1)/(float)(drw_w); 217 float tx2=X1+(float)(pbox->x2 - dstBox->x1)*(src_w)/(float)(drw_w); 218 float ty1=Y1+(float)(pbox->y1 - dstBox->y1)*(Y2-Y1)/(float)(drw_h); 219 float ty2=Y1+(float)(pbox->y2 - dstBox->y1)*(src_h)/(float)(drw_h); 220 int sx1=pbox->x1; 221 int sx2=pbox->x2; 222 int sy1=pbox->y1; 223 int sy2=pbox->y2; 224 225 if (nouveau_pushbuf_space(push, 64, 0, 0) || 226 nouveau_pushbuf_refn (push, refs, 3)) 227 return BadImplementation; 228 229 if (pNv->dev->chipset >= 0x110) { 230 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 231 PUSH_DATA (push, 256); 232 PUSH_DATA (push, (pNv->scratch->offset + PVP_DATA) >> 32); 233 PUSH_DATA (push, (pNv->scratch->offset + PVP_DATA)); 234 BEGIN_1IC0(push, NVC0_3D(CB_POS), 24 + 1); 235 PUSH_DATA (push, 0x80); 236 237 PUSH_DATAf(push, sx1); 238 PUSH_DATAf(push, sy1); 239 PUSH_DATAf(push, 0); 240 PUSH_DATAf(push, 1); 241 PUSH_DATAf(push, tx1); 242 PUSH_DATAf(push, ty1); 243 PUSH_DATAf(push, 0); 244 PUSH_DATAf(push, 0); 245 246 PUSH_DATAf(push, sx2+(sx2-sx1)); 247 PUSH_DATAf(push, sy1); 248 PUSH_DATAf(push, 0); 249 PUSH_DATAf(push, 1); 250 PUSH_DATAf(push, tx2+(tx2-tx1)); 251 PUSH_DATAf(push, ty1); 252 PUSH_DATAf(push, 0); 253 PUSH_DATAf(push, 0); 254 255 PUSH_DATAf(push, sx1); 256 PUSH_DATAf(push, sy2+(sy2-sy1)); 257 PUSH_DATAf(push, 0); 258 PUSH_DATAf(push, 1); 259 PUSH_DATAf(push, tx1); 260 PUSH_DATAf(push, ty2+(ty2-ty1)); 261 PUSH_DATAf(push, 0); 262 PUSH_DATAf(push, 0); 263 } 264 265 BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(0)), 2); 266 PUSH_DATA (push, sx2 << NVC0_3D_SCISSOR_HORIZ_MAX__SHIFT | sx1); 267 PUSH_DATA (push, sy2 << NVC0_3D_SCISSOR_VERT_MAX__SHIFT | sy1 ); 268 269 BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 270 PUSH_DATA (push, NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES); 271 if (pNv->dev->chipset < 0x110) { 272 PUSH_VTX1s(push, tx1, ty1, sx1, sy1); 273 PUSH_VTX1s(push, tx2+(tx2-tx1), ty1, sx2+(sx2-sx1), sy1); 274 PUSH_VTX1s(push, tx1, ty2+(ty2-ty1), sx1, sy2+(sy2-sy1)); 275 } else { 276 BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2); 277 PUSH_DATA (push, 0); 278 PUSH_DATA (push, 3); 279 } 280 BEGIN_NVC0(push, NVC0_3D(VERTEX_END_GL), 1); 281 PUSH_DATA (push, 0); 282 283 pbox++; 284 } 285 286 PUSH_KICK(push); 287 return Success; 288} 289 290void 291nvc0_xv_csc_update(NVPtr pNv, float yco, float *off, float *uco, float *vco) 292{ 293 struct nouveau_pushbuf *push = pNv->pushbuf; 294 295 if (nouveau_pushbuf_space(push, 64, 0, 0) || 296 nouveau_pushbuf_refn (push, &(struct nouveau_pushbuf_refn) { 297 pNv->scratch, NOUVEAU_BO_WR | 298 NOUVEAU_BO_VRAM }, 1)) 299 return; 300 301 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 302 PUSH_DATA (push, 256); 303 PUSH_DATA (push, (pNv->scratch->offset + PFP_DATA) >> 32); 304 PUSH_DATA (push, (pNv->scratch->offset + PFP_DATA)); 305 BEGIN_NVC0(push, NVC0_3D(CB_POS), 11); 306 PUSH_DATA (push, 0); 307 PUSH_DATAf(push, yco); 308 PUSH_DATAf(push, off[0]); 309 PUSH_DATAf(push, off[1]); 310 PUSH_DATAf(push, off[2]); 311 PUSH_DATAf(push, uco[0]); 312 PUSH_DATAf(push, uco[1]); 313 PUSH_DATAf(push, uco[2]); 314 PUSH_DATAf(push, vco[0]); 315 PUSH_DATAf(push, vco[1]); 316 PUSH_DATAf(push, vco[2]); 317} 318