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
delete_texture_wrapper(struct gl_context * ctx,struct gl_renderbuffer * rb)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
wrap_texture(struct gl_context * ctx,struct gl_renderbuffer_attachment * att)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
update_wrapper(struct gl_context * ctx,struct gl_renderbuffer_attachment * att)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
_swrast_render_texture(struct gl_context * ctx,struct gl_framebuffer * fb,struct gl_renderbuffer_attachment * att)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
_swrast_finish_render_texture(struct gl_context * ctx,struct gl_renderbuffer_attachment * att)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