7b25a7b7d81b1d4edd6bf0794f15c98de9c6ae93
[mesa.git] / src / mesa / swrast / s_texrender.c
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 }