1 2 #include "main/context.h" 3 #include "main/colormac.h" 4 #include "main/fbobject.h" 5 #include "main/macros.h" 6 #include "main/teximage.h" 7 #include "main/renderbuffer.h" 8 #include "swrast/swrast.h" 9 #include "swrast/s_context.h" 10 #include "swrast/s_texfetch.h" 11 12 13 /* 14 * Render-to-texture code for GL_EXT_framebuffer_object 15 */ 16 17 18 static void 19 delete_texture_wrapper(struct gl_context *ctx, struct gl_renderbuffer *rb) 20 { 21 ASSERT(rb->RefCount == 0); 22 free(rb); 23 } 24 25 26 /** 27 * This function creates a renderbuffer object which wraps a texture image. 28 * The new renderbuffer is plugged into the given attachment point. 29 * This allows rendering into the texture as if it were a renderbuffer. 30 */ 31 static void 32 wrap_texture(struct gl_context *ctx, struct gl_renderbuffer_attachment *att) 33 { 34 struct gl_renderbuffer *rb; 35 const GLuint name = 0; 36 37 ASSERT(att->Type == GL_TEXTURE); 38 ASSERT(att->Renderbuffer == NULL); 39 40 rb = ctx->Driver.NewRenderbuffer(ctx, name); 41 if (!rb) { 42 _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture"); 43 return; 44 } 45 46 /* init base gl_renderbuffer fields */ 47 _mesa_init_renderbuffer(rb, name); 48 /* plug in our texture_renderbuffer-specific functions */ 49 rb->Delete = delete_texture_wrapper; 50 rb->AllocStorage = NULL; /* illegal! */ 51 52 /* update attachment point */ 53 _mesa_reference_renderbuffer(&att->Renderbuffer, rb); 54 } 55 56 /** 57 * Update the renderbuffer wrapper for rendering to a texture. 58 * For example, update the width, height of the RB based on the texture size, 59 * update the internal format info, etc. 60 */ 61 static void 62 update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att) 63 { 64 struct gl_renderbuffer *rb = att->Renderbuffer; 65 struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); 66 struct swrast_texture_image *swImage; 67 gl_format format; 68 GLuint zOffset; 69 70 (void) ctx; 71 72 swImage = swrast_texture_image(_mesa_get_attachment_teximage(att)); 73 assert(swImage); 74 75 format = swImage->Base.TexFormat; 76 77 if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) { 78 zOffset = 0; 79 } 80 else { 81 zOffset = att->Zoffset; 82 } 83 84 rb->Width = swImage->Base.Width; 85 rb->Height = swImage->Base.Height; 86 rb->InternalFormat = swImage->Base.InternalFormat; 87 rb->_BaseFormat = _mesa_get_format_base_format(format); 88 89 /* Want to store linear values, not sRGB */ 90 rb->Format = _mesa_get_srgb_format_linear(format); 91 92 /* Set the gl_renderbuffer::Buffer field so that mapping the buffer 93 * succeeds. 94 */ 95 if (att->Texture->Target == GL_TEXTURE_3D || 96 att->Texture->Target == GL_TEXTURE_2D_ARRAY_EXT) { 97 srb->Buffer = swImage->Buffer + 98 swImage->ImageOffsets[zOffset] * _mesa_get_format_bytes(format); 99 } 100 else { 101 srb->Buffer = swImage->Buffer; 102 } 103 } 104 105 106 107 /** 108 * Called when rendering to a texture image begins, or when changing 109 * the dest mipmap level, cube face, etc. 110 * This is a fallback routine for software render-to-texture. 111 * 112 * Called via the glRenderbufferTexture1D/2D/3D() functions 113 * and elsewhere (such as glTexImage2D). 114 * 115 * The image we're rendering into is 116 * att->Texture->Image[att->CubeMapFace][att->TextureLevel]; 117 * It'll never be NULL. 118 * 119 * \param fb the framebuffer object the texture is being bound to 120 * \param att the fb attachment point of the texture 121 * 122 * \sa _mesa_framebuffer_renderbuffer 123 */ 124 void 125 _swrast_render_texture(struct gl_context *ctx, 126 struct gl_framebuffer *fb, 127 struct gl_renderbuffer_attachment *att) 128 { 129 (void) fb; 130 131 if (!att->Renderbuffer) { 132 wrap_texture(ctx, att); 133 } 134 update_wrapper(ctx, att); 135 } 136 137 138 void 139 _swrast_finish_render_texture(struct gl_context *ctx, 140 struct gl_renderbuffer_attachment *att) 141 { 142 /* do nothing */ 143 /* The renderbuffer texture wrapper will get deleted by the 144 * normal mechanism for deleting renderbuffers. 145 */ 146 (void) ctx; 147 (void) att; 148 } 149