nv04_surface.c revision 56dcd011b5ec33190f268cf546a4c68f81f5ebd0
1/* 2 * Copyright (C) 2007-2010 The Nouveau Project. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial 15 * portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 */ 26 27#include "nouveau_driver.h" 28#include "nouveau_class.h" 29#include "nouveau_context.h" 30#include "nouveau_util.h" 31#include "nv04_driver.h" 32 33static inline int 34swzsurf_format(gl_format format) 35{ 36 switch (format) { 37 case MESA_FORMAT_A8: 38 case MESA_FORMAT_L8: 39 case MESA_FORMAT_I8: 40 case MESA_FORMAT_RGB332: 41 case MESA_FORMAT_CI8: 42 return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y8; 43 44 case MESA_FORMAT_RGB565: 45 case MESA_FORMAT_RGB565_REV: 46 case MESA_FORMAT_ARGB4444: 47 case MESA_FORMAT_ARGB4444_REV: 48 case MESA_FORMAT_ARGB1555: 49 case MESA_FORMAT_RGBA5551: 50 case MESA_FORMAT_ARGB1555_REV: 51 case MESA_FORMAT_AL88: 52 case MESA_FORMAT_AL88_REV: 53 case MESA_FORMAT_YCBCR: 54 case MESA_FORMAT_YCBCR_REV: 55 case MESA_FORMAT_Z16: 56 return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_R5G6B5; 57 58 case MESA_FORMAT_RGBA8888: 59 case MESA_FORMAT_RGBA8888_REV: 60 case MESA_FORMAT_XRGB8888: 61 case MESA_FORMAT_ARGB8888: 62 case MESA_FORMAT_ARGB8888_REV: 63 case MESA_FORMAT_S8_Z24: 64 case MESA_FORMAT_Z24_S8: 65 case MESA_FORMAT_Z32: 66 return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8; 67 68 default: 69 assert(0); 70 } 71} 72 73static inline int 74surf2d_format(gl_format format) 75{ 76 switch (format) { 77 case MESA_FORMAT_A8: 78 case MESA_FORMAT_L8: 79 case MESA_FORMAT_I8: 80 case MESA_FORMAT_RGB332: 81 case MESA_FORMAT_CI8: 82 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8; 83 84 case MESA_FORMAT_RGB565: 85 case MESA_FORMAT_RGB565_REV: 86 case MESA_FORMAT_ARGB4444: 87 case MESA_FORMAT_ARGB4444_REV: 88 case MESA_FORMAT_ARGB1555: 89 case MESA_FORMAT_RGBA5551: 90 case MESA_FORMAT_ARGB1555_REV: 91 case MESA_FORMAT_AL88: 92 case MESA_FORMAT_AL88_REV: 93 case MESA_FORMAT_YCBCR: 94 case MESA_FORMAT_YCBCR_REV: 95 case MESA_FORMAT_Z16: 96 return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5; 97 98 case MESA_FORMAT_RGBA8888: 99 case MESA_FORMAT_RGBA8888_REV: 100 case MESA_FORMAT_XRGB8888: 101 case MESA_FORMAT_ARGB8888: 102 case MESA_FORMAT_ARGB8888_REV: 103 case MESA_FORMAT_S8_Z24: 104 case MESA_FORMAT_Z24_S8: 105 case MESA_FORMAT_Z32: 106 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32; 107 108 default: 109 assert(0); 110 } 111} 112 113static inline int 114rect_format(gl_format format) 115{ 116 switch (format) { 117 case MESA_FORMAT_A8: 118 case MESA_FORMAT_L8: 119 case MESA_FORMAT_I8: 120 case MESA_FORMAT_RGB332: 121 case MESA_FORMAT_CI8: 122 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8; 123 124 case MESA_FORMAT_RGB565: 125 case MESA_FORMAT_RGB565_REV: 126 case MESA_FORMAT_ARGB4444: 127 case MESA_FORMAT_ARGB4444_REV: 128 case MESA_FORMAT_ARGB1555: 129 case MESA_FORMAT_RGBA5551: 130 case MESA_FORMAT_ARGB1555_REV: 131 case MESA_FORMAT_AL88: 132 case MESA_FORMAT_AL88_REV: 133 case MESA_FORMAT_YCBCR: 134 case MESA_FORMAT_YCBCR_REV: 135 case MESA_FORMAT_Z16: 136 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5; 137 138 case MESA_FORMAT_RGBA8888: 139 case MESA_FORMAT_RGBA8888_REV: 140 case MESA_FORMAT_XRGB8888: 141 case MESA_FORMAT_ARGB8888: 142 case MESA_FORMAT_ARGB8888_REV: 143 case MESA_FORMAT_S8_Z24: 144 case MESA_FORMAT_Z24_S8: 145 case MESA_FORMAT_Z32: 146 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8; 147 148 default: 149 assert(0); 150 } 151} 152 153static inline int 154sifm_format(gl_format format) 155{ 156 switch (format) { 157 case MESA_FORMAT_A8: 158 case MESA_FORMAT_L8: 159 case MESA_FORMAT_I8: 160 case MESA_FORMAT_RGB332: 161 case MESA_FORMAT_CI8: 162 return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8; 163 164 case MESA_FORMAT_RGB565: 165 case MESA_FORMAT_RGB565_REV: 166 case MESA_FORMAT_ARGB4444: 167 case MESA_FORMAT_ARGB4444_REV: 168 case MESA_FORMAT_ARGB1555: 169 case MESA_FORMAT_RGBA5551: 170 case MESA_FORMAT_ARGB1555_REV: 171 case MESA_FORMAT_AL88: 172 case MESA_FORMAT_AL88_REV: 173 case MESA_FORMAT_YCBCR: 174 case MESA_FORMAT_YCBCR_REV: 175 case MESA_FORMAT_Z16: 176 return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5; 177 178 case MESA_FORMAT_RGBA8888: 179 case MESA_FORMAT_RGBA8888_REV: 180 case MESA_FORMAT_XRGB8888: 181 case MESA_FORMAT_ARGB8888: 182 case MESA_FORMAT_ARGB8888_REV: 183 case MESA_FORMAT_S8_Z24: 184 case MESA_FORMAT_Z24_S8: 185 case MESA_FORMAT_Z32: 186 return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8; 187 188 default: 189 assert(0); 190 } 191} 192 193static void 194nv04_surface_copy_swizzle(GLcontext *ctx, 195 struct nouveau_surface *dst, 196 struct nouveau_surface *src, 197 int dx, int dy, int sx, int sy, 198 int w, int h) 199{ 200 struct nouveau_channel *chan = context_chan(ctx); 201 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; 202 struct nouveau_grobj *swzsurf = hw->swzsurf; 203 struct nouveau_grobj *sifm = hw->sifm; 204 struct nouveau_bo_context *bctx = context_bctx(ctx, SURFACE); 205 const unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART; 206 /* Max width & height may not be the same on all HW, but must be POT */ 207 const unsigned max_w = 1024; 208 const unsigned max_h = 1024; 209 unsigned sub_w = w > max_w ? max_w : w; 210 unsigned sub_h = h > max_h ? max_h : h; 211 unsigned x, y; 212 213 /* Swizzled surfaces must be POT */ 214 assert(_mesa_is_pow_two(dst->width) && 215 _mesa_is_pow_two(dst->height)); 216 217 /* If area is too large to copy in one shot we must copy it in 218 * POT chunks to meet alignment requirements */ 219 assert(sub_w == w || _mesa_is_pow_two(sub_w)); 220 assert(sub_h == h || _mesa_is_pow_two(sub_h)); 221 222 nouveau_bo_marko(bctx, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 223 src->bo, bo_flags | NOUVEAU_BO_RD); 224 nouveau_bo_marko(bctx, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 225 dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 226 nouveau_bo_markl(bctx, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET, 227 dst->bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 228 229 BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_FORMAT, 1); 230 OUT_RING (chan, swzsurf_format(dst->format) | 231 log2i(dst->width) << 16 | 232 log2i(dst->height) << 24); 233 234 BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1); 235 OUT_RING (chan, swzsurf->handle); 236 237 for (y = 0; y < h; y += sub_h) { 238 sub_h = MIN2(sub_h, h - y); 239 240 for (x = 0; x < w; x += sub_w) { 241 sub_w = MIN2(sub_w, w - x); 242 /* Must be 64-byte aligned */ 243 assert(!(dst->offset & 63)); 244 245 MARK_RING(chan, 15, 1); 246 247 BEGIN_RING(chan, sifm, 248 NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 8); 249 OUT_RING(chan, sifm_format(src->format)); 250 OUT_RING(chan, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY); 251 OUT_RING(chan, (y + dy) << 16 | (x + dx)); 252 OUT_RING(chan, sub_h << 16 | sub_w); 253 OUT_RING(chan, (y + dy) << 16 | (x + dx)); 254 OUT_RING(chan, sub_h << 16 | sub_w); 255 OUT_RING(chan, 1 << 20); 256 OUT_RING(chan, 1 << 20); 257 258 BEGIN_RING(chan, sifm, 259 NV03_SCALED_IMAGE_FROM_MEMORY_SIZE, 4); 260 OUT_RING(chan, sub_h << 16 | sub_w); 261 OUT_RING(chan, src->pitch | 262 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER | 263 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE); 264 OUT_RELOCl(chan, src->bo, src->offset + 265 (y + sy) * src->pitch + 266 (x + sx) * src->cpp, 267 bo_flags | NOUVEAU_BO_RD); 268 OUT_RING(chan, 0); 269 } 270 } 271 272 nouveau_bo_context_reset(bctx); 273 274 if (context_chipset(ctx) < 0x10) 275 FIRE_RING(chan); 276} 277 278static void 279nv04_surface_copy_m2mf(GLcontext *ctx, 280 struct nouveau_surface *dst, 281 struct nouveau_surface *src, 282 int dx, int dy, int sx, int sy, 283 int w, int h) 284{ 285 struct nouveau_channel *chan = context_chan(ctx); 286 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; 287 struct nouveau_grobj *m2mf = hw->m2mf; 288 struct nouveau_bo_context *bctx = context_bctx(ctx, SURFACE); 289 const unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART; 290 unsigned dst_offset = dst->offset + dy * dst->pitch + dx * dst->cpp; 291 unsigned src_offset = src->offset + sy * src->pitch + sx * src->cpp; 292 293 nouveau_bo_marko(bctx, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 294 src->bo, bo_flags | NOUVEAU_BO_RD); 295 nouveau_bo_marko(bctx, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_OUT, 296 dst->bo, bo_flags | NOUVEAU_BO_WR); 297 298 while (h) { 299 int count = (h > 2047) ? 2047 : h; 300 301 MARK_RING(chan, 9, 2); 302 303 BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); 304 OUT_RELOCl(chan, src->bo, src_offset, 305 bo_flags | NOUVEAU_BO_RD); 306 OUT_RELOCl(chan, dst->bo, dst_offset, 307 bo_flags | NOUVEAU_BO_WR); 308 OUT_RING (chan, src->pitch); 309 OUT_RING (chan, dst->pitch); 310 OUT_RING (chan, w * src->cpp); 311 OUT_RING (chan, count); 312 OUT_RING (chan, 0x0101); 313 OUT_RING (chan, 0); 314 315 h -= count; 316 src_offset += src->pitch * count; 317 dst_offset += dst->pitch * count; 318 } 319 320 nouveau_bo_context_reset(bctx); 321 322 if (context_chipset(ctx) < 0x10) 323 FIRE_RING(chan); 324} 325 326void 327nv04_surface_copy(GLcontext *ctx, 328 struct nouveau_surface *dst, 329 struct nouveau_surface *src, 330 int dx, int dy, int sx, int sy, 331 int w, int h) 332{ 333 /* Setup transfer to swizzle the texture to vram if needed */ 334 if (src->layout != SWIZZLED && 335 dst->layout == SWIZZLED && 336 dst->width > 2 && dst->height > 1) { 337 nv04_surface_copy_swizzle(ctx, dst, src, 338 dx, dy, sx, sy, w, h); 339 return; 340 } 341 342 nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h); 343} 344 345void 346nv04_surface_fill(GLcontext *ctx, 347 struct nouveau_surface *dst, 348 unsigned mask, unsigned value, 349 int dx, int dy, int w, int h) 350{ 351 struct nouveau_channel *chan = context_chan(ctx); 352 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; 353 struct nouveau_grobj *surf2d = hw->surf2d; 354 struct nouveau_grobj *patt = hw->patt; 355 struct nouveau_grobj *rect = hw->rect; 356 unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART; 357 358 MARK_RING (chan, 19, 4); 359 360 BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2); 361 OUT_RELOCo(chan, dst->bo, bo_flags | NOUVEAU_BO_WR); 362 OUT_RELOCo(chan, dst->bo, bo_flags | NOUVEAU_BO_WR); 363 BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4); 364 OUT_RING (chan, surf2d_format(dst->format)); 365 OUT_RING (chan, (dst->pitch << 16) | dst->pitch); 366 OUT_RELOCl(chan, dst->bo, dst->offset, bo_flags | NOUVEAU_BO_WR); 367 OUT_RELOCl(chan, dst->bo, dst->offset, bo_flags | NOUVEAU_BO_WR); 368 369 BEGIN_RING(chan, patt, NV04_IMAGE_PATTERN_COLOR_FORMAT, 1); 370 OUT_RING (chan, rect_format(dst->format)); 371 BEGIN_RING(chan, patt, NV04_IMAGE_PATTERN_MONOCHROME_COLOR1, 1); 372 OUT_RING (chan, mask | ~0 << (8 * dst->cpp)); 373 374 BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1); 375 OUT_RING (chan, rect_format(dst->format)); 376 BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1); 377 OUT_RING (chan, value); 378 BEGIN_RING(chan, rect, 379 NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2); 380 OUT_RING (chan, (dx << 16) | dy); 381 OUT_RING (chan, ( w << 16) | h); 382 383 if (context_chipset(ctx) < 0x10) 384 FIRE_RING(chan); 385} 386 387void 388nv04_surface_takedown(GLcontext *ctx) 389{ 390 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; 391 392 nouveau_grobj_free(&hw->swzsurf); 393 nouveau_grobj_free(&hw->sifm); 394 nouveau_grobj_free(&hw->rect); 395 nouveau_grobj_free(&hw->rop); 396 nouveau_grobj_free(&hw->patt); 397 nouveau_grobj_free(&hw->surf2d); 398 nouveau_grobj_free(&hw->m2mf); 399 nouveau_notifier_free(&hw->ntfy); 400} 401 402GLboolean 403nv04_surface_init(GLcontext *ctx) 404{ 405 struct nouveau_channel *chan = context_chan(ctx); 406 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; 407 unsigned handle = 0x88000000, class; 408 int ret; 409 410 /* Notifier object. */ 411 ret = nouveau_notifier_alloc(chan, handle++, 1, &hw->ntfy); 412 if (ret) 413 goto fail; 414 415 /* Memory to memory format. */ 416 ret = nouveau_grobj_alloc(chan, handle++, NV04_MEMORY_TO_MEMORY_FORMAT, 417 &hw->m2mf); 418 if (ret) 419 goto fail; 420 421 BEGIN_RING(chan, hw->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); 422 OUT_RING (chan, hw->ntfy->handle); 423 424 /* Context surfaces 2D. */ 425 if (context_chipset(ctx) < 0x10) 426 class = NV04_CONTEXT_SURFACES_2D; 427 else 428 class = NV10_CONTEXT_SURFACES_2D; 429 430 ret = nouveau_grobj_alloc(chan, handle++, class, &hw->surf2d); 431 if (ret) 432 goto fail; 433 434 /* Raster op. */ 435 ret = nouveau_grobj_alloc(chan, handle++, NV03_CONTEXT_ROP, &hw->rop); 436 if (ret) 437 goto fail; 438 439 BEGIN_RING(chan, hw->rop, NV03_CONTEXT_ROP_DMA_NOTIFY, 1); 440 OUT_RING (chan, hw->ntfy->handle); 441 442 BEGIN_RING(chan, hw->rop, NV03_CONTEXT_ROP_ROP, 1); 443 OUT_RING (chan, 0xca); /* DPSDxax in the GDI speech. */ 444 445 /* Image pattern. */ 446 ret = nouveau_grobj_alloc(chan, handle++, NV04_IMAGE_PATTERN, 447 &hw->patt); 448 if (ret) 449 goto fail; 450 451 BEGIN_RING(chan, hw->patt, NV04_IMAGE_PATTERN_DMA_NOTIFY, 1); 452 OUT_RING (chan, hw->ntfy->handle); 453 454 BEGIN_RING(chan, hw->patt, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT, 3); 455 OUT_RING (chan, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE); 456 OUT_RING (chan, NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8); 457 OUT_RING (chan, NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO); 458 459 BEGIN_RING(chan, hw->patt, NV04_IMAGE_PATTERN_MONOCHROME_COLOR0, 4); 460 OUT_RING (chan, 0); 461 OUT_RING (chan, 0); 462 OUT_RING (chan, ~0); 463 OUT_RING (chan, ~0); 464 465 /* GDI rectangle text. */ 466 ret = nouveau_grobj_alloc(chan, handle++, NV04_GDI_RECTANGLE_TEXT, 467 &hw->rect); 468 if (ret) 469 goto fail; 470 471 BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1); 472 OUT_RING (chan, hw->ntfy->handle); 473 BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1); 474 OUT_RING (chan, hw->surf2d->handle); 475 BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_ROP, 1); 476 OUT_RING (chan, hw->rop->handle); 477 BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_PATTERN, 1); 478 OUT_RING (chan, hw->patt->handle); 479 480 BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1); 481 OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND); 482 BEGIN_RING(chan, hw->rect, 483 NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1); 484 OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE); 485 486 /* Swizzled surface. */ 487 switch (context_chipset(ctx) & 0xf0) { 488 case 0x00: 489 case 0x10: 490 class = NV04_SWIZZLED_SURFACE; 491 break; 492 case 0x20: 493 class = NV20_SWIZZLED_SURFACE; 494 break; 495 default: 496 /* Famous last words: this really can't happen.. */ 497 assert(0); 498 break; 499 } 500 501 ret = nouveau_grobj_alloc(chan, handle++, class, &hw->swzsurf); 502 if (ret) 503 goto fail; 504 505 /* Scaled image from memory. */ 506 switch (context_chipset(ctx) & 0xf0) { 507 case 0x00: 508 class = NV04_SCALED_IMAGE_FROM_MEMORY; 509 break; 510 case 0x10: 511 case 0x20: 512 class = NV10_SCALED_IMAGE_FROM_MEMORY; 513 break; 514 } 515 516 ret = nouveau_grobj_alloc(chan, handle++, class, &hw->sifm); 517 if (ret) 518 goto fail; 519 520 if (context_chipset(ctx) >= 0x10) { 521 BEGIN_RING(chan, hw->sifm, 522 NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 1); 523 OUT_RING(chan, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE); 524 } 525 526 return GL_TRUE; 527 528fail: 529 nv04_surface_takedown(ctx); 530 return GL_FALSE; 531} 532