1 #include "pipe/p_context.h"
2 #include "pipe/p_format.h"
3 #include "util/u_memory.h"
5 #include "nouveau/nouveau_winsys.h"
6 #include "nouveau/nouveau_util.h"
7 #include "nouveau/nouveau_screen.h"
8 #include "nv04_surface_2d.h"
11 nv04_surface_format(enum pipe_format format
)
14 case PIPE_FORMAT_A8_UNORM
:
15 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8
;
16 case PIPE_FORMAT_R16_SNORM
:
17 case PIPE_FORMAT_R5G6B5_UNORM
:
18 case PIPE_FORMAT_Z16_UNORM
:
19 return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5
;
20 case PIPE_FORMAT_X8R8G8B8_UNORM
:
21 case PIPE_FORMAT_A8R8G8B8_UNORM
:
22 return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8
;
23 case PIPE_FORMAT_Z24S8_UNORM
:
24 case PIPE_FORMAT_Z24X8_UNORM
:
25 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32
;
32 nv04_rect_format(enum pipe_format format
)
35 case PIPE_FORMAT_A8_UNORM
:
36 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8
;
37 case PIPE_FORMAT_R5G6B5_UNORM
:
38 case PIPE_FORMAT_Z16_UNORM
:
39 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5
;
40 case PIPE_FORMAT_A8R8G8B8_UNORM
:
41 case PIPE_FORMAT_Z24S8_UNORM
:
42 case PIPE_FORMAT_Z24X8_UNORM
:
43 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8
;
50 nv04_scaled_image_format(enum pipe_format format
)
53 case PIPE_FORMAT_A1R5G5B5_UNORM
:
54 return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5
;
55 case PIPE_FORMAT_A8R8G8B8_UNORM
:
56 return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8
;
57 case PIPE_FORMAT_X8R8G8B8_UNORM
:
58 return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8
;
59 case PIPE_FORMAT_R5G6B5_UNORM
:
60 case PIPE_FORMAT_R16_SNORM
:
61 return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5
;
67 static INLINE
unsigned
68 nv04_swizzle_bits(unsigned x
, unsigned y
)
70 unsigned u
= (x
& 0x001) << 0 |
83 unsigned v
= (y
& 0x001) << 1 |
99 nv04_surface_copy_swizzle(struct nv04_surface_2d
*ctx
,
100 struct pipe_surface
*dst
, int dx
, int dy
,
101 struct pipe_surface
*src
, int sx
, int sy
,
104 struct nouveau_channel
*chan
= ctx
->swzsurf
->channel
;
105 struct nouveau_grobj
*swzsurf
= ctx
->swzsurf
;
106 struct nouveau_grobj
*sifm
= ctx
->sifm
;
107 struct nouveau_bo
*src_bo
= nouveau_bo(ctx
->buf(src
));
108 struct nouveau_bo
*dst_bo
= nouveau_bo(ctx
->buf(dst
));
109 const unsigned src_pitch
= ((struct nv04_surface
*)src
)->pitch
;
110 const unsigned max_w
= 1024;
111 const unsigned max_h
= 1024;
112 const unsigned sub_w
= w
> max_w
? max_w
: w
;
113 const unsigned sub_h
= h
> max_h
? max_h
: h
;
118 /* That's the way she likes it */
119 assert(src_pitch
== ((struct nv04_surface
*)dst
)->pitch
);
122 BEGIN_RING(chan
, swzsurf
, NV04_SWIZZLED_SURFACE_DMA_IMAGE
, 1);
123 OUT_RELOCo(chan
, dst_bo
,
124 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
126 BEGIN_RING(chan
, swzsurf
, NV04_SWIZZLED_SURFACE_FORMAT
, 1);
127 OUT_RING (chan
, nv04_surface_format(dst
->format
) |
128 log2i(w
) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT
|
129 log2i(h
) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT
);
131 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE
, 1);
132 OUT_RELOCo(chan
, src_bo
,
133 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
134 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE
, 1);
135 OUT_RING (chan
, swzsurf
->handle
);
137 for (cy
= 0; cy
< h
; cy
+= sub_h
) {
138 for (cx
= 0; cx
< w
; cx
+= sub_w
) {
139 BEGIN_RING(chan
, swzsurf
, NV04_SWIZZLED_SURFACE_OFFSET
, 1);
140 OUT_RELOCl(chan
, dst_bo
, dst
->offset
+ nv04_swizzle_bits(cx
+dx
, cy
+dy
) *
141 dst
->texture
->block
.size
, NOUVEAU_BO_GART
|
142 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
144 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION
, 9);
145 OUT_RING (chan
, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE
);
146 OUT_RING (chan
, nv04_scaled_image_format(src
->format
));
147 OUT_RING (chan
, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY
);
149 OUT_RING (chan
, sub_h
<< 16 | sub_w
);
151 OUT_RING (chan
, sub_h
<< 16 | sub_w
);
152 OUT_RING (chan
, 1 << 20);
153 OUT_RING (chan
, 1 << 20);
155 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_SIZE
, 4);
156 OUT_RING (chan
, sub_h
<< 16 | sub_w
);
157 OUT_RING (chan
, src_pitch
|
158 NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER
|
159 NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE
);
160 OUT_RELOCl(chan
, src_bo
, src
->offset
+ (cy
+sy
) * src_pitch
+
161 (cx
+sx
) * src
->texture
->block
.size
, NOUVEAU_BO_GART
|
162 NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
171 nv04_surface_copy_m2mf(struct nv04_surface_2d
*ctx
,
172 struct pipe_surface
*dst
, int dx
, int dy
,
173 struct pipe_surface
*src
, int sx
, int sy
, int w
, int h
)
175 struct nouveau_channel
*chan
= ctx
->m2mf
->channel
;
176 struct nouveau_grobj
*m2mf
= ctx
->m2mf
;
177 struct nouveau_bo
*src_bo
= nouveau_bo(ctx
->buf(src
));
178 struct nouveau_bo
*dst_bo
= nouveau_bo(ctx
->buf(dst
));
179 unsigned src_pitch
= ((struct nv04_surface
*)src
)->pitch
;
180 unsigned dst_pitch
= ((struct nv04_surface
*)dst
)->pitch
;
181 unsigned dst_offset
= dst
->offset
+ dy
* dst_pitch
+
182 dx
* dst
->texture
->block
.size
;
183 unsigned src_offset
= src
->offset
+ sy
* src_pitch
+
184 sx
* src
->texture
->block
.size
;
186 WAIT_RING (chan
, 3 + ((h
/ 2047) + 1) * 9);
187 BEGIN_RING(chan
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN
, 2);
188 OUT_RELOCo(chan
, src_bo
,
189 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
190 OUT_RELOCo(chan
, dst_bo
,
191 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
194 int count
= (h
> 2047) ? 2047 : h
;
196 BEGIN_RING(chan
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN
, 8);
197 OUT_RELOCl(chan
, src_bo
, src_offset
,
198 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
);
199 OUT_RELOCl(chan
, dst_bo
, dst_offset
,
200 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_WR
);
201 OUT_RING (chan
, src_pitch
);
202 OUT_RING (chan
, dst_pitch
);
203 OUT_RING (chan
, w
* src
->texture
->block
.size
);
204 OUT_RING (chan
, count
);
205 OUT_RING (chan
, 0x0101);
209 src_offset
+= src_pitch
* count
;
210 dst_offset
+= dst_pitch
* count
;
217 nv04_surface_copy_m2mf_swizzle(struct nv04_surface_2d
*ctx
,
218 struct pipe_surface
*dst
, int dx
, int dy
,
219 struct pipe_surface
*src
, int sx
, int sy
)
221 struct nouveau_channel
*chan
= ctx
->m2mf
->channel
;
222 struct nouveau_grobj
*m2mf
= ctx
->m2mf
;
223 struct nouveau_bo
*src_bo
= nouveau_bo(ctx
->buf(src
));
224 struct nouveau_bo
*dst_bo
= nouveau_bo(ctx
->buf(dst
));
225 unsigned src_pitch
= ((struct nv04_surface
*)src
)->pitch
;
226 unsigned dst_pitch
= ((struct nv04_surface
*)dst
)->pitch
;
227 unsigned dst_offset
= dst
->offset
+ nv04_swizzle_bits(dx
, dy
) *
228 dst
->texture
->block
.size
;
229 unsigned src_offset
= src
->offset
+ sy
* src_pitch
+
230 sx
* src
->texture
->block
.size
;
232 BEGIN_RING(chan
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN
, 2);
233 OUT_RELOCo(chan
, src_bo
,
234 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
235 OUT_RELOCo(chan
, dst_bo
,
236 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
238 BEGIN_RING(chan
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN
, 8);
239 OUT_RELOCl(chan
, src_bo
, src_offset
,
240 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
);
241 OUT_RELOCl(chan
, dst_bo
, dst_offset
,
242 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_WR
);
243 OUT_RING (chan
, src_pitch
);
244 OUT_RING (chan
, dst_pitch
);
245 OUT_RING (chan
, 1 * src
->texture
->block
.size
);
247 OUT_RING (chan
, 0x0101);
254 nv04_surface_copy_blit(struct nv04_surface_2d
*ctx
, struct pipe_surface
*dst
,
255 int dx
, int dy
, struct pipe_surface
*src
, int sx
, int sy
,
258 struct nouveau_channel
*chan
= ctx
->surf2d
->channel
;
259 struct nouveau_grobj
*surf2d
= ctx
->surf2d
;
260 struct nouveau_grobj
*blit
= ctx
->blit
;
261 struct nouveau_bo
*src_bo
= nouveau_bo(ctx
->buf(src
));
262 struct nouveau_bo
*dst_bo
= nouveau_bo(ctx
->buf(dst
));
263 unsigned src_pitch
= ((struct nv04_surface
*)src
)->pitch
;
264 unsigned dst_pitch
= ((struct nv04_surface
*)dst
)->pitch
;
267 format
= nv04_surface_format(dst
->format
);
271 WAIT_RING (chan
, 12);
272 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
273 OUT_RELOCo(chan
, src_bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
274 OUT_RELOCo(chan
, dst_bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
275 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_FORMAT
, 4);
276 OUT_RING (chan
, format
);
277 OUT_RING (chan
, (dst_pitch
<< 16) | src_pitch
);
278 OUT_RELOCl(chan
, src_bo
, src
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
279 OUT_RELOCl(chan
, dst_bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
281 BEGIN_RING(chan
, blit
, 0x0300, 3);
282 OUT_RING (chan
, (sy
<< 16) | sx
);
283 OUT_RING (chan
, (dy
<< 16) | dx
);
284 OUT_RING (chan
, ( h
<< 16) | w
);
290 nv04_surface_copy(struct nv04_surface_2d
*ctx
, struct pipe_surface
*dst
,
291 int dx
, int dy
, struct pipe_surface
*src
, int sx
, int sy
,
294 unsigned src_pitch
= ((struct nv04_surface
*)src
)->pitch
;
295 unsigned dst_pitch
= ((struct nv04_surface
*)dst
)->pitch
;
296 int src_linear
= src
->texture
->tex_usage
& NOUVEAU_TEXTURE_USAGE_LINEAR
;
297 int dst_linear
= dst
->texture
->tex_usage
& NOUVEAU_TEXTURE_USAGE_LINEAR
;
299 assert(src
->format
== dst
->format
);
301 /* Setup transfer to swizzle the texture to vram if needed */
302 if (src_linear
&& !dst_linear
) {
305 if ((w
>1) && (h
>1)) {
306 int potWidth
= 1<<log2i(w
);
307 int potHeight
= 1<<log2i(h
);
308 int remainWidth
= w
-potWidth
;
309 int remainHeight
= h
-potHeight
;
310 int squareDim
= (potWidth
>potHeight
? potHeight
: potWidth
);
312 /* top left is always POT, but we can only swizzle squares */
313 for (y
=0; y
<potHeight
; y
+=squareDim
) {
314 for (x
=0; x
<potWidth
; x
+= squareDim
) {
315 nv04_surface_copy_swizzle(ctx
, dst
, dx
+x
, dy
+y
,
317 squareDim
, squareDim
);
323 nv04_surface_copy(ctx
, dst
, dx
+potWidth
, dy
,
324 src
, sx
+potWidth
, sy
,
325 remainWidth
, potHeight
);
329 if (remainHeight
>0) {
330 nv04_surface_copy(ctx
, dst
, dx
, dy
+potHeight
,
331 src
, sx
, sy
+potHeight
,
332 potWidth
, remainHeight
);
336 if ((remainWidth
>0) && (remainHeight
>0)) {
337 nv04_surface_copy(ctx
, dst
, dx
+potWidth
, dy
+potHeight
,
338 src
, sx
+potWidth
, sy
+potHeight
,
339 remainWidth
, remainHeight
);
342 /* We have a column to copy to a swizzled texture */
343 for (y
=0; y
<h
; y
++) {
344 nv04_surface_copy_m2mf_swizzle(ctx
, dst
, dx
, dy
+y
,
348 /* We have a row to copy to a swizzled texture */
349 for (x
=0; x
<w
; x
++) {
350 nv04_surface_copy_m2mf_swizzle(ctx
, dst
, dx
+x
, dy
,
358 /* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
359 * to NV_MEMORY_TO_MEMORY_FORMAT in this case.
361 if ((src
->offset
& 63) || (dst
->offset
& 63) ||
362 (src_pitch
& 63) || (dst_pitch
& 63)) {
363 nv04_surface_copy_m2mf(ctx
, dst
, dx
, dy
, src
, sx
, sy
, w
, h
);
367 nv04_surface_copy_blit(ctx
, dst
, dx
, dy
, src
, sx
, sy
, w
, h
);
371 nv04_surface_fill(struct nv04_surface_2d
*ctx
, struct pipe_surface
*dst
,
372 int dx
, int dy
, int w
, int h
, unsigned value
)
374 struct nouveau_channel
*chan
= ctx
->surf2d
->channel
;
375 struct nouveau_grobj
*surf2d
= ctx
->surf2d
;
376 struct nouveau_grobj
*rect
= ctx
->rect
;
377 struct nouveau_bo
*dst_bo
= nouveau_bo(ctx
->buf(dst
));
378 unsigned dst_pitch
= ((struct nv04_surface
*)dst
)->pitch
;
379 int cs2d_format
, gdirect_format
;
381 cs2d_format
= nv04_surface_format(dst
->format
);
382 assert(cs2d_format
>= 0);
384 gdirect_format
= nv04_rect_format(dst
->format
);
385 assert(gdirect_format
>= 0);
387 WAIT_RING (chan
, 16);
388 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
389 OUT_RELOCo(chan
, dst_bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
390 OUT_RELOCo(chan
, dst_bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
391 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_FORMAT
, 4);
392 OUT_RING (chan
, cs2d_format
);
393 OUT_RING (chan
, (dst_pitch
<< 16) | dst_pitch
);
394 OUT_RELOCl(chan
, dst_bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
395 OUT_RELOCl(chan
, dst_bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
397 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT
, 1);
398 OUT_RING (chan
, gdirect_format
);
399 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_COLOR1_A
, 1);
400 OUT_RING (chan
, value
);
401 BEGIN_RING(chan
, rect
,
402 NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
403 OUT_RING (chan
, (dx
<< 16) | dy
);
404 OUT_RING (chan
, ( w
<< 16) | h
);
408 nv04_surface_2d_takedown(struct nv04_surface_2d
**pctx
)
410 struct nv04_surface_2d
*ctx
;
417 nouveau_notifier_free(&ctx
->ntfy
);
418 nouveau_grobj_free(&ctx
->m2mf
);
419 nouveau_grobj_free(&ctx
->surf2d
);
420 nouveau_grobj_free(&ctx
->swzsurf
);
421 nouveau_grobj_free(&ctx
->rect
);
422 nouveau_grobj_free(&ctx
->blit
);
423 nouveau_grobj_free(&ctx
->sifm
);
428 struct nv04_surface_2d
*
429 nv04_surface_2d_init(struct nouveau_screen
*screen
)
431 struct nv04_surface_2d
*ctx
= CALLOC_STRUCT(nv04_surface_2d
);
432 struct nouveau_channel
*chan
= screen
->channel
;
433 unsigned handle
= 0x88000000, class;
439 ret
= nouveau_notifier_alloc(chan
, handle
++, 1, &ctx
->ntfy
);
441 nv04_surface_2d_takedown(&ctx
);
445 ret
= nouveau_grobj_alloc(chan
, handle
++, 0x0039, &ctx
->m2mf
);
447 nv04_surface_2d_takedown(&ctx
);
451 BEGIN_RING(chan
, ctx
->m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY
, 1);
452 OUT_RING (chan
, ctx
->ntfy
->handle
);
454 if (chan
->device
->chipset
< 0x10)
455 class = NV04_CONTEXT_SURFACES_2D
;
457 class = NV10_CONTEXT_SURFACES_2D
;
459 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &ctx
->surf2d
);
461 nv04_surface_2d_takedown(&ctx
);
465 BEGIN_RING(chan
, ctx
->surf2d
,
466 NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
467 OUT_RING (chan
, chan
->vram
->handle
);
468 OUT_RING (chan
, chan
->vram
->handle
);
470 if (chan
->device
->chipset
< 0x10)
471 class = NV04_IMAGE_BLIT
;
473 class = NV12_IMAGE_BLIT
;
475 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &ctx
->blit
);
477 nv04_surface_2d_takedown(&ctx
);
481 BEGIN_RING(chan
, ctx
->blit
, NV04_IMAGE_BLIT_DMA_NOTIFY
, 1);
482 OUT_RING (chan
, ctx
->ntfy
->handle
);
483 BEGIN_RING(chan
, ctx
->blit
, NV04_IMAGE_BLIT_SURFACE
, 1);
484 OUT_RING (chan
, ctx
->surf2d
->handle
);
485 BEGIN_RING(chan
, ctx
->blit
, NV04_IMAGE_BLIT_OPERATION
, 1);
486 OUT_RING (chan
, NV04_IMAGE_BLIT_OPERATION_SRCCOPY
);
488 ret
= nouveau_grobj_alloc(chan
, handle
++, NV04_GDI_RECTANGLE_TEXT
,
491 nv04_surface_2d_takedown(&ctx
);
495 BEGIN_RING(chan
, ctx
->rect
, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY
, 1);
496 OUT_RING (chan
, ctx
->ntfy
->handle
);
497 BEGIN_RING(chan
, ctx
->rect
, NV04_GDI_RECTANGLE_TEXT_SURFACE
, 1);
498 OUT_RING (chan
, ctx
->surf2d
->handle
);
499 BEGIN_RING(chan
, ctx
->rect
, NV04_GDI_RECTANGLE_TEXT_OPERATION
, 1);
500 OUT_RING (chan
, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY
);
501 BEGIN_RING(chan
, ctx
->rect
,
502 NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT
, 1);
503 OUT_RING (chan
, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE
);
505 switch (chan
->device
->chipset
& 0xf0) {
508 class = NV04_SWIZZLED_SURFACE
;
511 class = NV20_SWIZZLED_SURFACE
;
514 class = NV30_SWIZZLED_SURFACE
;
518 class = NV40_SWIZZLED_SURFACE
;
521 /* Famous last words: this really can't happen.. */
526 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &ctx
->swzsurf
);
528 nv04_surface_2d_takedown(&ctx
);
532 switch (chan
->device
->chipset
& 0xf0) {
535 class = NV10_SCALED_IMAGE_FROM_MEMORY
;
538 class = NV30_SCALED_IMAGE_FROM_MEMORY
;
542 class = NV40_SCALED_IMAGE_FROM_MEMORY
;
545 class = NV04_SCALED_IMAGE_FROM_MEMORY
;
549 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &ctx
->sifm
);
551 nv04_surface_2d_takedown(&ctx
);
555 ctx
->copy
= nv04_surface_copy
;
556 ctx
->fill
= nv04_surface_fill
;