Hint added.
[AROS.git] / workbench / hidds / nouveau / xf86-video-nouveau / nv40_exa.c
blob0ed70db25cbe87c75cc0c94836c6b379571e20e7
1 /*
2 * Copyright 2007 Ben Skeggs
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
23 #include "nv_include.h"
24 #include "nv30_shaders.h"
25 #include "nv04_pushbuf.h"
26 #if defined(__AROS__)
27 #include <aros/debug.h>
28 #define NV40EXA_STATE
29 #endif
31 typedef struct nv_pict_surface_format {
32 int pict_fmt;
33 uint32_t card_fmt;
34 } nv_pict_surface_format_t;
36 typedef struct nv_pict_texture_format {
37 int pict_fmt;
38 uint32_t card_fmt;
39 uint32_t card_swz;
40 } nv_pict_texture_format_t;
42 typedef struct nv_pict_op {
43 Bool src_alpha;
44 Bool dst_alpha;
45 uint32_t src_card_op;
46 uint32_t dst_card_op;
47 } nv_pict_op_t;
49 typedef struct nv40_exa_state {
50 Bool have_mask;
52 struct {
53 PictTransformPtr transform;
54 float width;
55 float height;
56 } unit[2];
57 } nv40_exa_state_t;
58 #if !defined(__AROS__)
59 static nv40_exa_state_t exa_state;
60 #define NV40EXA_STATE nv40_exa_state_t *state = &exa_state
61 #endif
63 static nv_pict_surface_format_t
64 NV40SurfaceFormat[] = {
65 { PICT_a8r8g8b8 , NV40TCL_RT_FORMAT_COLOR_A8R8G8B8 },
66 { PICT_x8r8g8b8 , NV40TCL_RT_FORMAT_COLOR_X8R8G8B8 },
67 { PICT_r5g6b5 , NV40TCL_RT_FORMAT_COLOR_R5G6B5 },
68 { PICT_a8 , NV40TCL_RT_FORMAT_COLOR_B8 },
69 { -1, ~0 }
72 static nv_pict_surface_format_t *
73 NV40_GetPictSurfaceFormat(int format)
75 int i = 0;
77 while (NV40SurfaceFormat[i].pict_fmt != -1) {
78 if (NV40SurfaceFormat[i].pict_fmt == format)
79 return &NV40SurfaceFormat[i];
80 i++;
83 return NULL;
86 enum {
87 NV40EXA_FPID_PASS_COL0 = 0,
88 NV40EXA_FPID_PASS_TEX0 = 1,
89 NV40EXA_FPID_COMPOSITE_MASK = 2,
90 NV40EXA_FPID_COMPOSITE_MASK_SA_CA = 3,
91 NV40EXA_FPID_COMPOSITE_MASK_CA = 4,
92 NV40EXA_FPID_MAX = 5
93 } NV40EXA_FPID;
95 static nv_shader_t *nv40_fp_map[NV40EXA_FPID_MAX] = {
96 &nv30_fp_pass_col0,
97 &nv30_fp_pass_tex0,
98 &nv30_fp_composite_mask,
99 &nv30_fp_composite_mask_sa_ca,
100 &nv30_fp_composite_mask_ca
103 static nv_shader_t *nv40_fp_map_a8[NV40EXA_FPID_MAX];
105 static void
106 NV40EXAHackupA8Shaders(ScrnInfoPtr pScrn)
108 int s;
110 for (s = 0; s < NV40EXA_FPID_MAX; s++) {
111 nv_shader_t *def, *a8;
113 def = nv40_fp_map[s];
114 a8 = calloc(1, sizeof(nv_shader_t));
115 a8->card_priv.NV30FP.num_regs = def->card_priv.NV30FP.num_regs;
116 a8->size = def->size + 4;
117 memcpy(a8->data, def->data, def->size * sizeof(uint32_t));
118 nv40_fp_map_a8[s] = a8;
120 a8->data[a8->size - 8 + 0] &= ~0x00000081;
121 a8->data[a8->size - 4 + 0] = 0x01401e81;
122 a8->data[a8->size - 4 + 1] = 0x1c9dfe00;
123 a8->data[a8->size - 4 + 2] = 0x0001c800;
124 a8->data[a8->size - 4 + 3] = 0x0001c800;
128 #define _(r,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w) \
130 PICT_##r, NV40TCL_TEX_FORMAT_FORMAT_##tf, \
131 NV40TCL_TEX_SWIZZLE_S0_X_##ts0x | NV40TCL_TEX_SWIZZLE_S0_Y_##ts0y | \
132 NV40TCL_TEX_SWIZZLE_S0_Z_##ts0z | NV40TCL_TEX_SWIZZLE_S0_W_##ts0w | \
133 NV40TCL_TEX_SWIZZLE_S1_X_##ts1x | NV40TCL_TEX_SWIZZLE_S1_Y_##ts1y | \
134 NV40TCL_TEX_SWIZZLE_S1_Z_##ts1z | NV40TCL_TEX_SWIZZLE_S1_W_##ts1w, \
136 static nv_pict_texture_format_t
137 NV40TextureFormat[] = {
138 _(a8r8g8b8, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W),
139 _(x8r8g8b8, A8R8G8B8, S1, S1, S1, ONE, X, Y, Z, W),
140 _(x8b8g8r8, A8R8G8B8, S1, S1, S1, ONE, Z, Y, X, W),
141 _(a1r5g5b5, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W),
142 _(x1r5g5b5, A1R5G5B5, S1, S1, S1, ONE, X, Y, Z, W),
143 _( r5g6b5, R5G6B5, S1, S1, S1, S1, X, Y, Z, W),
144 _( a8, L8, ZERO, ZERO, ZERO, S1, X, X, X, X),
145 { -1, ~0, ~0 }
147 #undef _
149 static nv_pict_texture_format_t *
150 NV40_GetPictTextureFormat(int format)
152 int i = 0;
154 while (NV40TextureFormat[i].pict_fmt != -1) {
155 if (NV40TextureFormat[i].pict_fmt == format)
156 return &NV40TextureFormat[i];
157 i++;
160 return NULL;
163 #define SF(bf) (NV40TCL_BLEND_FUNC_SRC_RGB_##bf | \
164 NV40TCL_BLEND_FUNC_SRC_ALPHA_##bf)
165 #define DF(bf) (NV40TCL_BLEND_FUNC_DST_RGB_##bf | \
166 NV40TCL_BLEND_FUNC_DST_ALPHA_##bf)
167 static nv_pict_op_t
168 NV40PictOp[] = {
169 /* Clear */ { 0, 0, SF( ZERO), DF( ZERO) },
170 /* Src */ { 0, 0, SF( ONE), DF( ZERO) },
171 /* Dst */ { 0, 0, SF( ZERO), DF( ONE) },
172 /* Over */ { 1, 0, SF( ONE), DF(ONE_MINUS_SRC_ALPHA) },
173 /* OverReverse */ { 0, 1, SF(ONE_MINUS_DST_ALPHA), DF( ONE) },
174 /* In */ { 0, 1, SF( DST_ALPHA), DF( ZERO) },
175 /* InReverse */ { 1, 0, SF( ZERO), DF( SRC_ALPHA) },
176 /* Out */ { 0, 1, SF(ONE_MINUS_DST_ALPHA), DF( ZERO) },
177 /* OutReverse */ { 1, 0, SF( ZERO), DF(ONE_MINUS_SRC_ALPHA) },
178 /* Atop */ { 1, 1, SF( DST_ALPHA), DF(ONE_MINUS_SRC_ALPHA) },
179 /* AtopReverse */ { 1, 1, SF(ONE_MINUS_DST_ALPHA), DF( SRC_ALPHA) },
180 /* Xor */ { 1, 1, SF(ONE_MINUS_DST_ALPHA), DF(ONE_MINUS_SRC_ALPHA) },
181 /* Add */ { 0, 0, SF( ONE), DF( ONE) },
182 /* OverAlpha */ { 1, 0, SF( SRC_ALPHA), DF(ONE_MINUS_SRC_ALPHA) }
185 static nv_pict_op_t *
186 NV40_GetPictOpRec(int op)
188 if (op >= PictOpSaturate)
189 return NULL;
190 return &NV40PictOp[op];
193 static void
194 NV40_SetupBlend(ScrnInfoPtr pScrn, nv_pict_op_t *blend,
195 PictFormatShort dest_format, Bool component_alpha)
197 NVPtr pNv = NVPTR(pScrn);
198 struct nouveau_channel *chan = pNv->chan;
199 struct nouveau_grobj *curie = pNv->Nv3D;
200 uint32_t sblend, dblend;
202 sblend = blend->src_card_op;
203 dblend = blend->dst_card_op;
205 if (blend->dst_alpha) {
206 if (!PICT_FORMAT_A(dest_format)) {
207 if (sblend == SF(DST_ALPHA)) {
208 sblend = SF(ONE);
209 } else if (sblend == SF(ONE_MINUS_DST_ALPHA)) {
210 sblend = SF(ZERO);
212 } else if (dest_format == PICT_a8) {
213 if (sblend == SF(DST_ALPHA)) {
214 sblend = SF(DST_COLOR);
215 } else if (sblend == SF(ONE_MINUS_DST_ALPHA)) {
216 sblend = SF(ONE_MINUS_DST_COLOR);
221 if (blend->src_alpha && (component_alpha || dest_format == PICT_a8)) {
222 if (dblend == DF(SRC_ALPHA)) {
223 dblend = DF(SRC_COLOR);
224 } else if (dblend == DF(ONE_MINUS_SRC_ALPHA)) {
225 dblend = DF(ONE_MINUS_SRC_COLOR);
229 if (sblend == SF(ONE) && dblend == DF(ZERO)) {
230 BEGIN_RING(chan, curie, NV40TCL_BLEND_ENABLE, 1);
231 OUT_RING (chan, 0);
232 } else {
233 BEGIN_RING(chan, curie, NV40TCL_BLEND_ENABLE, 5);
234 OUT_RING (chan, 1);
235 OUT_RING (chan, sblend);
236 OUT_RING (chan, dblend);
237 OUT_RING (chan, 0x00000000);
238 OUT_RING (chan, NV40TCL_BLEND_EQUATION_ALPHA_FUNC_ADD |
239 NV40TCL_BLEND_EQUATION_RGB_FUNC_ADD);
243 #if !defined(__AROS__)
244 static Bool
245 NV40EXATexture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit)
246 #else
247 static Bool
248 NV40EXATexture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit, nv40_exa_state_t * state)
249 #endif
251 NVPtr pNv = NVPTR(pScrn);
252 struct nouveau_channel *chan = pNv->chan;
253 struct nouveau_grobj *curie = pNv->Nv3D;
254 struct nouveau_bo *bo = nouveau_pixmap_bo(pPix);
255 unsigned tex_reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
256 nv_pict_texture_format_t *fmt;
257 NV40EXA_STATE;
259 fmt = NV40_GetPictTextureFormat(pPict->format);
260 if (!fmt)
261 return FALSE;
263 BEGIN_RING(chan, curie, NV40TCL_TEX_OFFSET(unit), 8);
264 if (OUT_RELOCl(chan, bo, 0, tex_reloc) ||
265 OUT_RELOCd(chan, bo, fmt->card_fmt | NV40TCL_TEX_FORMAT_LINEAR |
266 NV40TCL_TEX_FORMAT_DIMS_2D | 0x8000 |
267 NV40TCL_TEX_FORMAT_NO_BORDER |
268 (1 << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT),
269 tex_reloc | NOUVEAU_BO_OR,
270 NV40TCL_TEX_FORMAT_DMA0, NV40TCL_TEX_FORMAT_DMA1))
271 return FALSE;
273 if (pPict->repeat) {
274 switch(pPict->repeatType) {
275 case RepeatPad:
276 OUT_RING (chan, NV40TCL_TEX_WRAP_S_CLAMP |
277 NV40TCL_TEX_WRAP_T_CLAMP |
278 NV40TCL_TEX_WRAP_R_CLAMP);
279 break;
280 case RepeatReflect:
281 OUT_RING (chan, NV40TCL_TEX_WRAP_S_MIRRORED_REPEAT |
282 NV40TCL_TEX_WRAP_T_MIRRORED_REPEAT |
283 NV40TCL_TEX_WRAP_R_MIRRORED_REPEAT);
284 break;
285 case RepeatNormal:
286 default:
287 OUT_RING (chan, NV40TCL_TEX_WRAP_S_REPEAT |
288 NV40TCL_TEX_WRAP_T_REPEAT |
289 NV40TCL_TEX_WRAP_R_REPEAT);
290 break;
292 } else {
293 OUT_RING (chan, NV40TCL_TEX_WRAP_S_CLAMP_TO_BORDER |
294 NV40TCL_TEX_WRAP_T_CLAMP_TO_BORDER |
295 NV40TCL_TEX_WRAP_R_CLAMP_TO_BORDER);
297 OUT_RING (chan, NV40TCL_TEX_ENABLE_ENABLE);
298 OUT_RING (chan, fmt->card_swz);
299 if (pPict->filter == PictFilterBilinear) {
300 OUT_RING (chan, NV40TCL_TEX_FILTER_MIN_LINEAR |
301 NV40TCL_TEX_FILTER_MAG_LINEAR | 0x3fd6);
302 } else {
303 OUT_RING (chan, NV40TCL_TEX_FILTER_MIN_NEAREST |
304 NV40TCL_TEX_FILTER_MAG_NEAREST | 0x3fd6);
306 #if !defined(__AROS__)
307 OUT_RING (chan, (pPix->drawable.width << 16) | pPix->drawable.height);
308 OUT_RING (chan, 0); /* border ARGB */
309 BEGIN_RING(chan, curie, NV40TCL_TEX_SIZE1(unit), 1);
310 OUT_RING (chan, (1 << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) |
311 (uint32_t)exaGetPixmapPitch(pPix));
313 state->unit[unit].width = (float)pPix->drawable.width;
314 state->unit[unit].height = (float)pPix->drawable.height;
315 state->unit[unit].transform = pPict->transform;
316 #else
317 OUT_RING (chan, (pPix->width << 16) | pPix->height);
318 OUT_RING (chan, 0); /* border ARGB */
319 BEGIN_RING(chan, curie, NV40TCL_TEX_SIZE1(unit), 1);
320 OUT_RING (chan, (1 << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) |
321 (uint32_t)pPix->pitch);
323 state->unit[unit].width = (float)pPix->width;
324 state->unit[unit].height = (float)pPix->height;
325 state->unit[unit].transform = NULL; /* Keep this NULL, we are doing simple blits */
326 #endif
327 return TRUE;
330 static Bool
331 NV40_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PictFormatShort format)
333 NVPtr pNv = NVPTR(pScrn);
334 struct nouveau_channel *chan = pNv->chan;
335 struct nouveau_grobj *curie = pNv->Nv3D;
336 struct nouveau_bo *bo = nouveau_pixmap_bo(pPix);
337 nv_pict_surface_format_t *fmt;
339 fmt = NV40_GetPictSurfaceFormat(format);
340 if (!fmt) {
341 ErrorF("AIII no format\n");
342 return FALSE;
345 BEGIN_RING(chan, curie, NV40TCL_RT_FORMAT, 3);
346 OUT_RING (chan, NV40TCL_RT_FORMAT_TYPE_LINEAR |
347 NV40TCL_RT_FORMAT_ZETA_Z24S8 |
348 fmt->card_fmt);
349 OUT_RING (chan, exaGetPixmapPitch(pPix));
350 if (OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR))
351 return FALSE;
353 return TRUE;
356 #if !defined(__AROS__)
357 static Bool
358 NV40EXACheckCompositeTexture(PicturePtr pPict, PicturePtr pdPict, int op)
360 nv_pict_texture_format_t *fmt;
361 int w, h;
363 if (!pPict->pDrawable)
364 NOUVEAU_FALLBACK("Solid and gradient pictures unsupported\n");
366 w = pPict->pDrawable->width;
367 h = pPict->pDrawable->height;
369 if ((w > 4096) || (h > 4096))
370 NOUVEAU_FALLBACK("picture too large, %dx%d\n", w, h);
372 fmt = NV40_GetPictTextureFormat(pPict->format);
373 if (!fmt)
374 NOUVEAU_FALLBACK("picture format 0x%08x not supported\n",
375 pPict->format);
377 if (pPict->filter != PictFilterNearest &&
378 pPict->filter != PictFilterBilinear)
379 NOUVEAU_FALLBACK("filter 0x%x not supported\n", pPict->filter);
381 /* Opengl and Render disagree on what should be sampled outside an XRGB
382 * texture (with no repeating). Opengl has a hardcoded alpha value of
383 * 1.0, while render expects 0.0. We assume that clipping is done for
384 * untranformed sources.
386 if (NV40PictOp[op].src_alpha && !pPict->repeat &&
387 pPict->transform && (PICT_FORMAT_A(pPict->format) == 0)
388 && (PICT_FORMAT_A(pdPict->format) != 0))
389 NOUVEAU_FALLBACK("REPEAT_NONE unsupported for XRGB source\n");
391 return TRUE;
394 Bool
395 NV40EXACheckComposite(int op, PicturePtr psPict,
396 PicturePtr pmPict,
397 PicturePtr pdPict)
399 nv_pict_surface_format_t *fmt;
400 nv_pict_op_t *opr;
402 opr = NV40_GetPictOpRec(op);
403 if (!opr)
404 NOUVEAU_FALLBACK("unsupported blend op 0x%x\n", op);
406 fmt = NV40_GetPictSurfaceFormat(pdPict->format);
407 if (!fmt)
408 NOUVEAU_FALLBACK("dst picture format 0x%08x not supported\n",
409 pdPict->format);
411 if (!NV40EXACheckCompositeTexture(psPict, pdPict, op))
412 NOUVEAU_FALLBACK("src picture\n");
413 if (pmPict) {
414 if (pmPict->componentAlpha &&
415 PICT_FORMAT_RGB(pmPict->format) &&
416 opr->src_alpha && opr->src_card_op != SF(ZERO))
417 NOUVEAU_FALLBACK("mask CA + SA\n");
418 if (!NV40EXACheckCompositeTexture(pmPict, pdPict, op))
419 NOUVEAU_FALLBACK("mask picture\n");
422 return TRUE;
425 static void
426 NV40EXAStateCompositeReemit(struct nouveau_channel *chan)
428 ScrnInfoPtr pScrn = chan->user_private;
429 NVPtr pNv = NVPTR(pScrn);
431 NV40EXAPrepareComposite(pNv->alu, pNv->pspict, pNv->pmpict, pNv->pdpict,
432 pNv->pspix, pNv->pmpix, pNv->pdpix);
434 #endif
436 #if !defined(__AROS__)
437 Bool
438 NV40EXAPrepareComposite(int op, PicturePtr psPict,
439 PicturePtr pmPict,
440 PicturePtr pdPict,
441 PixmapPtr psPix,
442 PixmapPtr pmPix,
443 PixmapPtr pdPix)
445 ScrnInfoPtr pScrn = xf86Screens[psPix->drawable.pScreen->myNum];
446 #else
447 static Bool
448 NV40EXAPrepareComposite(int op, PicturePtr psPict,
449 PicturePtr pmPict,
450 PicturePtr pdPict,
451 PixmapPtr psPix,
452 PixmapPtr pmPix,
453 PixmapPtr pdPix,
454 nv40_exa_state_t * state)
456 ScrnInfoPtr pScrn = globalcarddataptr;
457 #endif
458 NVPtr pNv = NVPTR(pScrn);
459 struct nouveau_channel *chan = pNv->chan;
460 struct nouveau_grobj *curie = pNv->Nv3D;
461 nv_pict_op_t *blend;
462 int fpid = NV40EXA_FPID_PASS_COL0;
463 NV40EXA_STATE;
465 if (MARK_RING(chan, 128, 1 + 1 + 2*2))
466 return FALSE;
468 blend = NV40_GetPictOpRec(op);
470 NV40_SetupBlend(pScrn, blend, pdPict->format,
471 (pmPict && pmPict->componentAlpha &&
472 PICT_FORMAT_RGB(pmPict->format)));
474 if (!NV40_SetupSurface(pScrn, pdPix, pdPict->format) ||
475 #if !defined(__AROS__)
476 !NV40EXATexture(pScrn, psPix, psPict, 0)) {
477 #else
478 !NV40EXATexture(pScrn, psPix, psPict, 0, state)) {
479 #endif
480 MARK_UNDO(chan);
481 return FALSE;
484 NV40_LoadVtxProg(pScrn, &nv40_vp_exa_render);
485 if (pmPict) {
486 #if !defined(__AROS__)
487 if (!NV40EXATexture(pScrn, pmPix, pmPict, 1)) {
488 #else
489 if (!NV40EXATexture(pScrn, pmPix, pmPict, 1, state)) {
490 #endif
491 MARK_UNDO(chan);
492 return FALSE;
495 if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) {
496 if (blend->src_alpha)
497 fpid = NV40EXA_FPID_COMPOSITE_MASK_SA_CA;
498 else
499 fpid = NV40EXA_FPID_COMPOSITE_MASK_CA;
500 } else {
501 fpid = NV40EXA_FPID_COMPOSITE_MASK;
504 state->have_mask = TRUE;
505 } else {
506 fpid = NV40EXA_FPID_PASS_TEX0;
508 state->have_mask = FALSE;
512 if (!NV40_LoadFragProg(pScrn, (pdPict->format == PICT_a8) ?
513 nv40_fp_map_a8[fpid] : nv40_fp_map[fpid])) {
514 MARK_UNDO(chan);
515 return FALSE;
518 /* Appears to be some kind of cache flush, needed here at least
519 * sometimes.. funky text rendering otherwise :)
521 BEGIN_RING(chan, curie, NV40TCL_TEX_CACHE_CTL, 1);
522 OUT_RING (chan, 2);
523 BEGIN_RING(chan, curie, NV40TCL_TEX_CACHE_CTL, 1);
524 OUT_RING (chan, 1);
526 #if !defined(__AROS__)
527 pNv->alu = op;
528 pNv->pspict = psPict;
529 pNv->pmpict = pmPict;
530 pNv->pdpict = pdPict;
531 pNv->pspix = psPix;
532 pNv->pmpix = pmPix;
533 pNv->pdpix = pdPix;
534 chan->flush_notify = NV40EXAStateCompositeReemit;
535 #else
536 chan->flush_notify = NULL;
537 #endif
538 return TRUE;
541 #define xFixedToFloat(v) \
542 ((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0))
544 static inline void
545 NV40EXATransformCoord(PictTransformPtr t, int x, int y, float sx, float sy,
546 float *x_ret, float *y_ret)
548 if (t) {
549 /* Note: current t is always NULL in AROS. That is good enough for
550 operations being done (simple blits with alpha) */
551 #if !defined(__AROS__)
552 PictVector v;
553 v.vector[0] = IntToxFixed(x);
554 v.vector[1] = IntToxFixed(y);
555 v.vector[2] = xFixed1;
556 PictureTransformPoint(t, &v);
557 *x_ret = xFixedToFloat(v.vector[0]) / sx;
558 *y_ret = xFixedToFloat(v.vector[1]) / sy;
559 #endif
560 } else {
561 *x_ret = (float)x / sx;
562 *y_ret = (float)y / sy;
566 #define CV_OUTm(sx,sy,mx,my,dx,dy) do { \
567 BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_2F_X(8), 4); \
568 OUT_RINGf (chan, (sx)); OUT_RINGf (chan, (sy)); \
569 OUT_RINGf (chan, (mx)); OUT_RINGf (chan, (my)); \
570 BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_2I(0), 1); \
571 OUT_RING (chan, ((dy)<<16)|(dx)); \
572 } while(0)
573 #define CV_OUT(sx,sy,dx,dy) do { \
574 BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_2F_X(8), 2); \
575 OUT_RINGf (chan, (sx)); OUT_RINGf (chan, (sy)); \
576 BEGIN_RING(chan, curie, NV40TCL_VTX_ATTR_2I(0), 1); \
577 OUT_RING (chan, ((dy)<<16)|(dx)); \
578 } while(0)
580 #if !defined(__AROS__)
581 void
582 NV40EXAComposite(PixmapPtr pdPix, int srcX , int srcY,
583 int maskX, int maskY,
584 int dstX , int dstY,
585 int width, int height)
587 ScrnInfoPtr pScrn = xf86Screens[pdPix->drawable.pScreen->myNum];
588 #else
589 static void
590 NV40EXAComposite(PixmapPtr pdPix, int srcX , int srcY,
591 int maskX, int maskY,
592 int dstX , int dstY,
593 int width, int height, nv40_exa_state_t * state)
595 ScrnInfoPtr pScrn = globalcarddataptr;
596 #endif
597 NVPtr pNv = NVPTR(pScrn);
598 struct nouveau_channel *chan = pNv->chan;
599 struct nouveau_grobj *curie = pNv->Nv3D;
600 float sX0=0.0f, sX1=0.0f, sX2=0.0f, sY0=0.0f, sY1=0.0f, sY2=0.0f;
601 float mX0=0.0f, mX1=0.0f, mX2=0.0f, mY0=0.0f, mY1=0.0f, mY2=0.0f;
602 NV40EXA_STATE;
604 WAIT_RING(chan, 64);
606 /* We're drawing a triangle, we need to scissor it to a quad. */
607 /* The scissors are here for a good reason, we don't get the full
608 * image, but just a part.
610 /* Handling the cliprects is done for us already. */
611 BEGIN_RING(chan, curie, NV40TCL_SCISSOR_HORIZ, 2);
612 OUT_RING (chan, (width << 16) | dstX);
613 OUT_RING (chan, (height << 16) | dstY);
614 BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1);
615 OUT_RING (chan, NV40TCL_BEGIN_END_TRIANGLES);
617 NV40EXATransformCoord(state->unit[0].transform, srcX, srcY - height,
618 state->unit[0].width, state->unit[0].height,
619 &sX0, &sY0);
620 NV40EXATransformCoord(state->unit[0].transform, srcX, srcY + height,
621 state->unit[0].width, state->unit[0].height,
622 &sX1, &sY1);
623 NV40EXATransformCoord(state->unit[0].transform,
624 srcX + 2*width, srcY + height,
625 state->unit[0].width,
626 state->unit[0].height, &sX2, &sY2);
628 if (state->have_mask) {
629 NV40EXATransformCoord(state->unit[1].transform,
630 maskX, maskY - height,
631 state->unit[1].width,
632 state->unit[1].height, &mX0, &mY0);
633 NV40EXATransformCoord(state->unit[1].transform,
634 maskX, maskY + height,
635 state->unit[1].width,
636 state->unit[1].height, &mX1, &mY1);
637 NV40EXATransformCoord(state->unit[1].transform,
638 maskX + 2*width, maskY + height,
639 state->unit[1].width,
640 state->unit[1].height, &mX2, &mY2);
642 CV_OUTm(sX0, sY0, mX0, mY0, dstX, dstY - height);
643 CV_OUTm(sX1, sY1, mX1, mY1, dstX, dstY + height);
644 CV_OUTm(sX2, sY2, mX2, mY2, dstX + 2*width, dstY + height);
645 } else {
646 CV_OUT(sX0, sY0, dstX, dstY - height);
647 CV_OUT(sX1, sY1, dstX, dstY + height);
648 CV_OUT(sX2, sY2, dstX + 2*width, dstY + height);
651 BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1);
652 OUT_RING (chan, NV40TCL_BEGIN_END_STOP);
655 #if !defined(__AROS__)
656 void
657 NV40EXADoneComposite(PixmapPtr pdPix)
659 ScrnInfoPtr pScrn = xf86Screens[pdPix->drawable.pScreen->myNum];
660 NVPtr pNv = NVPTR(pScrn);
661 struct nouveau_channel *chan = pNv->chan;
663 chan->flush_notify = NULL;
665 #endif
667 #define NV40TCL_CHIPSET_4X_MASK 0x00000baf
668 #define NV44TCL_CHIPSET_4X_MASK 0x00005450
669 Bool
670 NVAccelInitNV40TCL(ScrnInfoPtr pScrn)
672 NVPtr pNv = NVPTR(pScrn);
673 struct nouveau_channel *chan = pNv->chan;
674 struct nouveau_grobj *curie;
675 uint32_t class = 0, chipset;
676 int next_hw_id = 0, next_hw_offset = 0, i;
678 if (!nv40_fp_map_a8[0])
679 NV40EXAHackupA8Shaders(pScrn);
681 chipset = pNv->dev->chipset;
682 if ((chipset & 0xf0) == NV_ARCH_40) {
683 chipset &= 0xf;
684 if (NV40TCL_CHIPSET_4X_MASK & (1<<chipset))
685 class = NV40TCL;
686 else if (NV44TCL_CHIPSET_4X_MASK & (1<<chipset))
687 class = NV44TCL;
688 else {
689 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
690 "NV40EXA: Unknown chipset NV4%1x\n", chipset);
691 return FALSE;
693 } else if ( (chipset & 0xf0) == 0x60) {
694 class = NV44TCL;
695 } else
696 return TRUE;
698 if (!pNv->Nv3D) {
699 if (nouveau_grobj_alloc(pNv->chan, Nv3D, class, &pNv->Nv3D))
700 return FALSE;
702 curie = pNv->Nv3D;
704 if (!pNv->shader_mem) {
705 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
706 NOUVEAU_BO_MAP, 0, 0x1000,
707 &pNv->shader_mem)) {
708 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
709 "Couldn't alloc fragprog buffer!\n");
710 nouveau_grobj_free(&pNv->Nv3D);
711 return FALSE;
715 BEGIN_RING(chan, curie, NV40TCL_DMA_NOTIFY, 1);
716 OUT_RING (chan, pNv->notify0->handle);
717 BEGIN_RING(chan, curie, NV40TCL_DMA_TEXTURE0, 2);
718 OUT_RING (chan, pNv->chan->vram->handle);
719 OUT_RING (chan, pNv->chan->gart->handle);
720 BEGIN_RING(chan, curie, NV40TCL_DMA_COLOR0, 2);
721 OUT_RING (chan, pNv->chan->vram->handle);
722 OUT_RING (chan, pNv->chan->vram->handle);
724 /* voodoo */
725 BEGIN_RING(chan, curie, 0x1ea4, 3);
726 OUT_RING (chan, 0x00000010);
727 OUT_RING (chan, 0x01000100);
728 OUT_RING (chan, 0xff800006);
729 BEGIN_RING(chan, curie, 0x1fc4, 1);
730 OUT_RING (chan, 0x06144321);
731 BEGIN_RING(chan, curie, 0x1fc8, 2);
732 OUT_RING (chan, 0xedcba987);
733 OUT_RING (chan, 0x00000021);
734 BEGIN_RING(chan, curie, 0x1fd0, 1);
735 OUT_RING (chan, 0x00171615);
736 BEGIN_RING(chan, curie, 0x1fd4, 1);
737 OUT_RING (chan, 0x001b1a19);
738 BEGIN_RING(chan, curie, 0x1ef8, 1);
739 OUT_RING (chan, 0x0020ffff);
740 BEGIN_RING(chan, curie, 0x1d64, 1);
741 OUT_RING (chan, 0x00d30000);
742 BEGIN_RING(chan, curie, 0x1e94, 1);
743 OUT_RING (chan, 0x00000001);
745 /* This removes the the stair shaped tearing that i get. */
746 /* Verified on one G70 card that it doesn't cause regressions for people without the problem. */
747 /* The blob sets this up by default for NV43. */
748 BEGIN_RING(chan, curie, 0x1450, 1);
749 OUT_RING (chan, 0x0000000F);
751 BEGIN_RING(chan, curie, NV40TCL_VIEWPORT_TRANSLATE_X, 8);
752 OUT_RINGf (chan, 0.0);
753 OUT_RINGf (chan, 0.0);
754 OUT_RINGf (chan, 0.0);
755 OUT_RINGf (chan, 0.0);
756 OUT_RINGf (chan, 1.0);
757 OUT_RINGf (chan, 1.0);
758 OUT_RINGf (chan, 1.0);
759 OUT_RINGf (chan, 0.0);
761 /* default 3D state */
762 /*XXX: replace with the same state that the DRI emits on startup */
763 BEGIN_RING(chan, curie, NV40TCL_STENCIL_FRONT_ENABLE, 1);
764 OUT_RING (chan, 0);
765 BEGIN_RING(chan, curie, NV40TCL_STENCIL_BACK_ENABLE, 1);
766 OUT_RING (chan, 0);
767 BEGIN_RING(chan, curie, NV40TCL_ALPHA_TEST_ENABLE, 1);
768 OUT_RING (chan, 0);
769 BEGIN_RING(chan, curie, NV40TCL_DEPTH_WRITE_ENABLE, 2);
770 OUT_RING (chan, 0);
771 OUT_RING (chan, 0);
772 BEGIN_RING(chan, curie, NV40TCL_COLOR_MASK, 1);
773 OUT_RING (chan, 0x01010101); /* TR,TR,TR,TR */
774 BEGIN_RING(chan, curie, NV40TCL_CULL_FACE_ENABLE, 1);
775 OUT_RING (chan, 0);
776 BEGIN_RING(chan, curie, NV40TCL_BLEND_ENABLE, 1);
777 OUT_RING (chan, 0);
778 BEGIN_RING(chan, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 2);
779 OUT_RING (chan, 0);
780 OUT_RING (chan, NV40TCL_COLOR_LOGIC_OP_COPY);
781 BEGIN_RING(chan, curie, NV40TCL_DITHER_ENABLE, 1);
782 OUT_RING (chan, 0);
783 BEGIN_RING(chan, curie, NV40TCL_SHADE_MODEL, 1);
784 OUT_RING (chan, NV40TCL_SHADE_MODEL_SMOOTH);
785 BEGIN_RING(chan, curie, NV40TCL_POLYGON_OFFSET_FACTOR,2);
786 OUT_RINGf (chan, 0.0);
787 OUT_RINGf (chan, 0.0);
788 BEGIN_RING(chan, curie, NV40TCL_POLYGON_MODE_FRONT, 2);
789 OUT_RING (chan, NV40TCL_POLYGON_MODE_FRONT_FILL);
790 OUT_RING (chan, NV40TCL_POLYGON_MODE_BACK_FILL);
791 BEGIN_RING(chan, curie, NV40TCL_POLYGON_STIPPLE_PATTERN(0), 0x20);
792 for (i=0;i<0x20;i++)
793 OUT_RING (chan, 0xFFFFFFFF);
794 for (i=0;i<16;i++) {
795 BEGIN_RING(chan, curie, NV40TCL_TEX_ENABLE(i), 1);
796 OUT_RING (chan, 0);
799 BEGIN_RING(chan, curie, 0x1d78, 1);
800 OUT_RING (chan, 0x110);
802 BEGIN_RING(chan, curie, NV40TCL_RT_ENABLE, 1);
803 OUT_RING (chan, NV40TCL_RT_ENABLE_COLOR0);
805 BEGIN_RING(chan, curie, NV40TCL_RT_HORIZ, 2);
806 OUT_RING (chan, (4096 << 16));
807 OUT_RING (chan, (4096 << 16));
808 BEGIN_RING(chan, curie, NV40TCL_SCISSOR_HORIZ, 2);
809 OUT_RING (chan, (4096 << 16));
810 OUT_RING (chan, (4096 << 16));
811 BEGIN_RING(chan, curie, NV40TCL_VIEWPORT_HORIZ, 2);
812 OUT_RING (chan, (4096 << 16));
813 OUT_RING (chan, (4096 << 16));
814 BEGIN_RING(chan, curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2);
815 OUT_RING (chan, (4095 << 16));
816 OUT_RING (chan, (4095 << 16));
818 NV40_UploadVtxProg(pNv, &nv40_vp_exa_render, &next_hw_id);
819 for (i = 0; i < NV40EXA_FPID_MAX; i++) {
820 NV30_UploadFragProg(pNv, nv40_fp_map[i], &next_hw_offset);
821 NV30_UploadFragProg(pNv, nv40_fp_map_a8[i], &next_hw_offset);
824 NV40_UploadVtxProg(pNv, &nv40_vp_video, &next_hw_id);
825 NV30_UploadFragProg(pNv, &nv40_fp_yv12_bicubic, &next_hw_offset);
826 NV30_UploadFragProg(pNv, &nv30_fp_yv12_bilinear, &next_hw_offset);
828 return TRUE;
831 /* AROS CODE */
833 /* NOTE: Assumes lock on bitmap is already made */
834 /* NOTE: Assumes buffer is not mapped */
835 /* NOTE: Allows different formats of source and destination */
836 BOOL HIDDNouveauNV403DCopyBox(struct CardData * carddata,
837 struct HIDDNouveauBitMapData * srcdata, struct HIDDNouveauBitMapData * destdata,
838 LONG srcX, LONG srcY, LONG destX, LONG destY, LONG width, LONG height,
839 ULONG blendop)
841 struct Picture sPict, dPict;
842 nv40_exa_state_t state;
843 LONG maskX = 0; LONG maskY = 0;
845 HIDDNouveauFillPictureFromBitMapData(&sPict, srcdata);
846 HIDDNouveauFillPictureFromBitMapData(&dPict, destdata);
848 if (NV40EXAPrepareComposite(blendop,
849 &sPict, NULL, &dPict, srcdata, NULL, destdata, &state))
851 NV40EXAComposite(destdata, srcX, srcY,
852 maskX, maskY,
853 destX , destY,
854 width, height, &state);
855 return TRUE;
858 return FALSE;