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