1e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 2755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul#include "main/context.h" 3755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul#include "main/colormac.h" 4755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul#include "main/fbobject.h" 5755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul#include "main/macros.h" 6755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul#include "main/teximage.h" 7755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul#include "main/renderbuffer.h" 8755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul#include "swrast/swrast.h" 9a1661dc8957a35899d653e9fffd97f166c56be56Brian Paul#include "swrast/s_context.h" 10baeefef2c0445bfd717a3086fdd9b5bd5d9cb675Brian Paul#include "swrast/s_texfetch.h" 11e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 12e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 13e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul/* 14e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Render-to-texture code for GL_EXT_framebuffer_object 15e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul */ 16e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 17e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 18f0339f502cf96499bc5cac8c0611f76f3fd39461Brian Paulstatic void 199d4ab9a663d4088ec553edaae0eeafb746d2490dBrian Pauldelete_texture_wrapper(struct gl_context *ctx, struct gl_renderbuffer *rb) 20e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul{ 210e31e02aef4fe44b1196d0bf6e351250d9d8f68cBrian Paul ASSERT(rb->RefCount == 0); 2232f2fd1c5d6088692551c80352b7d6fa35b0cd09Kristian Høgsberg free(rb); 23e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul} 24e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 25e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 26e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul/** 27555478fed6240db06db364716d40ccfd235b466bBrian Paul * This function creates a renderbuffer object which wraps a texture image. 28555478fed6240db06db364716d40ccfd235b466bBrian Paul * The new renderbuffer is plugged into the given attachment point. 29555478fed6240db06db364716d40ccfd235b466bBrian Paul * This allows rendering into the texture as if it were a renderbuffer. 30e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul */ 31e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paulstatic void 32f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergwrap_texture(struct gl_context *ctx, struct gl_renderbuffer_attachment *att) 33e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul{ 34ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul struct gl_renderbuffer *rb; 35e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul const GLuint name = 0; 36e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 37e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul ASSERT(att->Type == GL_TEXTURE); 38e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul ASSERT(att->Renderbuffer == NULL); 39e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 40f2479530b8be3866c234ac759a7fa84e634dd1aaBrian Paul rb = ctx->Driver.NewRenderbuffer(ctx, name); 41ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul if (!rb) { 42e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture"); 43e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul return; 44e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul } 45e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 46555478fed6240db06db364716d40ccfd235b466bBrian Paul /* init base gl_renderbuffer fields */ 47ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul _mesa_init_renderbuffer(rb, name); 48555478fed6240db06db364716d40ccfd235b466bBrian Paul /* plug in our texture_renderbuffer-specific functions */ 49ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul rb->Delete = delete_texture_wrapper; 50ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul rb->AllocStorage = NULL; /* illegal! */ 51555478fed6240db06db364716d40ccfd235b466bBrian Paul 52555478fed6240db06db364716d40ccfd235b466bBrian Paul /* update attachment point */ 53ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul _mesa_reference_renderbuffer(&att->Renderbuffer, rb); 54555478fed6240db06db364716d40ccfd235b466bBrian Paul} 55555478fed6240db06db364716d40ccfd235b466bBrian Paul 56555478fed6240db06db364716d40ccfd235b466bBrian Paul/** 57555478fed6240db06db364716d40ccfd235b466bBrian Paul * Update the renderbuffer wrapper for rendering to a texture. 58555478fed6240db06db364716d40ccfd235b466bBrian Paul * For example, update the width, height of the RB based on the texture size, 59555478fed6240db06db364716d40ccfd235b466bBrian Paul * update the internal format info, etc. 60555478fed6240db06db364716d40ccfd235b466bBrian Paul */ 61555478fed6240db06db364716d40ccfd235b466bBrian Paulstatic void 62db0f9e701d59dcfcd3b50f4d245897692f27fec9Brian Paulupdate_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att) 63555478fed6240db06db364716d40ccfd235b466bBrian Paul{ 64ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul struct gl_renderbuffer *rb = att->Renderbuffer; 650c1862851f27c428a18ba5509636efcc2f0084f8Brian Paul struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); 66ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul struct swrast_texture_image *swImage; 67ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul gl_format format; 68ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul GLuint zOffset; 69555478fed6240db06db364716d40ccfd235b466bBrian Paul 70a9bcf751030895494fc098f8d0ff56b2496bd993Brian Paul (void) ctx; 71e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 72ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul swImage = swrast_texture_image(_mesa_get_attachment_teximage(att)); 73ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul assert(swImage); 74e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 75ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul format = swImage->Base.TexFormat; 76a988ddf3798e0ec568704e4a72b46030079c7e45Dave Airlie 77bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) { 78ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul zOffset = 0; 79bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick } 80bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick else { 81ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul zOffset = att->Zoffset; 82bb372f1c9bc08e8b0dca983cb4ba36b2f2f039fbIan Romanick } 83e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 84ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul rb->Width = swImage->Base.Width; 85ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul rb->Height = swImage->Base.Height; 86ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul rb->InternalFormat = swImage->Base.InternalFormat; 87ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul rb->_BaseFormat = _mesa_get_format_base_format(format); 88ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul 89ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul /* Want to store linear values, not sRGB */ 90ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul rb->Format = _mesa_get_srgb_format_linear(format); 91ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul 92ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul /* Set the gl_renderbuffer::Buffer field so that mapping the buffer 93ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul * succeeds. 94ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul */ 956dbf2bac5043564f32cdad08e8d6220618a02080Brian Paul if (att->Texture->Target == GL_TEXTURE_3D || 966dbf2bac5043564f32cdad08e8d6220618a02080Brian Paul att->Texture->Target == GL_TEXTURE_2D_ARRAY_EXT) { 970c1862851f27c428a18ba5509636efcc2f0084f8Brian Paul srb->Buffer = swImage->Buffer + 98ab331140c68d1c157e69ea8e53b44729355fa43cBrian Paul swImage->ImageOffsets[zOffset] * _mesa_get_format_bytes(format); 996dbf2bac5043564f32cdad08e8d6220618a02080Brian Paul } 1006dbf2bac5043564f32cdad08e8d6220618a02080Brian Paul else { 1010c1862851f27c428a18ba5509636efcc2f0084f8Brian Paul srb->Buffer = swImage->Buffer; 102555478fed6240db06db364716d40ccfd235b466bBrian Paul } 103e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul} 104e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 105e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 106e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 107e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul/** 108ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul * Called when rendering to a texture image begins, or when changing 109ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul * the dest mipmap level, cube face, etc. 110519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul * This is a fallback routine for software render-to-texture. 111519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul * 112519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul * Called via the glRenderbufferTexture1D/2D/3D() functions 113519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul * and elsewhere (such as glTexImage2D). 114519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul * 115519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul * The image we're rendering into is 116519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul * att->Texture->Image[att->CubeMapFace][att->TextureLevel]; 117519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul * It'll never be NULL. 118519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul * 119519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul * \param fb the framebuffer object the texture is being bound to 120519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul * \param att the fb attachment point of the texture 121519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul * 122e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * \sa _mesa_framebuffer_renderbuffer 123e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul */ 124e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paulvoid 125755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul_swrast_render_texture(struct gl_context *ctx, 126755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul struct gl_framebuffer *fb, 127755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul struct gl_renderbuffer_attachment *att) 128e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul{ 129a9bcf751030895494fc098f8d0ff56b2496bd993Brian Paul (void) fb; 130a9bcf751030895494fc098f8d0ff56b2496bd993Brian Paul 131555478fed6240db06db364716d40ccfd235b466bBrian Paul if (!att->Renderbuffer) { 132519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul wrap_texture(ctx, att); 133e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul } 134555478fed6240db06db364716d40ccfd235b466bBrian Paul update_wrapper(ctx, att); 135e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul} 136519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul 137519b23b21f9cd6945fd17cdb26e7a6f531cdeec0Brian Paul 138ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paulvoid 139755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul_swrast_finish_render_texture(struct gl_context *ctx, 140755f2e2ae597df9208523b0996bbdabf3db463b0Brian Paul struct gl_renderbuffer_attachment *att) 141ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul{ 142ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul /* do nothing */ 143ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul /* The renderbuffer texture wrapper will get deleted by the 144ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul * normal mechanism for deleting renderbuffers. 145ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul */ 146a9bcf751030895494fc098f8d0ff56b2496bd993Brian Paul (void) ctx; 147a9bcf751030895494fc098f8d0ff56b2496bd993Brian Paul (void) att; 148ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul} 149