1 /* 2 * Copyright (C) 2009 Francisco Jerez. 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_context.h" 29 #include "nouveau_texture.h" 30 #include "nouveau_fbo.h" 31 #include "nouveau_util.h" 32 33 #include "main/pbo.h" 34 #include "main/texobj.h" 35 #include "main/texstore.h" 36 #include "main/texformat.h" 37 #include "main/texcompress.h" 38 #include "main/texgetimage.h" 39 #include "main/mipmap.h" 40 #include "main/teximage.h" 41 #include "drivers/common/meta.h" 42 #include "swrast/s_texfetch.h" 43 44 static struct gl_texture_object * 45 nouveau_texture_new(struct gl_context *ctx, GLuint name, GLenum target) 46 { 47 struct nouveau_texture *nt = CALLOC_STRUCT(nouveau_texture); 48 49 _mesa_initialize_texture_object(&nt->base, name, target); 50 51 return &nt->base; 52 } 53 54 static void 55 nouveau_texture_free(struct gl_context *ctx, struct gl_texture_object *t) 56 { 57 struct nouveau_texture *nt = to_nouveau_texture(t); 58 int i; 59 60 for (i = 0; i < MAX_TEXTURE_LEVELS; i++) 61 nouveau_surface_ref(NULL, &nt->surfaces[i]); 62 63 _mesa_delete_texture_object(ctx, t); 64 } 65 66 static struct gl_texture_image * 67 nouveau_teximage_new(struct gl_context *ctx) 68 { 69 struct nouveau_teximage *nti = CALLOC_STRUCT(nouveau_teximage); 70 71 return &nti->base.Base; 72 } 73 74 static void 75 nouveau_teximage_free(struct gl_context *ctx, struct gl_texture_image *ti) 76 { 77 struct nouveau_teximage *nti = to_nouveau_teximage(ti); 78 79 nouveau_surface_ref(NULL, &nti->surface); 80 } 81 82 static void 83 nouveau_teximage_map(struct gl_context *ctx, struct gl_texture_image *ti, 84 int access, int x, int y, int w, int h) 85 { 86 struct nouveau_teximage *nti = to_nouveau_teximage(ti); 87 struct nouveau_surface *s = &nti->surface; 88 struct nouveau_surface *st = &nti->transfer.surface; 89 struct nouveau_client *client = context_client(ctx); 90 91 if (s->bo) { 92 if (!(access & GL_MAP_READ_BIT) && 93 nouveau_pushbuf_refd(context_push(ctx), s->bo)) { 94 unsigned size; 95 /* 96 * Heuristic: use a bounce buffer to pipeline 97 * teximage transfers. 98 */ 99 st->layout = LINEAR; 100 st->format = s->format; 101 st->cpp = s->cpp; 102 st->width = w; 103 st->height = h; 104 st->pitch = s->pitch; 105 nti->transfer.x = x; 106 nti->transfer.y = y; 107 108 size = get_format_blocksy(st->format, h) * st->pitch; 109 nti->base.Map = nouveau_get_scratch(ctx, size, 110 &st->bo, &st->offset); 111 112 } else { 113 int ret, flags = 0; 114 115 if (access & GL_MAP_READ_BIT) 116 flags |= NOUVEAU_BO_RD; 117 if (access & GL_MAP_WRITE_BIT) 118 flags |= NOUVEAU_BO_WR; 119 120 if (!s->bo->map) { 121 ret = nouveau_bo_map(s->bo, flags, client); 122 assert(!ret); 123 } 124 125 nti->base.Map = s->bo->map + 126 get_format_blocksy(s->format, y) * s->pitch + 127 get_format_blocksx(s->format, x) * s->cpp; 128 129 } 130 } 131 } 132 133 static void 134 nouveau_teximage_unmap(struct gl_context *ctx, struct gl_texture_image *ti) 135 { 136 struct nouveau_teximage *nti = to_nouveau_teximage(ti); 137 struct nouveau_surface *s = &nti->surface; 138 struct nouveau_surface *st = &nti->transfer.surface; 139 140 if (st->bo) { 141 context_drv(ctx)->surface_copy(ctx, s, st, nti->transfer.x, 142 nti->transfer.y, 0, 0, 143 st->width, st->height); 144 nouveau_surface_ref(NULL, st); 145 146 } 147 nti->base.Map = NULL; 148 } 149 150 151 static void 152 nouveau_map_texture_image(struct gl_context *ctx, 153 struct gl_texture_image *ti, 154 GLuint slice, 155 GLuint x, GLuint y, GLuint w, GLuint h, 156 GLbitfield mode, 157 GLubyte **map, 158 GLint *stride) 159 { 160 struct nouveau_teximage *nti = to_nouveau_teximage(ti); 161 struct nouveau_surface *s = &nti->surface; 162 struct nouveau_surface *st = &nti->transfer.surface; 163 struct nouveau_client *client = context_client(ctx); 164 165 /* Nouveau has no support for 3D or cubemap textures. */ 166 assert(slice == 0); 167 168 if (s->bo) { 169 if (!(mode & GL_MAP_READ_BIT) && 170 nouveau_pushbuf_refd(context_push(ctx), s->bo)) { 171 unsigned size; 172 /* 173 * Heuristic: use a bounce buffer to pipeline 174 * teximage transfers. 175 */ 176 st->layout = LINEAR; 177 st->format = s->format; 178 st->cpp = s->cpp; 179 st->width = w; 180 st->height = h; 181 st->pitch = s->pitch; 182 nti->transfer.x = x; 183 nti->transfer.y = y; 184 185 size = get_format_blocksy(st->format, h) * st->pitch; 186 *map = nouveau_get_scratch(ctx, size, 187 &st->bo, &st->offset); 188 *stride = st->pitch; 189 } else { 190 int ret, flags = 0; 191 192 if (mode & GL_MAP_READ_BIT) 193 flags |= NOUVEAU_BO_RD; 194 if (mode & GL_MAP_WRITE_BIT) 195 flags |= NOUVEAU_BO_WR; 196 197 if (!s->bo->map) { 198 ret = nouveau_bo_map(s->bo, flags, client); 199 assert(!ret); 200 } 201 202 *map = s->bo->map + 203 get_format_blocksy(s->format, y) * s->pitch + 204 get_format_blocksx(s->format, x) * s->cpp; 205 *stride = s->pitch; 206 } 207 } else { 208 *map = nti->base.Map + 209 get_format_blocksy(s->format, y) * s->pitch + 210 get_format_blocksx(s->format, x) * s->cpp; 211 *stride = s->pitch; 212 } 213 } 214 215 static void 216 nouveau_unmap_texture_image(struct gl_context *ctx, struct gl_texture_image *ti, 217 GLuint slice) 218 { 219 struct nouveau_teximage *nti = to_nouveau_teximage(ti); 220 struct nouveau_surface *s = &nti->surface; 221 struct nouveau_surface *st = &nti->transfer.surface; 222 223 if (st->bo) { 224 context_drv(ctx)->surface_copy(ctx, s, st, nti->transfer.x, 225 nti->transfer.y, 0, 0, 226 st->width, st->height); 227 nouveau_surface_ref(NULL, st); 228 229 } 230 231 nti->base.Map = NULL; 232 } 233 234 static gl_format 235 nouveau_choose_tex_format(struct gl_context *ctx, GLenum target, 236 GLint internalFormat, 237 GLenum srcFormat, GLenum srcType) 238 { 239 switch (internalFormat) { 240 case 4: 241 case GL_RGBA: 242 case GL_RGBA2: 243 case GL_RGBA4: 244 case GL_RGBA8: 245 case GL_RGBA12: 246 case GL_RGBA16: 247 case GL_RGB10_A2: 248 case GL_COMPRESSED_RGBA: 249 return MESA_FORMAT_ARGB8888; 250 case GL_RGB5_A1: 251 return MESA_FORMAT_ARGB1555; 252 253 case GL_RGB: 254 case GL_RGB8: 255 case GL_RGB10: 256 case GL_RGB12: 257 case GL_RGB16: 258 case GL_COMPRESSED_RGB: 259 return MESA_FORMAT_XRGB8888; 260 case 3: 261 case GL_R3_G3_B2: 262 case GL_RGB4: 263 case GL_RGB5: 264 return MESA_FORMAT_RGB565; 265 266 case 2: 267 case GL_LUMINANCE_ALPHA: 268 case GL_LUMINANCE4_ALPHA4: 269 case GL_LUMINANCE6_ALPHA2: 270 case GL_LUMINANCE12_ALPHA4: 271 case GL_LUMINANCE12_ALPHA12: 272 case GL_LUMINANCE16_ALPHA16: 273 case GL_LUMINANCE8_ALPHA8: 274 case GL_COMPRESSED_LUMINANCE_ALPHA: 275 return MESA_FORMAT_ARGB8888; 276 277 case 1: 278 case GL_LUMINANCE: 279 case GL_LUMINANCE4: 280 case GL_LUMINANCE12: 281 case GL_LUMINANCE16: 282 case GL_LUMINANCE8: 283 case GL_COMPRESSED_LUMINANCE: 284 return MESA_FORMAT_L8; 285 286 case GL_ALPHA: 287 case GL_ALPHA4: 288 case GL_ALPHA12: 289 case GL_ALPHA16: 290 case GL_ALPHA8: 291 case GL_COMPRESSED_ALPHA: 292 return MESA_FORMAT_A8; 293 294 case GL_INTENSITY: 295 case GL_INTENSITY4: 296 case GL_INTENSITY12: 297 case GL_INTENSITY16: 298 case GL_INTENSITY8: 299 return MESA_FORMAT_I8; 300 301 case GL_RGB_S3TC: 302 case GL_RGB4_S3TC: 303 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 304 return MESA_FORMAT_RGB_DXT1; 305 306 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 307 return MESA_FORMAT_RGBA_DXT1; 308 309 case GL_RGBA_S3TC: 310 case GL_RGBA4_S3TC: 311 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 312 return MESA_FORMAT_RGBA_DXT3; 313 314 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 315 return MESA_FORMAT_RGBA_DXT5; 316 317 default: 318 assert(0); 319 } 320 } 321 322 static GLboolean 323 teximage_fits(struct gl_texture_object *t, int level) 324 { 325 struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level]; 326 struct gl_texture_image *ti = t->Image[0][level]; 327 328 if (!ti || !to_nouveau_teximage(ti)->surface.bo) 329 return GL_FALSE; 330 331 if (level == t->BaseLevel && (s->offset & 0x7f)) 332 return GL_FALSE; 333 334 return t->Target == GL_TEXTURE_RECTANGLE || 335 (s->bo && s->format == ti->TexFormat && 336 s->width == ti->Width && s->height == ti->Height); 337 } 338 339 static GLboolean 340 validate_teximage(struct gl_context *ctx, struct gl_texture_object *t, 341 int level, int x, int y, int z, 342 int width, int height, int depth) 343 { 344 struct gl_texture_image *ti = t->Image[0][level]; 345 346 if (teximage_fits(t, level)) { 347 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces; 348 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; 349 350 if (t->Target == GL_TEXTURE_RECTANGLE) 351 nouveau_surface_ref(s, &ss[level]); 352 else 353 context_drv(ctx)->surface_copy(ctx, &ss[level], s, 354 x, y, x, y, 355 width, height); 356 357 return GL_TRUE; 358 } 359 360 return GL_FALSE; 361 } 362 363 static int 364 get_last_level(struct gl_texture_object *t) 365 { 366 struct gl_texture_image *base = t->Image[0][t->BaseLevel]; 367 368 if (t->Sampler.MinFilter == GL_NEAREST || 369 t->Sampler.MinFilter == GL_LINEAR || !base) 370 return t->BaseLevel; 371 else 372 return MIN2(t->BaseLevel + base->MaxNumLevels - 1, t->MaxLevel); 373 } 374 375 static void 376 relayout_texture(struct gl_context *ctx, struct gl_texture_object *t) 377 { 378 struct gl_texture_image *base = t->Image[0][t->BaseLevel]; 379 380 if (base && t->Target != GL_TEXTURE_RECTANGLE) { 381 struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces; 382 struct nouveau_surface *s = &to_nouveau_teximage(base)->surface; 383 int i, ret, last = get_last_level(t); 384 enum nouveau_surface_layout layout = 385 (_mesa_is_format_compressed(s->format) ? LINEAR : SWIZZLED); 386 unsigned size, pitch, offset = 0, 387 width = s->width, 388 height = s->height; 389 390 /* Deallocate the old storage. */ 391 for (i = 0; i < MAX_TEXTURE_LEVELS; i++) 392 nouveau_bo_ref(NULL, &ss[i].bo); 393 394 /* Relayout the mipmap tree. */ 395 for (i = t->BaseLevel; i <= last; i++) { 396 pitch = _mesa_format_row_stride(s->format, width); 397 size = get_format_blocksy(s->format, height) * pitch; 398 399 /* Images larger than 16B have to be aligned. */ 400 if (size > 16) 401 offset = align(offset, 64); 402 403 ss[i] = (struct nouveau_surface) { 404 .offset = offset, 405 .layout = layout, 406 .format = s->format, 407 .width = width, 408 .height = height, 409 .cpp = s->cpp, 410 .pitch = pitch, 411 }; 412 413 offset += size; 414 width = MAX2(1, width / 2); 415 height = MAX2(1, height / 2); 416 } 417 418 /* Get new storage. */ 419 size = align(offset, 64); 420 421 ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP | 422 NOUVEAU_BO_GART | NOUVEAU_BO_VRAM, 423 0, size, NULL, &ss[last].bo); 424 assert(!ret); 425 426 for (i = t->BaseLevel; i < last; i++) 427 nouveau_bo_ref(ss[last].bo, &ss[i].bo); 428 } 429 } 430 431 GLboolean 432 nouveau_texture_validate(struct gl_context *ctx, struct gl_texture_object *t) 433 { 434 struct nouveau_texture *nt = to_nouveau_texture(t); 435 int i, last = get_last_level(t); 436 437 if (!teximage_fits(t, t->BaseLevel) || 438 !teximage_fits(t, last)) 439 return GL_FALSE; 440 441 if (nt->dirty) { 442 nt->dirty = GL_FALSE; 443 444 /* Copy the teximages to the actual miptree. */ 445 for (i = t->BaseLevel; i <= last; i++) { 446 struct nouveau_surface *s = &nt->surfaces[i]; 447 448 validate_teximage(ctx, t, i, 0, 0, 0, 449 s->width, s->height, 1); 450 } 451 452 PUSH_KICK(context_push(ctx)); 453 } 454 455 return GL_TRUE; 456 } 457 458 void 459 nouveau_texture_reallocate(struct gl_context *ctx, struct gl_texture_object *t) 460 { 461 if (!teximage_fits(t, t->BaseLevel) || 462 !teximage_fits(t, get_last_level(t))) { 463 texture_dirty(t); 464 relayout_texture(ctx, t); 465 nouveau_texture_validate(ctx, t); 466 } 467 } 468 469 static unsigned 470 get_teximage_placement(struct gl_texture_image *ti) 471 { 472 if (ti->TexFormat == MESA_FORMAT_A8 || 473 ti->TexFormat == MESA_FORMAT_L8 || 474 ti->TexFormat == MESA_FORMAT_I8) 475 /* 1 cpp formats will have to be swizzled by the CPU, 476 * so leave them in system RAM for now. */ 477 return NOUVEAU_BO_MAP; 478 else 479 return NOUVEAU_BO_GART | NOUVEAU_BO_MAP; 480 } 481 482 static void 483 nouveau_teximage(struct gl_context *ctx, GLint dims, 484 struct gl_texture_image *ti, 485 GLsizei imageSize, 486 GLenum format, GLenum type, const GLvoid *pixels, 487 const struct gl_pixelstore_attrib *packing, 488 GLboolean compressed) 489 { 490 struct gl_texture_object *t = ti->TexObject; 491 const GLuint level = ti->Level; 492 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; 493 struct nouveau_teximage *nti = to_nouveau_teximage(ti); 494 int ret; 495 GLuint depth = compressed ? 1 : ti->Depth; 496 497 /* Allocate a new bo for the image. */ 498 nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti), 499 ti->TexFormat, ti->Width, ti->Height); 500 nti->base.RowStride = s->pitch / s->cpp; 501 502 if (compressed) 503 pixels = _mesa_validate_pbo_compressed_teximage(ctx, 504 imageSize, 505 pixels, packing, "glCompressedTexImage"); 506 else 507 pixels = _mesa_validate_pbo_teximage(ctx, 508 dims, ti->Width, ti->Height, depth, format, type, 509 pixels, packing, "glTexImage"); 510 511 if (pixels) { 512 /* Store the pixel data. */ 513 nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT, 514 0, 0, ti->Width, ti->Height); 515 516 ret = _mesa_texstore(ctx, dims, ti->_BaseFormat, 517 ti->TexFormat, 518 s->pitch, 519 &nti->base.Map, 520 ti->Width, ti->Height, depth, 521 format, type, pixels, packing); 522 assert(ret); 523 524 nouveau_teximage_unmap(ctx, ti); 525 _mesa_unmap_teximage_pbo(ctx, packing); 526 527 if (!validate_teximage(ctx, t, level, 0, 0, 0, 528 ti->Width, ti->Height, depth)) 529 /* It doesn't fit, mark it as dirty. */ 530 texture_dirty(t); 531 } 532 533 if (level == t->BaseLevel) { 534 if (!teximage_fits(t, level)) 535 relayout_texture(ctx, t); 536 nouveau_texture_validate(ctx, t); 537 } 538 539 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); 540 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); 541 } 542 543 544 static void 545 nouveau_teximage_123d(struct gl_context *ctx, GLuint dims, 546 struct gl_texture_image *ti, 547 GLenum format, GLenum type, const GLvoid *pixels, 548 const struct gl_pixelstore_attrib *packing) 549 { 550 nouveau_teximage(ctx, dims, ti, 0, format, type, pixels, 551 packing, GL_FALSE); 552 } 553 554 static void 555 nouveau_compressed_teximage(struct gl_context *ctx, GLuint dims, 556 struct gl_texture_image *ti, 557 GLsizei imageSize, const GLvoid *data) 558 { 559 nouveau_teximage(ctx, 2, ti, imageSize, 0, 0, data, 560 &ctx->Unpack, GL_TRUE); 561 } 562 563 static void 564 nouveau_texsubimage(struct gl_context *ctx, GLint dims, 565 struct gl_texture_image *ti, 566 GLint xoffset, GLint yoffset, GLint zoffset, 567 GLint width, GLint height, GLint depth, 568 GLsizei imageSize, 569 GLenum format, GLenum type, const void *pixels, 570 const struct gl_pixelstore_attrib *packing, 571 GLboolean compressed) 572 { 573 struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; 574 struct nouveau_teximage *nti = to_nouveau_teximage(ti); 575 int ret; 576 577 if (compressed) 578 pixels = _mesa_validate_pbo_compressed_teximage(ctx, 579 imageSize, 580 pixels, packing, "glCompressedTexSubImage"); 581 else 582 pixels = _mesa_validate_pbo_teximage(ctx, 583 dims, width, height, depth, format, type, 584 pixels, packing, "glTexSubImage"); 585 586 if (pixels) { 587 nouveau_teximage_map(ctx, ti, GL_MAP_WRITE_BIT, 588 xoffset, yoffset, width, height); 589 590 ret = _mesa_texstore(ctx, dims, ti->_BaseFormat, ti->TexFormat, 591 s->pitch, 592 &nti->base.Map, 593 width, height, depth, 594 format, type, pixels, packing); 595 assert(ret); 596 597 nouveau_teximage_unmap(ctx, ti); 598 _mesa_unmap_teximage_pbo(ctx, packing); 599 } 600 601 if (!to_nouveau_texture(ti->TexObject)->dirty) 602 validate_teximage(ctx, ti->TexObject, ti->Level, 603 xoffset, yoffset, zoffset, 604 width, height, depth); 605 } 606 607 static void 608 nouveau_texsubimage_123d(struct gl_context *ctx, GLuint dims, 609 struct gl_texture_image *ti, 610 GLint xoffset, GLint yoffset, GLint zoffset, 611 GLint width, GLint height, GLint depth, 612 GLenum format, GLenum type, const void *pixels, 613 const struct gl_pixelstore_attrib *packing) 614 { 615 nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset, 616 width, height, depth, 0, format, type, pixels, 617 packing, GL_FALSE); 618 } 619 620 static void 621 nouveau_compressed_texsubimage(struct gl_context *ctx, GLuint dims, 622 struct gl_texture_image *ti, 623 GLint xoffset, GLint yoffset, GLint zoffset, 624 GLsizei width, GLint height, GLint depth, 625 GLenum format, 626 GLint imageSize, const void *data) 627 { 628 nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset, 629 width, height, depth, imageSize, format, 0, data, 630 &ctx->Unpack, GL_TRUE); 631 } 632 633 static void 634 nouveau_bind_texture(struct gl_context *ctx, GLenum target, 635 struct gl_texture_object *t) 636 { 637 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); 638 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); 639 } 640 641 static gl_format 642 get_texbuffer_format(struct gl_renderbuffer *rb, GLint format) 643 { 644 struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; 645 646 if (s->cpp < 4) 647 return s->format; 648 else if (format == __DRI_TEXTURE_FORMAT_RGBA) 649 return MESA_FORMAT_ARGB8888; 650 else 651 return MESA_FORMAT_XRGB8888; 652 } 653 654 void 655 nouveau_set_texbuffer(__DRIcontext *dri_ctx, 656 GLint target, GLint format, 657 __DRIdrawable *draw) 658 { 659 struct nouveau_context *nctx = dri_ctx->driverPrivate; 660 struct gl_context *ctx = &nctx->base; 661 struct gl_framebuffer *fb = draw->driverPrivate; 662 struct gl_renderbuffer *rb = 663 fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; 664 struct gl_texture_object *t = _mesa_get_current_tex_object(ctx, target); 665 struct gl_texture_image *ti; 666 struct nouveau_teximage *nti; 667 struct nouveau_surface *s; 668 669 _mesa_lock_texture(ctx, t); 670 ti = _mesa_get_tex_image(ctx, t, target, 0); 671 nti = to_nouveau_teximage(ti); 672 s = &to_nouveau_teximage(ti)->surface; 673 674 /* Update the texture surface with the given drawable. */ 675 nouveau_update_renderbuffers(dri_ctx, draw); 676 nouveau_surface_ref(&to_nouveau_renderbuffer(rb)->surface, s); 677 678 s->format = get_texbuffer_format(rb, format); 679 680 /* Update the image fields. */ 681 _mesa_init_teximage_fields(ctx, ti, s->width, s->height, 682 1, 0, s->cpp, s->format); 683 nti->base.RowStride = s->pitch / s->cpp; 684 685 /* Try to validate it. */ 686 if (!validate_teximage(ctx, t, 0, 0, 0, 0, s->width, s->height, 1)) 687 nouveau_texture_reallocate(ctx, t); 688 689 context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); 690 context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); 691 692 _mesa_unlock_texture(ctx, t); 693 } 694 695 void 696 nouveau_texture_functions_init(struct dd_function_table *functions) 697 { 698 functions->NewTextureObject = nouveau_texture_new; 699 functions->DeleteTexture = nouveau_texture_free; 700 functions->NewTextureImage = nouveau_teximage_new; 701 functions->FreeTextureImageBuffer = nouveau_teximage_free; 702 functions->ChooseTextureFormat = nouveau_choose_tex_format; 703 functions->TexImage = nouveau_teximage_123d; 704 functions->TexSubImage = nouveau_texsubimage_123d; 705 functions->CompressedTexImage = nouveau_compressed_teximage; 706 functions->CompressedTexSubImage = nouveau_compressed_texsubimage; 707 functions->BindTexture = nouveau_bind_texture; 708 functions->MapTextureImage = nouveau_map_texture_image; 709 functions->UnmapTextureImage = nouveau_unmap_texture_image; 710 } 711