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