Hint added.
[AROS.git] / workbench / hidds / nouveau / xf86-video-nouveau / nv50_exa.c
blobeee472b883e5abad452d819ce3f62bff6e19c5e5
1 /*
2 * Copyright 2007 NVIDIA, Corporation
3 * Copyright 2008 Ben Skeggs
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
24 #include "nv_include.h"
25 #include "nv_rop.h"
27 #include "nv04_pushbuf.h"
28 #include "nv50_accel.h"
29 #include "nv50_texture.h"
31 struct nv50_exa_state {
32 Bool have_mask;
34 struct {
35 PictTransformPtr transform;
36 float width;
37 float height;
38 } unit[2];
40 #if !defined(__AROS__)
41 static struct nv50_exa_state exa_state;
43 #define NV50EXA_LOCALS(p) \
44 ScrnInfoPtr pScrn = xf86Screens[(p)->drawable.pScreen->myNum]; \
45 NVPtr pNv = NVPTR(pScrn); \
46 struct nouveau_channel *chan = pNv->chan; (void)chan; \
47 struct nouveau_grobj *eng2d = pNv->Nv2D; (void)eng2d; \
48 struct nouveau_grobj *tesla = pNv->Nv3D; (void)tesla; \
49 struct nv50_exa_state *state = &exa_state; (void)state
50 #else
51 #define NV50EXA_LOCALS(p) \
52 ScrnInfoPtr pScrn = globalcarddataptr; \
53 NVPtr pNv = NVPTR(pScrn); \
54 struct nouveau_channel *chan = pNv->chan; (void)chan; \
55 struct nouveau_grobj *eng2d = pNv->Nv2D; (void)eng2d; \
56 struct nouveau_grobj *tesla = pNv->Nv3D; (void)tesla;
58 #endif
60 #define BF(f) NV50TCL_BLEND_FUNC_SRC_RGB_##f
62 struct nv50_blend_op {
63 unsigned src_alpha;
64 unsigned dst_alpha;
65 unsigned src_blend;
66 unsigned dst_blend;
69 static struct nv50_blend_op
70 NV50EXABlendOp[] = {
71 /* Clear */ { 0, 0, BF( ZERO), BF( ZERO) },
72 /* Src */ { 0, 0, BF( ONE), BF( ZERO) },
73 /* Dst */ { 0, 0, BF( ZERO), BF( ONE) },
74 /* Over */ { 1, 0, BF( ONE), BF(ONE_MINUS_SRC_ALPHA) },
75 /* OverReverse */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF( ONE) },
76 /* In */ { 0, 1, BF( DST_ALPHA), BF( ZERO) },
77 /* InReverse */ { 1, 0, BF( ZERO), BF( SRC_ALPHA) },
78 /* Out */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF( ZERO) },
79 /* OutReverse */ { 1, 0, BF( ZERO), BF(ONE_MINUS_SRC_ALPHA) },
80 /* Atop */ { 1, 1, BF( DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) },
81 /* AtopReverse */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF( SRC_ALPHA) },
82 /* Xor */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) },
83 /* Add */ { 0, 0, BF( ONE), BF( ONE) },
84 /* OverAlpha */ { 1, 0, BF( SRC_ALPHA), BF(ONE_MINUS_SRC_ALPHA) },
87 static Bool
88 NV50EXA2DSurfaceFormat(PixmapPtr ppix, uint32_t *fmt)
90 NV50EXA_LOCALS(ppix);
92 #if !defined(__AROS__)
93 switch (ppix->drawable.bitsPerPixel) {
94 #else
95 switch (ppix->depth) {
96 #endif
97 case 8 : *fmt = NV50_2D_SRC_FORMAT_R8_UNORM; break;
98 case 15: *fmt = NV50_2D_SRC_FORMAT_X1R5G5B5_UNORM; break;
99 case 16: *fmt = NV50_2D_SRC_FORMAT_R5G6B5_UNORM; break;
100 case 24: *fmt = NV50_2D_SRC_FORMAT_X8R8G8B8_UNORM; break;
101 case 30: *fmt = NV50_2D_SRC_FORMAT_A2B10G10R10_UNORM; break;
102 case 32: *fmt = NV50_2D_SRC_FORMAT_A8R8G8B8_UNORM; break;
103 default:
104 NOUVEAU_FALLBACK("Unknown surface format for bpp=%d\n",
105 ppix->drawable.bitsPerPixel);
106 return FALSE;
109 return TRUE;
112 static void NV50EXASetClip(PixmapPtr ppix, int x, int y, int w, int h)
114 NV50EXA_LOCALS(ppix);
116 BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4);
117 OUT_RING (chan, x);
118 OUT_RING (chan, y);
119 OUT_RING (chan, w);
120 OUT_RING (chan, h);
123 static Bool
124 NV50EXAAcquireSurface2D(PixmapPtr ppix, int is_src)
126 NV50EXA_LOCALS(ppix);
127 struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
128 int mthd = is_src ? NV50_2D_SRC_FORMAT : NV50_2D_DST_FORMAT;
129 uint32_t fmt, bo_flags;
131 if (!NV50EXA2DSurfaceFormat(ppix, &fmt))
132 return FALSE;
134 bo_flags = NOUVEAU_BO_VRAM;
135 bo_flags |= is_src ? NOUVEAU_BO_RD : NOUVEAU_BO_WR;
137 if (!nv50_style_tiled_pixmap(ppix)) {
138 BEGIN_RING(chan, eng2d, mthd, 2);
139 OUT_RING (chan, fmt);
140 OUT_RING (chan, 1);
141 BEGIN_RING(chan, eng2d, mthd + 0x14, 1);
142 OUT_RING (chan, (uint32_t)exaGetPixmapPitch(ppix));
143 } else {
144 BEGIN_RING(chan, eng2d, mthd, 5);
145 OUT_RING (chan, fmt);
146 OUT_RING (chan, 0);
147 OUT_RING (chan, bo->tile_mode << 4);
148 OUT_RING (chan, 1);
149 OUT_RING (chan, 0);
152 BEGIN_RING(chan, eng2d, mthd + 0x18, 4);
153 #if !defined(__AROS__)
154 OUT_RING (chan, ppix->drawable.width);
155 OUT_RING (chan, ppix->drawable.height);
156 #else
157 OUT_RING (chan, ppix->width);
158 OUT_RING (chan, ppix->height);
159 #endif
160 if (OUT_RELOCh(chan, bo, 0, bo_flags) ||
161 OUT_RELOCl(chan, bo, 0, bo_flags))
162 return FALSE;
164 if (is_src == 0)
165 #if !defined(__AROS__)
166 NV50EXASetClip(ppix, 0, 0, ppix->drawable.width, ppix->drawable.height);
167 #else
168 NV50EXASetClip(ppix, 0, 0, ppix->width, ppix->height);
169 #endif
171 return TRUE;
174 static void
175 NV50EXASetPattern(PixmapPtr pdpix, int col0, int col1, int pat0, int pat1)
177 NV50EXA_LOCALS(pdpix);
179 BEGIN_RING(chan, eng2d, NV50_2D_PATTERN_COLOR(0), 4);
180 OUT_RING (chan, col0);
181 OUT_RING (chan, col1);
182 OUT_RING (chan, pat0);
183 OUT_RING (chan, pat1);
186 #if !defined(__AROS__)
187 static void
188 NV50EXASetROP(PixmapPtr pdpix, int alu, Pixel planemask)
190 NV50EXA_LOCALS(pdpix);
191 int rop;
193 if (planemask != ~0)
194 rop = NVROP[alu].copy_planemask;
195 else
196 rop = NVROP[alu].copy;
198 BEGIN_RING(chan, eng2d, NV50_2D_OPERATION, 1);
199 if (alu == GXcopy && EXA_PM_IS_SOLID(&pdpix->drawable, planemask)) {
200 OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY);
201 return;
202 } else {
203 OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY_PREMULT);
206 BEGIN_RING(chan, eng2d, NV50_2D_PATTERN_FORMAT, 2);
207 switch (pdpix->drawable.bitsPerPixel) {
208 case 8: OUT_RING (chan, 3); break;
209 case 15: OUT_RING (chan, 1); break;
210 case 16: OUT_RING (chan, 0); break;
211 case 24:
212 case 32:
213 default:
214 OUT_RING (chan, 2);
215 break;
217 OUT_RING (chan, 1);
219 /* There are 16 alu's.
220 * 0-15: copy
221 * 16-31: copy_planemask
224 if (!EXA_PM_IS_SOLID(&pdpix->drawable, planemask)) {
225 alu += 16;
226 NV50EXASetPattern(pdpix, 0, planemask, ~0, ~0);
227 } else {
228 if (pNv->currentRop > 15)
229 NV50EXASetPattern(pdpix, ~0, ~0, ~0, ~0);
232 if (pNv->currentRop != alu) {
233 BEGIN_RING(chan, eng2d, NV50_2D_ROP, 1);
234 OUT_RING (chan, rop);
235 pNv->currentRop = alu;
238 #else
239 static void
240 NV50EXASetROP(PixmapPtr pdpix, int alu, Pixel planemask)
242 NV50EXA_LOCALS(pdpix);
243 int rop;
245 rop = NVROP[alu].copy;
247 BEGIN_RING(chan, eng2d, NV50_2D_OPERATION, 1);
248 if (alu == 0x03 /* DrawMode_Copy */) {
249 OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY);
250 return;
251 } else {
252 OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY_PREMULT);
255 BEGIN_RING(chan, eng2d, NV50_2D_PATTERN_FORMAT, 2);
256 switch (pdpix->depth) {
257 case 8: OUT_RING (chan, 3); break;
258 case 15: OUT_RING (chan, 1); break;
259 case 16: OUT_RING (chan, 0); break;
260 case 24:
261 case 32:
262 default:
263 OUT_RING (chan, 2);
264 break;
266 OUT_RING (chan, 1);
269 BEGIN_RING(chan, eng2d, NV50_2D_ROP, 1);
270 OUT_RING (chan, rop);
272 #endif
274 #if !defined(__AROS__)
275 static void
276 NV50EXAStateSolidResubmit(struct nouveau_channel *chan)
278 ScrnInfoPtr pScrn = chan->user_private;
279 NVPtr pNv = NVPTR(pScrn);
281 NV50EXAPrepareSolid(pNv->pdpix, pNv->alu, pNv->planemask,
282 pNv->fg_colour);
284 #endif
286 Bool
287 NV50EXAPrepareSolid(PixmapPtr pdpix, int alu, Pixel planemask, Pixel fg)
289 NV50EXA_LOCALS(pdpix);
290 uint32_t fmt;
292 if (!NV50EXA2DSurfaceFormat(pdpix, &fmt))
293 NOUVEAU_FALLBACK("rect format\n");
295 if (MARK_RING(chan, 64, 4))
296 NOUVEAU_FALLBACK("ring space\n");
298 if (!NV50EXAAcquireSurface2D(pdpix, 0)) {
299 MARK_UNDO(chan);
300 NOUVEAU_FALLBACK("dest pixmap\n");
303 NV50EXASetROP(pdpix, alu, planemask);
305 BEGIN_RING(chan, eng2d, NV50_2D_DRAW_SHAPE, 3);
306 OUT_RING (chan, NV50_2D_DRAW_SHAPE_RECTANGLES);
307 OUT_RING (chan, fmt);
308 OUT_RING (chan, fg);
310 #if !defined(__AROS__)
311 pNv->pdpix = pdpix;
312 pNv->alu = alu;
313 pNv->planemask = planemask;
314 pNv->fg_colour = fg;
315 chan->flush_notify = NV50EXAStateSolidResubmit;
316 #else
317 chan->flush_notify = NULL;
318 #endif
319 return TRUE;
322 void
323 NV50EXASolid(PixmapPtr pdpix, int x1, int y1, int x2, int y2)
325 NV50EXA_LOCALS(pdpix);
327 WAIT_RING (chan, 5);
328 BEGIN_RING(chan, eng2d, NV50_2D_DRAW_POINT32_X(0), 4);
329 OUT_RING (chan, x1);
330 OUT_RING (chan, y1);
331 OUT_RING (chan, x2);
332 OUT_RING (chan, y2);
334 #if !defined(__AROS__)
335 if((x2 - x1) * (y2 - y1) >= 512)
336 #endif
337 FIRE_RING (chan);
340 #if !defined(__AROS__)
341 void
342 NV50EXADoneSolid(PixmapPtr pdpix)
344 NV50EXA_LOCALS(pdpix);
346 chan->flush_notify = NULL;
349 static void
350 NV50EXAStateCopyResubmit(struct nouveau_channel *chan)
352 ScrnInfoPtr pScrn = chan->user_private;
353 NVPtr pNv = NVPTR(pScrn);
355 NV50EXAPrepareCopy(pNv->pspix, pNv->pdpix, 0, 0, pNv->alu,
356 pNv->planemask);
358 #endif
360 Bool
361 NV50EXAPrepareCopy(PixmapPtr pspix, PixmapPtr pdpix, int dx, int dy,
362 int alu, Pixel planemask)
364 NV50EXA_LOCALS(pdpix);
366 if (MARK_RING(chan, 64, 4))
367 NOUVEAU_FALLBACK("ring space\n");
369 if (!NV50EXAAcquireSurface2D(pspix, 1)) {
370 MARK_UNDO(chan);
371 NOUVEAU_FALLBACK("src pixmap\n");
374 if (!NV50EXAAcquireSurface2D(pdpix, 0)) {
375 MARK_UNDO(chan);
376 NOUVEAU_FALLBACK("dest pixmap\n");
379 NV50EXASetROP(pdpix, alu, planemask);
381 #if !defined(__AROS__)
382 pNv->pspix = pspix;
383 pNv->pdpix = pdpix;
384 pNv->alu = alu;
385 pNv->planemask = planemask;
386 chan->flush_notify = NV50EXAStateCopyResubmit;
387 #else
388 chan->flush_notify = NULL;
389 #endif
390 return TRUE;
393 void
394 NV50EXACopy(PixmapPtr pdpix, int srcX , int srcY,
395 int dstX , int dstY,
396 int width, int height)
398 NV50EXA_LOCALS(pdpix);
400 WAIT_RING (chan, 17);
401 BEGIN_RING(chan, eng2d, 0x0110, 1);
402 OUT_RING (chan, 0);
403 BEGIN_RING(chan, eng2d, 0x088c, 1);
404 OUT_RING (chan, 0);
405 BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 12);
406 OUT_RING (chan, dstX);
407 OUT_RING (chan, dstY);
408 OUT_RING (chan, width);
409 OUT_RING (chan, height);
410 OUT_RING (chan, 0);
411 OUT_RING (chan, 1);
412 OUT_RING (chan, 0);
413 OUT_RING (chan, 1);
414 OUT_RING (chan, 0);
415 OUT_RING (chan, srcX);
416 OUT_RING (chan, 0);
417 OUT_RING (chan, srcY);
419 #if !defined(__AROS__)
420 if(width * height >= 512)
421 #endif
422 FIRE_RING (chan);
425 #if !defined(__AROS__)
426 void
427 NV50EXADoneCopy(PixmapPtr pdpix)
429 NV50EXA_LOCALS(pdpix);
431 chan->flush_notify = NULL;
434 static void
435 NV50EXAStateSIFCResubmit(struct nouveau_channel *chan)
437 ScrnInfoPtr pScrn = chan->user_private;
438 NVPtr pNv = NVPTR(pScrn);
440 if (MARK_RING(pNv->chan, 32, 2))
441 return;
443 if (!NV50EXAAcquireSurface2D(pNv->pdpix, 0))
444 MARK_UNDO(pNv->chan);
447 Bool
448 NV50EXAUploadSIFC(const char *src, int src_pitch,
449 PixmapPtr pdpix, int x, int y, int w, int h, int cpp)
451 NV50EXA_LOCALS(pdpix);
452 ScreenPtr pScreen = pdpix->drawable.pScreen;
453 int line_dwords = (w * cpp + 3) / 4;
454 uint32_t sifc_fmt;
456 if (!NV50EXA2DSurfaceFormat(pdpix, &sifc_fmt))
457 NOUVEAU_FALLBACK("hostdata format\n");
459 if (MARK_RING(chan, 64, 2))
460 return FALSE;
462 if (!NV50EXAAcquireSurface2D(pdpix, 0)) {
463 MARK_UNDO(chan);
464 NOUVEAU_FALLBACK("dest pixmap\n");
467 /* If the pitch isn't aligned to a dword, then you can get corruption at the end of a line. */
468 NV50EXASetClip(pdpix, x, y, w, h);
470 BEGIN_RING(chan, eng2d, NV50_2D_OPERATION, 1);
471 OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY);
472 BEGIN_RING(chan, eng2d, NV50_2D_SIFC_BITMAP_ENABLE, 2);
473 OUT_RING (chan, 0);
474 OUT_RING (chan, sifc_fmt);
475 BEGIN_RING(chan, eng2d, NV50_2D_SIFC_WIDTH, 10);
476 OUT_RING (chan, (line_dwords * 4) / cpp);
477 OUT_RING (chan, h);
478 OUT_RING (chan, 0);
479 OUT_RING (chan, 1);
480 OUT_RING (chan, 0);
481 OUT_RING (chan, 1);
482 OUT_RING (chan, 0);
483 OUT_RING (chan, x);
484 OUT_RING (chan, 0);
485 OUT_RING (chan, y);
487 pNv->pdpix = pdpix;
488 chan->flush_notify = NV50EXAStateSIFCResubmit;
490 while (h--) {
491 int count = line_dwords;
492 const char *p = src;
494 while(count) {
495 int size = count > 1792 ? 1792 : count;
497 WAIT_RING (chan, size + 1);
498 BEGIN_RING_NI(chan, eng2d, NV50_2D_SIFC_DATA, size);
499 OUT_RINGp (chan, p, size);
501 p += size * 4;
502 count -= size;
505 src += src_pitch;
508 chan->flush_notify = NULL;
510 if (pdpix == pScreen->GetScreenPixmap(pScreen))
511 FIRE_RING(chan);
512 return TRUE;
515 static Bool
516 NV50EXACheckRenderTarget(PicturePtr ppict)
518 if (ppict->pDrawable->width > 8192 ||
519 ppict->pDrawable->height > 8192)
520 NOUVEAU_FALLBACK("render target dimensions exceeded %dx%d\n",
521 ppict->pDrawable->width,
522 ppict->pDrawable->height);
524 switch (ppict->format) {
525 case PICT_a8r8g8b8:
526 case PICT_x8r8g8b8:
527 case PICT_r5g6b5:
528 case PICT_a8:
529 case PICT_x1r5g5b5:
530 case PICT_a1r5g5b5:
531 case PICT_x8b8g8r8:
532 case PICT_a2b10g10r10:
533 case PICT_x2b10g10r10:
534 case PICT_a2r10g10b10:
535 case PICT_x2r10g10b10:
536 break;
537 default:
538 NOUVEAU_FALLBACK("picture format 0x%08x\n", ppict->format);
541 return TRUE;
543 #endif
545 static Bool
546 NV50EXARenderTarget(PixmapPtr ppix, PicturePtr ppict)
548 NV50EXA_LOCALS(ppix);
549 struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
550 unsigned format;
552 /*XXX: Scanout buffer not tiled, someone needs to figure it out */
553 if (!nv50_style_tiled_pixmap(ppix))
554 NOUVEAU_FALLBACK("pixmap is scanout buffer\n");
556 switch (ppict->format) {
557 case PICT_a8r8g8b8: format = NV50TCL_RT_FORMAT_A8R8G8B8_UNORM; break;
558 case PICT_x8r8g8b8: format = NV50TCL_RT_FORMAT_X8R8G8B8_UNORM; break;
559 case PICT_r5g6b5 : format = NV50TCL_RT_FORMAT_R5G6B5_UNORM; break;
560 case PICT_a8 : format = NV50TCL_RT_FORMAT_A8_UNORM; break;
561 case PICT_x1r5g5b5:
562 case PICT_a1r5g5b5:
563 format = NV50TCL_RT_FORMAT_A1R5G5B5_UNORM;
564 break;
565 case PICT_x8b8g8r8: format = NV50TCL_RT_FORMAT_X8B8G8R8_UNORM; break;
566 case PICT_a2b10g10r10:
567 case PICT_x2b10g10r10:
568 format = NV50TCL_RT_FORMAT_A2B10G10R10_UNORM;
569 break;
570 case PICT_a2r10g10b10:
571 case PICT_x2r10g10b10:
572 format = NV50TCL_RT_FORMAT_A2R10G10B10_UNORM;
573 break;
574 default:
575 NOUVEAU_FALLBACK("invalid picture format\n");
578 BEGIN_RING(chan, tesla, NV50TCL_RT_ADDRESS_HIGH(0), 5);
579 if (OUT_RELOCh(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) ||
580 OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR))
581 return FALSE;
582 OUT_RING (chan, format);
583 OUT_RING (chan, bo->tile_mode << 4);
584 OUT_RING (chan, 0x00000000);
585 BEGIN_RING(chan, tesla, NV50TCL_RT_HORIZ(0), 2);
586 #if !defined(__AROS__)
587 OUT_RING (chan, ppix->drawable.width);
588 OUT_RING (chan, ppix->drawable.height);
589 #else
590 OUT_RING (chan, ppix->width);
591 OUT_RING (chan, ppix->height);
592 #endif
593 BEGIN_RING(chan, tesla, NV50TCL_RT_ARRAY_MODE, 1);
594 OUT_RING (chan, 0x00000001);
596 return TRUE;
599 #if !defined(__AROS__)
600 static Bool
601 NV50EXACheckTexture(PicturePtr ppict, PicturePtr pdpict, int op)
603 if (!ppict->pDrawable)
604 NOUVEAU_FALLBACK("Solid and gradient pictures unsupported\n");
606 if (ppict->pDrawable->width > 8192 ||
607 ppict->pDrawable->height > 8192)
608 NOUVEAU_FALLBACK("texture dimensions exceeded %dx%d\n",
609 ppict->pDrawable->width,
610 ppict->pDrawable->height);
612 switch (ppict->format) {
613 case PICT_a8r8g8b8:
614 case PICT_a8b8g8r8:
615 case PICT_x8r8g8b8:
616 case PICT_x8b8g8r8:
617 case PICT_r5g6b5:
618 case PICT_a8:
619 case PICT_x1r5g5b5:
620 case PICT_x1b5g5r5:
621 case PICT_a1r5g5b5:
622 case PICT_a1b5g5r5:
623 case PICT_b5g6r5:
624 case PICT_b8g8r8a8:
625 case PICT_b8g8r8x8:
626 case PICT_a2b10g10r10:
627 case PICT_x2b10g10r10:
628 case PICT_x2r10g10b10:
629 case PICT_a2r10g10b10:
630 case PICT_x4r4g4b4:
631 case PICT_x4b4g4r4:
632 case PICT_a4r4g4b4:
633 case PICT_a4b4g4r4:
634 break;
635 default:
636 NOUVEAU_FALLBACK("picture format 0x%08x\n", ppict->format);
639 switch (ppict->filter) {
640 case PictFilterNearest:
641 case PictFilterBilinear:
642 break;
643 default:
644 NOUVEAU_FALLBACK("picture filter %d\n", ppict->filter);
647 /* Opengl and Render disagree on what should be sampled outside an XRGB
648 * texture (with no repeating). Opengl has a hardcoded alpha value of
649 * 1.0, while render expects 0.0. We assume that clipping is done for
650 * untranformed sources.
652 if (NV50EXABlendOp[op].src_alpha && !ppict->repeat &&
653 ppict->transform && (PICT_FORMAT_A(ppict->format) == 0)
654 && (PICT_FORMAT_A(pdpict->format) != 0))
655 NOUVEAU_FALLBACK("REPEAT_NONE unsupported for XRGB source\n");
657 return TRUE;
659 #endif
661 #define _(X1,X2,X3,X4,FMT) (NV50TIC_0_0_TYPER_UNORM | NV50TIC_0_0_TYPEG_UNORM | NV50TIC_0_0_TYPEB_UNORM | NV50TIC_0_0_TYPEA_UNORM | \
662 NV50TIC_0_0_MAP##X1 | NV50TIC_0_0_MAP##X2 | NV50TIC_0_0_MAP##X3 | NV50TIC_0_0_MAP##X4 | \
663 NV50TIC_0_0_FMT_##FMT)
665 #if !defined(__AROS__)
666 static Bool
667 NV50EXATexture(PixmapPtr ppix, PicturePtr ppict, unsigned unit)
668 #else
669 static Bool
670 NV50EXATexture(PixmapPtr ppix, PicturePtr ppict, unsigned unit, struct nv50_exa_state * state)
671 #endif
673 NV50EXA_LOCALS(ppix);
674 struct nouveau_bo *bo = nouveau_pixmap_bo(ppix);
675 const unsigned tcb_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
676 uint32_t mode;
678 /*XXX: Scanout buffer not tiled, someone needs to figure it out */
679 if (!nv50_style_tiled_pixmap(ppix))
680 NOUVEAU_FALLBACK("pixmap is scanout buffer\n");
682 BEGIN_RING(chan, tesla, NV50TCL_TIC_ADDRESS_HIGH, 3);
683 if (OUT_RELOCh(chan, pNv->tesla_scratch, TIC_OFFSET, tcb_flags) ||
684 OUT_RELOCl(chan, pNv->tesla_scratch, TIC_OFFSET, tcb_flags))
685 return FALSE;
686 OUT_RING (chan, 0x00000800);
687 BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
688 if (OUT_RELOCh(chan, pNv->tesla_scratch, TIC_OFFSET, tcb_flags) ||
689 OUT_RELOCl(chan, pNv->tesla_scratch, TIC_OFFSET, tcb_flags))
690 return FALSE;
691 OUT_RING (chan, (CB_TIC << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
692 BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
693 OUT_RING (chan, CB_TIC | ((unit * 8) << NV50TCL_CB_ADDR_ID_SHIFT));
694 BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), 8);
696 switch (ppict->format) {
697 case PICT_a8r8g8b8:
698 OUT_RING(chan, _(B_C0, G_C1, R_C2, A_C3, 8_8_8_8));
699 break;
700 case PICT_a8b8g8r8:
701 OUT_RING(chan, _(R_C0, G_C1, B_C2, A_C3, 8_8_8_8));
702 break;
703 case PICT_x8r8g8b8:
704 OUT_RING(chan, _(B_C0, G_C1, R_C2, A_ONE, 8_8_8_8));
705 break;
706 case PICT_x8b8g8r8:
707 OUT_RING(chan, _(R_C0, G_C1, B_C2, A_ONE, 8_8_8_8));
708 break;
709 case PICT_r5g6b5:
710 OUT_RING(chan, _(B_C0, G_C1, R_C2, A_ONE, 5_6_5));
711 break;
712 case PICT_a8:
713 OUT_RING(chan, _(A_C0, B_ZERO, G_ZERO, R_ZERO, 8));
714 break;
715 case PICT_x1r5g5b5:
716 OUT_RING(chan, _(B_C0, G_C1, R_C2, A_ONE, 1_5_5_5));
717 break;
718 case PICT_x1b5g5r5:
719 OUT_RING(chan, _(R_C0, G_C1, B_C2, A_ONE, 1_5_5_5));
720 break;
721 case PICT_a1r5g5b5:
722 OUT_RING(chan, _(B_C0, G_C1, R_C2, A_C3, 1_5_5_5));
723 break;
724 case PICT_a1b5g5r5:
725 OUT_RING(chan, _(R_C0, G_C1, B_C2, A_C3, 1_5_5_5));
726 break;
727 case PICT_b5g6r5:
728 OUT_RING(chan, _(R_C0, G_C1, B_C2, A_ONE, 5_6_5));
729 break;
730 case PICT_b8g8r8x8:
731 OUT_RING(chan, _(A_ONE, R_C1, G_C2, B_C3, 8_8_8_8));
732 break;
733 case PICT_b8g8r8a8:
734 OUT_RING(chan, _(A_C0, R_C1, G_C2, B_C3, 8_8_8_8));
735 break;
736 case PICT_a2b10g10r10:
737 OUT_RING(chan, _(R_C0, G_C1, B_C2, A_C3, 2_10_10_10));
738 break;
739 case PICT_x2b10g10r10:
740 OUT_RING(chan, _(R_C0, G_C1, B_C2, A_ONE, 2_10_10_10));
741 break;
742 case PICT_x2r10g10b10:
743 OUT_RING(chan, _(B_C0, G_C1, R_C2, A_ONE, 2_10_10_10));
744 break;
745 case PICT_a2r10g10b10:
746 OUT_RING(chan, _(B_C0, G_C1, R_C2, A_C3, 2_10_10_10));
747 break;
748 case PICT_x4r4g4b4:
749 OUT_RING(chan, _(B_C0, G_C1, R_C2, A_ONE, 4_4_4_4));
750 break;
751 case PICT_x4b4g4r4:
752 OUT_RING(chan, _(R_C0, G_C1, B_C2, A_ONE, 4_4_4_4));
753 break;
754 case PICT_a4r4g4b4:
755 OUT_RING(chan, _(B_C0, G_C1, R_C2, A_C3, 4_4_4_4));
756 break;
757 case PICT_a4b4g4r4:
758 OUT_RING(chan, _(R_C0, G_C1, B_C2, A_C3, 4_4_4_4));
759 break;
760 default:
761 NOUVEAU_FALLBACK("invalid picture format, this SHOULD NOT HAPPEN. Expect trouble.\n");
763 #undef _
765 mode = 0xd0005000 | (bo->tile_mode << 22);
766 if (OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) ||
767 OUT_RELOCd(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
768 NOUVEAU_BO_HIGH | NOUVEAU_BO_OR, mode, mode))
769 return FALSE;
770 OUT_RING (chan, 0x00300000);
771 #if !defined(__AROS__)
772 OUT_RING (chan, ppix->drawable.width);
773 OUT_RING (chan, (1 << NV50TIC_0_5_DEPTH_SHIFT) | ppix->drawable.height);
774 #else
775 OUT_RING (chan, ppix->width);
776 OUT_RING (chan, (1 << NV50TIC_0_5_DEPTH_SHIFT) | ppix->height);
777 #endif
778 OUT_RING (chan, 0x03000000);
779 OUT_RING (chan, 0x00000000);
781 BEGIN_RING(chan, tesla, NV50TCL_TSC_ADDRESS_HIGH, 3);
782 if (OUT_RELOCh(chan, pNv->tesla_scratch, TSC_OFFSET, tcb_flags) ||
783 OUT_RELOCl(chan, pNv->tesla_scratch, TSC_OFFSET, tcb_flags))
784 return FALSE;
785 OUT_RING (chan, 0x00000000);
786 BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
787 if (OUT_RELOCh(chan, pNv->tesla_scratch, TSC_OFFSET, tcb_flags) ||
788 OUT_RELOCl(chan, pNv->tesla_scratch, TSC_OFFSET, tcb_flags))
789 return FALSE;
790 OUT_RING (chan, (CB_TSC << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
791 BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
792 OUT_RING (chan, CB_TSC | ((unit * 8) << NV50TCL_CB_ADDR_ID_SHIFT));
793 BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), 8);
794 if (ppict->repeat) {
795 switch (ppict->repeatType) {
796 case RepeatPad:
797 OUT_RING (chan, NV50TSC_1_0_WRAPS_CLAMP |
798 NV50TSC_1_0_WRAPT_CLAMP |
799 NV50TSC_1_0_WRAPR_CLAMP | 0x00024000);
800 break;
801 case RepeatReflect:
802 OUT_RING (chan, NV50TSC_1_0_WRAPS_MIRROR_REPEAT |
803 NV50TSC_1_0_WRAPT_MIRROR_REPEAT |
804 NV50TSC_1_0_WRAPR_MIRROR_REPEAT | 0x00024000);
805 break;
806 case RepeatNormal:
807 default:
808 OUT_RING (chan, NV50TSC_1_0_WRAPS_REPEAT |
809 NV50TSC_1_0_WRAPT_REPEAT |
810 NV50TSC_1_0_WRAPR_REPEAT | 0x00024000);
811 break;
813 } else {
814 OUT_RING (chan, NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER |
815 NV50TSC_1_0_WRAPT_CLAMP_TO_BORDER |
816 NV50TSC_1_0_WRAPR_CLAMP_TO_BORDER | 0x00024000);
818 if (ppict->filter == PictFilterBilinear) {
819 OUT_RING (chan, NV50TSC_1_1_MAGF_LINEAR |
820 NV50TSC_1_1_MINF_LINEAR |
821 NV50TSC_1_1_MIPF_NONE);
822 } else {
823 OUT_RING (chan, NV50TSC_1_1_MAGF_NEAREST |
824 NV50TSC_1_1_MINF_NEAREST |
825 NV50TSC_1_1_MIPF_NONE);
827 OUT_RING (chan, 0x00000000);
828 OUT_RING (chan, 0x00000000);
829 OUT_RING (chan, 0x00000000);
830 OUT_RING (chan, 0x00000000);
831 OUT_RING (chan, 0x00000000);
832 OUT_RING (chan, 0x00000000);
834 #if !defined(__AROS__)
835 state->unit[unit].width = ppix->drawable.width;
836 state->unit[unit].height = ppix->drawable.height;
837 state->unit[unit].transform = ppict->transform;
838 #else
839 state->unit[unit].width = ppix->width;
840 state->unit[unit].height = ppix->height;
841 state->unit[unit].transform = NULL; /* Keep this NULL, we are doing simple blits */
842 #endif
843 return TRUE;
846 #if !defined(__AROS__)
847 static Bool
848 NV50EXACheckBlend(int op)
850 if (op > PictOpAdd)
851 NOUVEAU_FALLBACK("unsupported blend op %d\n", op);
852 return TRUE;
854 #endif
856 static void
857 NV50EXABlend(PixmapPtr ppix, PicturePtr ppict, int op, int component_alpha)
859 NV50EXA_LOCALS(ppix);
860 struct nv50_blend_op *b = &NV50EXABlendOp[op];
861 unsigned sblend = b->src_blend;
862 unsigned dblend = b->dst_blend;
864 if (b->dst_alpha) {
865 if (!PICT_FORMAT_A(ppict->format)) {
866 if (sblend == BF(DST_ALPHA))
867 sblend = BF(ONE);
868 else
869 if (sblend == BF(ONE_MINUS_DST_ALPHA))
870 sblend = BF(ZERO);
874 if (b->src_alpha && component_alpha) {
875 if (dblend == BF(SRC_ALPHA))
876 dblend = BF(SRC_COLOR);
877 else
878 if (dblend == BF(ONE_MINUS_SRC_ALPHA))
879 dblend = BF(ONE_MINUS_SRC_COLOR);
882 if (sblend == BF(ONE) && dblend == BF(ZERO)) {
883 BEGIN_RING(chan, tesla, NV50TCL_BLEND_ENABLE(0), 1);
884 OUT_RING (chan, 0);
885 } else {
886 BEGIN_RING(chan, tesla, NV50TCL_BLEND_ENABLE(0), 1);
887 OUT_RING (chan, 1);
888 BEGIN_RING(chan, tesla, NV50TCL_BLEND_EQUATION_RGB, 5);
889 OUT_RING (chan, NV50TCL_BLEND_EQUATION_RGB_FUNC_ADD);
890 OUT_RING (chan, sblend);
891 OUT_RING (chan, dblend);
892 OUT_RING (chan, NV50TCL_BLEND_EQUATION_ALPHA_FUNC_ADD);
893 OUT_RING (chan, sblend);
894 BEGIN_RING(chan, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1);
895 OUT_RING (chan, dblend);
899 #if !defined(__AROS__)
900 Bool
901 NV50EXACheckComposite(int op,
902 PicturePtr pspict, PicturePtr pmpict, PicturePtr pdpict)
904 if (!NV50EXACheckBlend(op))
905 NOUVEAU_FALLBACK("blend not supported\n");
907 if (!NV50EXACheckRenderTarget(pdpict))
908 NOUVEAU_FALLBACK("render target invalid\n");
910 if (!NV50EXACheckTexture(pspict, pdpict, op))
911 NOUVEAU_FALLBACK("src picture invalid\n");
913 if (pmpict) {
914 if (pmpict->componentAlpha &&
915 PICT_FORMAT_RGB(pmpict->format) &&
916 NV50EXABlendOp[op].src_alpha &&
917 NV50EXABlendOp[op].src_blend != BF(ZERO))
918 NOUVEAU_FALLBACK("component-alpha not supported\n");
920 if (!NV50EXACheckTexture(pmpict, pdpict, op))
921 NOUVEAU_FALLBACK("mask picture invalid\n");
924 return TRUE;
927 static void
928 NV50EXAStateCompositeResubmit(struct nouveau_channel *chan)
930 ScrnInfoPtr pScrn = chan->user_private;
931 NVPtr pNv = NVPTR(pScrn);
933 NV50EXAPrepareComposite(pNv->alu, pNv->pspict, pNv->pmpict, pNv->pdpict,
934 pNv->pspix, pNv->pmpix, pNv->pdpix);
936 #endif
938 #if !defined(__AROS__)
939 Bool
940 NV50EXAPrepareComposite(int op,
941 PicturePtr pspict, PicturePtr pmpict, PicturePtr pdpict,
942 PixmapPtr pspix, PixmapPtr pmpix, PixmapPtr pdpix)
943 #else
944 static Bool
945 NV50EXAPrepareComposite(int op,
946 PicturePtr pspict, PicturePtr pmpict, PicturePtr pdpict,
947 PixmapPtr pspix, PixmapPtr pmpix, PixmapPtr pdpix,
948 struct nv50_exa_state * state)
949 #endif
951 NV50EXA_LOCALS(pspix);
952 const unsigned shd_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD;
954 if (MARK_RING (chan, 128, 4 + 2 + 2 * 10))
955 NOUVEAU_FALLBACK("ring space\n");
957 BEGIN_RING(chan, eng2d, 0x0110, 1);
958 OUT_RING (chan, 0);
960 if (!NV50EXARenderTarget(pdpix, pdpict)) {
961 MARK_UNDO(chan);
962 NOUVEAU_FALLBACK("render target invalid\n");
965 NV50EXABlend(pdpix, pdpict, op, pmpict && pmpict->componentAlpha &&
966 PICT_FORMAT_RGB(pmpict->format));
968 BEGIN_RING(chan, tesla, NV50TCL_VP_ADDRESS_HIGH, 2);
969 if (OUT_RELOCh(chan, pNv->tesla_scratch, PVP_OFFSET, shd_flags) ||
970 OUT_RELOCl(chan, pNv->tesla_scratch, PVP_OFFSET, shd_flags)) {
971 MARK_UNDO(chan);
972 return FALSE;
975 BEGIN_RING(chan, tesla, NV50TCL_FP_ADDRESS_HIGH, 2);
976 if (OUT_RELOCh(chan, pNv->tesla_scratch, PFP_OFFSET, shd_flags) ||
977 OUT_RELOCl(chan, pNv->tesla_scratch, PFP_OFFSET, shd_flags)) {
978 MARK_UNDO(chan);
979 return FALSE;
982 #if !defined(__AROS__)
983 if (!NV50EXATexture(pspix, pspict, 0)) {
984 #else
985 if (!NV50EXATexture(pspix, pspict, 0, state)) {
986 #endif
987 MARK_UNDO(chan);
988 NOUVEAU_FALLBACK("src picture invalid\n");
991 if (pmpict) {
992 #if !defined(__AROS__)
993 if (!NV50EXATexture(pmpix, pmpict, 1)) {
994 #else
995 if (!NV50EXATexture(pmpix, pmpict, 1, state)) {
996 #endif
997 MARK_UNDO(chan);
998 NOUVEAU_FALLBACK("mask picture invalid\n");
1000 state->have_mask = TRUE;
1002 BEGIN_RING(chan, tesla, NV50TCL_FP_START_ID, 1);
1003 if (pdpict->format == PICT_a8) {
1004 OUT_RING (chan, PFP_C_A8);
1005 } else {
1006 if (pmpict->componentAlpha &&
1007 PICT_FORMAT_RGB(pmpict->format)) {
1008 if (NV50EXABlendOp[op].src_alpha)
1009 OUT_RING (chan, PFP_CCASA);
1010 else
1011 OUT_RING (chan, PFP_CCA);
1012 } else {
1013 OUT_RING (chan, PFP_C);
1016 } else {
1017 state->have_mask = FALSE;
1019 BEGIN_RING(chan, tesla, NV50TCL_FP_START_ID, 1);
1020 if (pdpict->format == PICT_a8)
1021 OUT_RING (chan, PFP_S_A8);
1022 else
1023 OUT_RING (chan, PFP_S);
1026 BEGIN_RING(chan, tesla, 0x1334, 1);
1027 OUT_RING (chan, 0);
1029 BEGIN_RING(chan, tesla, NV50TCL_BIND_TIC(2), 1);
1030 OUT_RING (chan, 1);
1031 BEGIN_RING(chan, tesla, NV50TCL_BIND_TIC(2), 1);
1032 OUT_RING (chan, 0x203);
1034 #if !defined(__AROS__)
1035 pNv->alu = op;
1036 pNv->pspict = pspict;
1037 pNv->pmpict = pmpict;
1038 pNv->pdpict = pdpict;
1039 pNv->pspix = pspix;
1040 pNv->pmpix = pmpix;
1041 pNv->pdpix = pdpix;
1042 chan->flush_notify = NV50EXAStateCompositeResubmit;
1043 #else
1044 chan->flush_notify = NULL;
1045 #endif
1046 return TRUE;
1049 #define xFixedToFloat(v) \
1050 ((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0))
1051 static inline void
1052 NV50EXATransform(PictTransformPtr t, int x, int y, float sx, float sy,
1053 float *x_ret, float *y_ret)
1055 if (t) {
1056 /* Note: current t is always NULL in AROS. That is good enough for
1057 operations being done (simple blits with alpha) */
1058 #if !defined(__AROS__)
1059 PictVector v;
1061 v.vector[0] = IntToxFixed(x);
1062 v.vector[1] = IntToxFixed(y);
1063 v.vector[2] = xFixed1;
1064 PictureTransformPoint(t, &v);
1065 *x_ret = xFixedToFloat(v.vector[0]) / sx;
1066 *y_ret = xFixedToFloat(v.vector[1]) / sy;
1067 #endif
1068 } else {
1069 *x_ret = (float)x / sx;
1070 *y_ret = (float)y / sy;
1074 #if !defined(__AROS__)
1075 void
1076 NV50EXAComposite(PixmapPtr pdpix, int sx, int sy, int mx, int my,
1077 int dx, int dy, int w, int h)
1078 #else
1079 static void
1080 NV50EXAComposite(PixmapPtr pdpix, int sx, int sy, int mx, int my,
1081 int dx, int dy, int w, int h, struct nv50_exa_state * state)
1082 #endif
1084 NV50EXA_LOCALS(pdpix);
1085 float sX0=0.0f, sX1=0.0f, sX2=0.0f, sY0=0.0f, sY1=0.0f, sY2=0.0f;
1087 WAIT_RING (chan, 64);
1088 BEGIN_RING(chan, tesla, NV50TCL_SCISSOR_HORIZ(0), 2);
1089 OUT_RING (chan, (dx + w) << 16 | dx);
1090 OUT_RING (chan, (dy + h) << 16 | dy);
1091 BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
1092 OUT_RING (chan, NV50TCL_VERTEX_BEGIN_TRIANGLES);
1094 NV50EXATransform(state->unit[0].transform, sx, sy + (h * 2),
1095 state->unit[0].width, state->unit[0].height,
1096 &sX0, &sY0);
1097 NV50EXATransform(state->unit[0].transform, sx, sy,
1098 state->unit[0].width, state->unit[0].height,
1099 &sX1, &sY1);
1100 NV50EXATransform(state->unit[0].transform, sx + (w * 2), sy,
1101 state->unit[0].width, state->unit[0].height,
1102 &sX2, &sY2);
1104 if (state->have_mask) {
1105 float mX0=0.0f, mX1=0.0f, mX2=0.0f, mY0=0.0f, mY1=0.0f, mY2=0.0f;
1107 NV50EXATransform(state->unit[1].transform, mx, my + (h * 2),
1108 state->unit[1].width, state->unit[1].height,
1109 &mX0, &mY0);
1110 NV50EXATransform(state->unit[1].transform, mx, my,
1111 state->unit[1].width, state->unit[1].height,
1112 &mX1, &mY1);
1113 NV50EXATransform(state->unit[1].transform, mx + (w * 2), my,
1114 state->unit[1].width, state->unit[1].height,
1115 &mX2, &mY2);
1117 VTX2s(pNv, sX0, sY0, mX0, mY0, dx, dy + (h * 2));
1118 VTX2s(pNv, sX1, sY1, mX1, mY1, dx, dy);
1119 VTX2s(pNv, sX2, sY2, mX2, mY2, dx + (w * 2), dy);
1120 } else {
1121 VTX1s(pNv, sX0, sY0, dx, dy + (h * 2));
1122 VTX1s(pNv, sX1, sY1, dx, dy);
1123 VTX1s(pNv, sX2, sY2, dx + (w * 2), dy);
1126 BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
1127 OUT_RING (chan, 0);
1130 #if !defined(__AROS__)
1131 void
1132 NV50EXADoneComposite(PixmapPtr pdpix)
1134 NV50EXA_LOCALS(pdpix);
1136 chan->flush_notify = NULL;
1138 #endif
1140 /* AROS CODE */
1142 VOID HIDDNouveauNV50SetPattern(struct CardData * carddata, LONG col0,
1143 LONG col1, LONG pat0, LONG pat1)
1145 NV50EXASetPattern(NULL, col0, col1, pat0, pat1);
1148 /* NOTE: Assumes lock on bitmap is already made */
1149 /* NOTE: Assumes buffer is not mapped */
1150 BOOL HIDDNouveauNV50FillSolidRect(struct CardData * carddata,
1151 struct HIDDNouveauBitMapData * bmdata, LONG minX, LONG minY, LONG maxX,
1152 LONG maxY, ULONG drawmode, ULONG color)
1154 if (NV50EXAPrepareSolid(bmdata, drawmode, ~0, color))
1156 NV50EXASolid(bmdata, minX, minY, maxX + 1, maxY + 1);
1157 return TRUE;
1160 return FALSE;
1163 /* NOTE: Assumes lock on bitmap is already made */
1164 /* NOTE: Assumes buffer is not mapped */
1165 BOOL HIDDNouveauNV50CopySameFormat(struct CardData * carddata,
1166 struct HIDDNouveauBitMapData * srcdata, struct HIDDNouveauBitMapData * destdata,
1167 LONG srcX, LONG srcY, LONG destX, LONG destY, LONG width, LONG height,
1168 ULONG drawmode)
1170 if (NV50EXAPrepareCopy(srcdata, destdata, 0, 0, drawmode, ~0))
1172 NV50EXACopy(destdata, srcX, srcY, destX , destY, width, height);
1173 return TRUE;
1176 return FALSE;
1179 /* NOTE: Assumes lock on bitmap is already made */
1180 /* NOTE: Assumes buffer is not mapped */
1181 /* NOTE: Allows different formats of source and destination */
1182 BOOL HIDDNouveauNV503DCopyBox(struct CardData * carddata,
1183 struct HIDDNouveauBitMapData * srcdata, struct HIDDNouveauBitMapData * destdata,
1184 LONG srcX, LONG srcY, LONG destX, LONG destY, LONG width, LONG height,
1185 ULONG blendop)
1187 struct Picture sPict, dPict;
1188 struct nv50_exa_state state;
1189 ULONG maskX = 0; ULONG maskY = 0;
1191 HIDDNouveauFillPictureFromBitMapData(&sPict, srcdata);
1192 HIDDNouveauFillPictureFromBitMapData(&dPict, destdata);
1194 if (NV50EXAPrepareComposite(blendop,
1195 &sPict, NULL, &dPict, srcdata, NULL, destdata, &state))
1197 NV50EXAComposite(destdata, srcX, srcY,
1198 maskX, maskY,
1199 destX , destY,
1200 width, height, &state);
1201 return TRUE;
1204 return FALSE;