s_texrender.c revision 3464ebd5
1 2#include "main/context.h" 3#include "main/colormac.h" 4#include "main/fbobject.h" 5#include "main/macros.h" 6#include "main/texfetch.h" 7#include "main/teximage.h" 8#include "main/renderbuffer.h" 9#include "swrast/swrast.h" 10 11 12/* 13 * Render-to-texture code for GL_EXT_framebuffer_object 14 */ 15 16 17/** 18 * Derived from gl_renderbuffer class 19 */ 20struct texture_renderbuffer 21{ 22 struct gl_renderbuffer Base; /**< Base class object */ 23 struct gl_texture_image *TexImage; 24 StoreTexelFunc Store; 25 FetchTexelFuncF Fetchf; 26 GLint Yoffset; /**< Layer for 1D array textures. */ 27 GLint Zoffset; /**< Layer for 2D array textures, or slice 28 * for 3D textures 29 */ 30}; 31 32 33/** 34 * Get row of values from the renderbuffer that wraps a texture image. 35 */ 36static void 37texture_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 38 GLint x, GLint y, void *values) 39{ 40 const struct texture_renderbuffer *trb 41 = (const struct texture_renderbuffer *) rb; 42 const GLint z = trb->Zoffset; 43 GLuint i; 44 45 ASSERT(trb->TexImage->Width == rb->Width); 46 ASSERT(trb->TexImage->Height == rb->Height); 47 48 y += trb->Yoffset; 49 50 if (rb->DataType == CHAN_TYPE) { 51 GLchan *rgbaOut = (GLchan *) values; 52 for (i = 0; i < count; i++) { 53 GLfloat rgba[4]; 54 trb->Fetchf(trb->TexImage, x + i, y, z, rgba); 55 UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut + 4 * i, rgba); 56 } 57 } 58 else if (rb->DataType == GL_UNSIGNED_SHORT) { 59 GLushort *zValues = (GLushort *) values; 60 for (i = 0; i < count; i++) { 61 GLfloat flt; 62 trb->Fetchf(trb->TexImage, x + i, y, z, &flt); 63 zValues[i] = (GLushort) (flt * 0xffff); 64 } 65 } 66 else if (rb->DataType == GL_UNSIGNED_INT) { 67 GLuint *zValues = (GLuint *) values; 68 /* 69 const GLdouble scale = (GLdouble) 0xffffffff; 70 */ 71 for (i = 0; i < count; i++) { 72 GLfloat flt; 73 trb->Fetchf(trb->TexImage, x + i, y, z, &flt); 74#if 0 75 /* this should work, but doesn't (overflow due to low precision) */ 76 zValues[i] = (GLuint) (flt * scale); 77#else 78 /* temporary hack */ 79 zValues[i] = ((GLuint) (flt * 0xffffff)) << 8; 80#endif 81 } 82 } 83 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { 84 GLuint *zValues = (GLuint *) values; 85 for (i = 0; i < count; i++) { 86 GLfloat flt; 87 trb->Fetchf(trb->TexImage, x + i, y, z, &flt); 88 zValues[i] = ((GLuint) (flt * 0xffffff)) << 8; 89 } 90 } 91 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) { 92 GLuint *zValues = (GLuint *) values; 93 for (i = 0; i < count; i++) { 94 GLfloat flt; 95 trb->Fetchf(trb->TexImage, x + i, y, z, &flt); 96 zValues[i] = (GLuint) (flt * 0xffffff); 97 } 98 } 99 else { 100 _mesa_problem(ctx, "invalid rb->DataType in texture_get_row"); 101 } 102} 103 104 105static void 106texture_get_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 107 const GLint x[], const GLint y[], void *values) 108{ 109 const struct texture_renderbuffer *trb 110 = (const struct texture_renderbuffer *) rb; 111 const GLint z = trb->Zoffset; 112 GLuint i; 113 114 if (rb->DataType == CHAN_TYPE) { 115 GLchan *rgbaOut = (GLchan *) values; 116 for (i = 0; i < count; i++) { 117 GLfloat rgba[4]; 118 trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset, 119 z, rgba); 120 UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut + 4 * i, rgba); 121 } 122 } 123 else if (rb->DataType == GL_UNSIGNED_SHORT) { 124 GLushort *zValues = (GLushort *) values; 125 for (i = 0; i < count; i++) { 126 GLfloat flt; 127 trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset, 128 z, &flt); 129 zValues[i] = (GLushort) (flt * 0xffff); 130 } 131 } 132 else if (rb->DataType == GL_UNSIGNED_INT) { 133 GLuint *zValues = (GLuint *) values; 134 for (i = 0; i < count; i++) { 135 GLfloat flt; 136 trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset, 137 z, &flt); 138#if 0 139 zValues[i] = (GLuint) (flt * 0xffffffff); 140#else 141 zValues[i] = ((GLuint) (flt * 0xffffff)) << 8; 142#endif 143 } 144 } 145 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { 146 GLuint *zValues = (GLuint *) values; 147 for (i = 0; i < count; i++) { 148 GLfloat flt; 149 trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset, 150 z, &flt); 151 zValues[i] = ((GLuint) (flt * 0xffffff)) << 8; 152 } 153 } 154 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) { 155 GLuint *zValues = (GLuint *) values; 156 for (i = 0; i < count; i++) { 157 GLfloat flt; 158 trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset, 159 z, &flt); 160 zValues[i] = (GLuint) (flt * 0xffffff); 161 } 162 } 163 else { 164 _mesa_problem(ctx, "invalid rb->DataType in texture_get_values"); 165 } 166} 167 168 169/** 170 * Put row of values into a renderbuffer that wraps a texture image. 171 */ 172static void 173texture_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 174 GLint x, GLint y, const void *values, const GLubyte *mask) 175{ 176 const struct texture_renderbuffer *trb 177 = (const struct texture_renderbuffer *) rb; 178 const GLint z = trb->Zoffset; 179 GLuint i; 180 181 y += trb->Yoffset; 182 183 if (rb->DataType == CHAN_TYPE) { 184 const GLchan *rgba = (const GLchan *) values; 185 for (i = 0; i < count; i++) { 186 if (!mask || mask[i]) { 187 trb->Store(trb->TexImage, x + i, y, z, rgba); 188 } 189 rgba += 4; 190 } 191 } 192 else if (rb->DataType == GL_UNSIGNED_SHORT) { 193 const GLushort *zValues = (const GLushort *) values; 194 for (i = 0; i < count; i++) { 195 if (!mask || mask[i]) { 196 trb->Store(trb->TexImage, x + i, y, z, zValues + i); 197 } 198 } 199 } 200 else if (rb->DataType == GL_UNSIGNED_INT) { 201 const GLuint *zValues = (const GLuint *) values; 202 for (i = 0; i < count; i++) { 203 if (!mask || mask[i]) { 204 trb->Store(trb->TexImage, x + i, y, z, zValues + i); 205 } 206 } 207 } 208 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { 209 const GLuint *zValues = (const GLuint *) values; 210 for (i = 0; i < count; i++) { 211 if (!mask || mask[i]) { 212 GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff)); 213 trb->Store(trb->TexImage, x + i, y, z, &flt); 214 } 215 } 216 } 217 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) { 218 const GLuint *zValues = (const GLuint *) values; 219 for (i = 0; i < count; i++) { 220 if (!mask || mask[i]) { 221 GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff)); 222 trb->Store(trb->TexImage, x + i, y, z, &flt); 223 } 224 } 225 } 226 else { 227 _mesa_problem(ctx, "invalid rb->DataType in texture_put_row"); 228 } 229} 230 231/** 232 * Put row of RGB values into a renderbuffer that wraps a texture image. 233 */ 234static void 235texture_put_row_rgb(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 236 GLint x, GLint y, const void *values, const GLubyte *mask) 237{ 238 const struct texture_renderbuffer *trb 239 = (const struct texture_renderbuffer *) rb; 240 const GLint z = trb->Zoffset; 241 GLuint i; 242 243 y += trb->Yoffset; 244 245 if (rb->DataType == CHAN_TYPE) { 246 const GLchan *rgb = (const GLchan *) values; 247 for (i = 0; i < count; i++) { 248 if (!mask || mask[i]) { 249 trb->Store(trb->TexImage, x + i, y, z, rgb); 250 } 251 rgb += 3; 252 } 253 } 254 else if (rb->DataType == GL_UNSIGNED_SHORT) { 255 const GLushort *zValues = (const GLushort *) values; 256 for (i = 0; i < count; i++) { 257 if (!mask || mask[i]) { 258 trb->Store(trb->TexImage, x + i, y, z, zValues + i); 259 } 260 } 261 } 262 else if (rb->DataType == GL_UNSIGNED_INT) { 263 const GLuint *zValues = (const GLuint *) values; 264 for (i = 0; i < count; i++) { 265 if (!mask || mask[i]) { 266 trb->Store(trb->TexImage, x + i, y, z, zValues + i); 267 } 268 } 269 } 270 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { 271 const GLuint *zValues = (const GLuint *) values; 272 for (i = 0; i < count; i++) { 273 if (!mask || mask[i]) { 274 GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff)); 275 trb->Store(trb->TexImage, x + i, y, z, &flt); 276 } 277 } 278 } 279 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) { 280 const GLuint *zValues = (const GLuint *) values; 281 for (i = 0; i < count; i++) { 282 if (!mask || mask[i]) { 283 GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff)); 284 trb->Store(trb->TexImage, x + i, y, z, &flt); 285 } 286 } 287 } 288 else { 289 _mesa_problem(ctx, "invalid rb->DataType in texture_put_row"); 290 } 291} 292 293 294static void 295texture_put_mono_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 296 GLint x, GLint y, const void *value, const GLubyte *mask) 297{ 298 const struct texture_renderbuffer *trb 299 = (const struct texture_renderbuffer *) rb; 300 const GLint z = trb->Zoffset; 301 GLuint i; 302 303 y += trb->Yoffset; 304 305 if (rb->DataType == CHAN_TYPE) { 306 const GLchan *rgba = (const GLchan *) value; 307 for (i = 0; i < count; i++) { 308 if (!mask || mask[i]) { 309 trb->Store(trb->TexImage, x + i, y, z, rgba); 310 } 311 } 312 } 313 else if (rb->DataType == GL_UNSIGNED_SHORT) { 314 const GLushort zValue = *((const GLushort *) value); 315 for (i = 0; i < count; i++) { 316 if (!mask || mask[i]) { 317 trb->Store(trb->TexImage, x + i, y, z, &zValue); 318 } 319 } 320 } 321 else if (rb->DataType == GL_UNSIGNED_INT) { 322 const GLuint zValue = *((const GLuint *) value); 323 for (i = 0; i < count; i++) { 324 if (!mask || mask[i]) { 325 trb->Store(trb->TexImage, x + i, y, z, &zValue); 326 } 327 } 328 } 329 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { 330 const GLuint zValue = *((const GLuint *) value); 331 const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff)); 332 for (i = 0; i < count; i++) { 333 if (!mask || mask[i]) { 334 trb->Store(trb->TexImage, x + i, y, z, &flt); 335 } 336 } 337 } 338 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) { 339 const GLuint zValue = *((const GLuint *) value); 340 const GLfloat flt = (GLfloat) ((zValue & 0xffffff) * (1.0 / 0xffffff)); 341 for (i = 0; i < count; i++) { 342 if (!mask || mask[i]) { 343 trb->Store(trb->TexImage, x + i, y, z, &flt); 344 } 345 } 346 } 347 else { 348 _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_row"); 349 } 350} 351 352 353static void 354texture_put_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count, 355 const GLint x[], const GLint y[], const void *values, 356 const GLubyte *mask) 357{ 358 const struct texture_renderbuffer *trb 359 = (const struct texture_renderbuffer *) rb; 360 const GLint z = trb->Zoffset; 361 GLuint i; 362 363 if (rb->DataType == CHAN_TYPE) { 364 const GLchan *rgba = (const GLchan *) values; 365 for (i = 0; i < count; i++) { 366 if (!mask || mask[i]) { 367 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba); 368 } 369 rgba += 4; 370 } 371 } 372 else if (rb->DataType == GL_UNSIGNED_SHORT) { 373 const GLushort *zValues = (const GLushort *) values; 374 for (i = 0; i < count; i++) { 375 if (!mask || mask[i]) { 376 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, zValues + i); 377 } 378 } 379 } 380 else if (rb->DataType == GL_UNSIGNED_INT) { 381 const GLuint *zValues = (const GLuint *) values; 382 for (i = 0; i < count; i++) { 383 if (!mask || mask[i]) { 384 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, zValues + i); 385 } 386 } 387 } 388 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { 389 const GLuint *zValues = (const GLuint *) values; 390 for (i = 0; i < count; i++) { 391 if (!mask || mask[i]) { 392 GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff)); 393 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt); 394 } 395 } 396 } 397 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) { 398 const GLuint *zValues = (const GLuint *) values; 399 for (i = 0; i < count; i++) { 400 if (!mask || mask[i]) { 401 GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff)); 402 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt); 403 } 404 } 405 } 406 else { 407 _mesa_problem(ctx, "invalid rb->DataType in texture_put_values"); 408 } 409} 410 411 412static void 413texture_put_mono_values(struct gl_context *ctx, struct gl_renderbuffer *rb, 414 GLuint count, const GLint x[], const GLint y[], 415 const void *value, const GLubyte *mask) 416{ 417 const struct texture_renderbuffer *trb 418 = (const struct texture_renderbuffer *) rb; 419 const GLint z = trb->Zoffset; 420 GLuint i; 421 422 if (rb->DataType == CHAN_TYPE) { 423 const GLchan *rgba = (const GLchan *) value; 424 for (i = 0; i < count; i++) { 425 if (!mask || mask[i]) { 426 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba); 427 } 428 } 429 } 430 else if (rb->DataType == GL_UNSIGNED_INT) { 431 const GLuint zValue = *((const GLuint *) value); 432 for (i = 0; i < count; i++) { 433 if (!mask || mask[i]) { 434 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue); 435 } 436 } 437 } 438 else if (rb->DataType == GL_UNSIGNED_SHORT) { 439 const GLushort zValue = *((const GLushort *) value); 440 for (i = 0; i < count; i++) { 441 if (!mask || mask[i]) { 442 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue); 443 } 444 } 445 } 446 else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) { 447 const GLuint zValue = *((const GLuint *) value); 448 const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff)); 449 for (i = 0; i < count; i++) { 450 if (!mask || mask[i]) { 451 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt); 452 } 453 } 454 } 455 else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) { 456 const GLuint zValue = *((const GLuint *) value); 457 const GLfloat flt = (GLfloat) ((zValue & 0xffffff) * (1.0 / 0xffffff)); 458 for (i = 0; i < count; i++) { 459 if (!mask || mask[i]) { 460 trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt); 461 } 462 } 463 } 464 else { 465 _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_values"); 466 } 467} 468 469 470static void 471store_nop(struct gl_texture_image *texImage, 472 GLint col, GLint row, GLint img, 473 const void *texel) 474{ 475} 476 477 478static void 479delete_texture_wrapper(struct gl_renderbuffer *rb) 480{ 481 ASSERT(rb->RefCount == 0); 482 free(rb); 483} 484 485 486/** 487 * This function creates a renderbuffer object which wraps a texture image. 488 * The new renderbuffer is plugged into the given attachment point. 489 * This allows rendering into the texture as if it were a renderbuffer. 490 */ 491static void 492wrap_texture(struct gl_context *ctx, struct gl_renderbuffer_attachment *att) 493{ 494 struct texture_renderbuffer *trb; 495 const GLuint name = 0; 496 497 ASSERT(att->Type == GL_TEXTURE); 498 ASSERT(att->Renderbuffer == NULL); 499 500 trb = CALLOC_STRUCT(texture_renderbuffer); 501 if (!trb) { 502 _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture"); 503 return; 504 } 505 506 /* init base gl_renderbuffer fields */ 507 _mesa_init_renderbuffer(&trb->Base, name); 508 /* plug in our texture_renderbuffer-specific functions */ 509 trb->Base.Delete = delete_texture_wrapper; 510 trb->Base.AllocStorage = NULL; /* illegal! */ 511 trb->Base.GetRow = texture_get_row; 512 trb->Base.GetValues = texture_get_values; 513 trb->Base.PutRow = texture_put_row; 514 trb->Base.PutRowRGB = texture_put_row_rgb; 515 trb->Base.PutMonoRow = texture_put_mono_row; 516 trb->Base.PutValues = texture_put_values; 517 trb->Base.PutMonoValues = texture_put_mono_values; 518 519 /* update attachment point */ 520 _mesa_reference_renderbuffer(&att->Renderbuffer, &(trb->Base)); 521} 522 523/** 524 * Update the renderbuffer wrapper for rendering to a texture. 525 * For example, update the width, height of the RB based on the texture size, 526 * update the internal format info, etc. 527 */ 528static void 529update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att) 530{ 531 struct texture_renderbuffer *trb 532 = (struct texture_renderbuffer *) att->Renderbuffer; 533 534 (void) ctx; 535 ASSERT(trb); 536 537 trb->TexImage = _mesa_get_attachment_teximage(att); 538 ASSERT(trb->TexImage); 539 540 trb->Store = _mesa_get_texel_store_func(trb->TexImage->TexFormat); 541 if (!trb->Store) { 542 /* we'll never draw into some textures (compressed formats) */ 543 trb->Store = store_nop; 544 } 545 546 trb->Fetchf = trb->TexImage->FetchTexelf; 547 548 if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) { 549 trb->Yoffset = att->Zoffset; 550 trb->Zoffset = 0; 551 } 552 else { 553 trb->Yoffset = 0; 554 trb->Zoffset = att->Zoffset; 555 } 556 557 trb->Base.Width = trb->TexImage->Width; 558 trb->Base.Height = trb->TexImage->Height; 559 trb->Base.InternalFormat = trb->TexImage->InternalFormat; 560 trb->Base.Format = trb->TexImage->TexFormat; 561 562 /* XXX may need more special cases here */ 563 switch (trb->TexImage->TexFormat) { 564 case MESA_FORMAT_Z24_S8: 565 trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT; 566 trb->Base._BaseFormat = GL_DEPTH_STENCIL; 567 break; 568 case MESA_FORMAT_S8_Z24: 569 trb->Base.DataType = GL_UNSIGNED_INT_8_24_REV_MESA; 570 trb->Base._BaseFormat = GL_DEPTH_STENCIL; 571 break; 572 case MESA_FORMAT_Z24_X8: 573 trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT; 574 trb->Base._BaseFormat = GL_DEPTH_COMPONENT; 575 break; 576 case MESA_FORMAT_X8_Z24: 577 trb->Base.DataType = GL_UNSIGNED_INT_8_24_REV_MESA; 578 trb->Base._BaseFormat = GL_DEPTH_COMPONENT; 579 break; 580 case MESA_FORMAT_Z16: 581 trb->Base.DataType = GL_UNSIGNED_SHORT; 582 trb->Base._BaseFormat = GL_DEPTH_COMPONENT; 583 break; 584 case MESA_FORMAT_Z32: 585 trb->Base.DataType = GL_UNSIGNED_INT; 586 trb->Base._BaseFormat = GL_DEPTH_COMPONENT; 587 break; 588 /* SRGB formats pre EXT_framebuffer_sRGB don't do sRGB translations on FBO readback */ 589 case MESA_FORMAT_SRGB8: 590 trb->Fetchf = _mesa_get_texel_fetch_func(MESA_FORMAT_RGB888, _mesa_get_texture_dimensions(att->Texture->Target)); 591 trb->Base.DataType = CHAN_TYPE; 592 trb->Base._BaseFormat = GL_RGBA; 593 break; 594 case MESA_FORMAT_SRGBA8: 595 trb->Fetchf = _mesa_get_texel_fetch_func(MESA_FORMAT_RGBA8888, _mesa_get_texture_dimensions(att->Texture->Target)); 596 trb->Base.DataType = CHAN_TYPE; 597 trb->Base._BaseFormat = GL_RGBA; 598 break; 599 case MESA_FORMAT_SARGB8: 600 trb->Fetchf = _mesa_get_texel_fetch_func(MESA_FORMAT_ARGB8888, _mesa_get_texture_dimensions(att->Texture->Target)); 601 trb->Base.DataType = CHAN_TYPE; 602 trb->Base._BaseFormat = GL_RGBA; 603 break; 604 default: 605 trb->Base.DataType = CHAN_TYPE; 606 trb->Base._BaseFormat = GL_RGBA; 607 } 608 trb->Base.Data = trb->TexImage->Data; 609} 610 611 612 613/** 614 * Called when rendering to a texture image begins, or when changing 615 * the dest mipmap level, cube face, etc. 616 * This is a fallback routine for software render-to-texture. 617 * 618 * Called via the glRenderbufferTexture1D/2D/3D() functions 619 * and elsewhere (such as glTexImage2D). 620 * 621 * The image we're rendering into is 622 * att->Texture->Image[att->CubeMapFace][att->TextureLevel]; 623 * It'll never be NULL. 624 * 625 * \param fb the framebuffer object the texture is being bound to 626 * \param att the fb attachment point of the texture 627 * 628 * \sa _mesa_framebuffer_renderbuffer 629 */ 630void 631_swrast_render_texture(struct gl_context *ctx, 632 struct gl_framebuffer *fb, 633 struct gl_renderbuffer_attachment *att) 634{ 635 (void) fb; 636 637 if (!att->Renderbuffer) { 638 wrap_texture(ctx, att); 639 } 640 update_wrapper(ctx, att); 641} 642 643 644void 645_swrast_finish_render_texture(struct gl_context *ctx, 646 struct gl_renderbuffer_attachment *att) 647{ 648 /* do nothing */ 649 /* The renderbuffer texture wrapper will get deleted by the 650 * normal mechanism for deleting renderbuffers. 651 */ 652 (void) ctx; 653 (void) att; 654} 655