New st_init_*_functions() to initialize the driver functions table.
[mesa.git] / src / mesa / state_tracker / st_cb_fbo.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29 /**
30 * Framebuffer/renderbuffer functions.
31 *
32 * \author Brian Paul
33 */
34
35
36 #include "main/imports.h"
37 #include "main/context.h"
38 #include "main/fbobject.h"
39 #include "main/framebuffer.h"
40 #include "main/renderbuffer.h"
41
42 #include "pipe/p_context.h"
43 #include "pipe/p_defines.h"
44 #include "st_context.h"
45 #include "st_cb_fbo.h"
46 #include "st_cb_teximage.h"
47
48
49 /**
50 * Derived renderbuffer class. Just need to add a pointer to the
51 * pipe surface.
52 */
53 struct st_renderbuffer
54 {
55 struct gl_renderbuffer Base;
56 struct pipe_surface *surface;
57 };
58
59
60 /**
61 * Cast wrapper.
62 */
63 static INLINE struct st_renderbuffer *
64 st_renderbuffer(struct gl_renderbuffer *rb)
65 {
66 return (struct st_renderbuffer *) rb;
67 }
68
69
70 struct pipe_format_info
71 {
72 GLuint format;
73 GLenum base_format;
74 GLubyte red_bits;
75 GLubyte green_bits;
76 GLubyte blue_bits;
77 GLubyte alpha_bits;
78 GLubyte luminance_bits;
79 GLubyte intensity_bits;
80 GLubyte depth_bits;
81 GLubyte stencil_bits;
82 GLubyte size; /**< in bytes */
83 };
84
85
86 /*
87 * XXX temporary here
88 */
89 static const struct pipe_format_info *
90 pipe_get_format_info(GLuint format)
91 {
92 static const struct pipe_format_info info[] = {
93 {
94 PIPE_FORMAT_U_R8_G8_B8_A8, /* format */
95 GL_RGBA, /* base_format */
96 4, 4, 4, 4, 0, 0, /* color bits */
97 0, 0, /* depth, stencil */
98 4 /* size in bytes */
99 },
100 {
101 PIPE_FORMAT_U_A8_R8_G8_B8,
102 GL_RGBA, /* base_format */
103 4, 4, 4, 4, 0, 0, /* color bits */
104 0, 0, /* depth, stencil */
105 4 /* size in bytes */
106 },
107 {
108 PIPE_FORMAT_U_A1_R5_G5_B5,
109 GL_RGBA, /* base_format */
110 5, 5, 5, 1, 0, 0, /* color bits */
111 0, 0, /* depth, stencil */
112 2 /* size in bytes */
113 },
114 {
115 PIPE_FORMAT_U_R5_G6_B5,
116 GL_RGBA, /* base_format */
117 5, 6, 5, 0, 0, 0, /* color bits */
118 0, 0, /* depth, stencil */
119 2 /* size in bytes */
120 },
121 /* XXX lots more */
122 {
123 PIPE_FORMAT_S8_Z24,
124 GL_DEPTH_STENCIL_EXT, /* base_format */
125 0, 0, 0, 0, 0, 0, /* color bits */
126 24, 8, /* depth, stencil */
127 4 /* size in bytes */
128 }
129 };
130 GLuint i;
131
132 for (i = 0; i < sizeof(info) / sizeof(info[0]); i++) {
133 if (info[i].format == format)
134 return info + i;
135 }
136 return NULL;
137 }
138
139
140 /**
141 * gl_renderbuffer::AllocStorage()
142 */
143 static GLboolean
144 st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
145 GLenum internalFormat,
146 GLuint width, GLuint height)
147 {
148 struct pipe_context *pipe = ctx->st->pipe;
149 struct st_renderbuffer *strb = st_renderbuffer(rb);
150 const GLuint pipeFormat
151 = st_choose_pipe_format(pipe, internalFormat, GL_NONE, GL_NONE);
152 const struct pipe_format_info *info = pipe_get_format_info(pipeFormat);
153 GLuint cpp, pitch;
154
155 if (!info)
156 return GL_FALSE;
157
158 strb->Base._ActualFormat = info->base_format;
159 strb->Base.DataType = GL_UNSIGNED_BYTE; /* XXX fix */
160 strb->Base.RedBits = info->red_bits;
161 strb->Base.GreenBits = info->green_bits;
162 strb->Base.BlueBits = info->blue_bits;
163 strb->Base.AlphaBits = info->alpha_bits;
164 strb->Base.DepthBits = info->depth_bits;
165 strb->Base.StencilBits = info->stencil_bits;
166
167 cpp = info->size;
168
169 if (!strb->surface) {
170 strb->surface = pipe->surface_alloc(pipe, pipeFormat);
171 if (!strb->surface)
172 return GL_FALSE;
173 }
174
175 /* free old region */
176 if (strb->surface->region) {
177 pipe->region_release(pipe, &strb->surface->region);
178 }
179
180 /* Choose a pitch to match hardware requirements:
181 */
182 pitch = ((cpp * width + 63) & ~63) / cpp; /* XXX fix: device-specific */
183
184 strb->surface->region = pipe->region_alloc(pipe, cpp, pitch, height);
185 if (!strb->surface->region)
186 return GL_FALSE; /* out of memory, try s/w buffer? */
187
188 ASSERT(strb->surface->region->buffer);
189
190 strb->Base.Width = strb->surface->width = width;
191 strb->Base.Height = strb->surface->height = height;
192
193 return GL_TRUE;
194 }
195
196
197 /**
198 * gl_renderbuffer::Delete()
199 */
200 static void
201 st_renderbuffer_delete(struct gl_renderbuffer *rb)
202 {
203 GET_CURRENT_CONTEXT(ctx);
204 struct pipe_context *pipe = ctx->st->pipe;
205 struct st_renderbuffer *strb = st_renderbuffer(rb);
206 ASSERT(strb);
207 if (strb && strb->surface) {
208 if (rb->surface->region) {
209 pipe->region_release(pipe, &strb->surface->region);
210 }
211 free(strb->surface);
212 }
213 free(strb);
214 }
215
216
217 /**
218 * gl_renderbuffer::GetPointer()
219 */
220 static void *
221 null_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
222 GLint x, GLint y)
223 {
224 /* By returning NULL we force all software rendering to go through
225 * the span routines.
226 */
227 assert(0); /* Should never get called with softpipe */
228 return NULL;
229 }
230
231
232 /**
233 * Called via ctx->Driver.NewFramebuffer()
234 */
235 static struct gl_framebuffer *
236 st_new_framebuffer(GLcontext *ctx, GLuint name)
237 {
238 /* XXX not sure we need to subclass gl_framebuffer for pipe */
239 return _mesa_new_framebuffer(ctx, name);
240 }
241
242
243 /**
244 * Called via ctx->Driver.NewRenderbuffer()
245 */
246 static struct gl_renderbuffer *
247 st_new_renderbuffer(GLcontext *ctx, GLuint name)
248 {
249 struct st_renderbuffer *strb = CALLOC_STRUCT(st_renderbuffer);
250 if (strb) {
251 _mesa_init_renderbuffer(&strb->Base, name);
252 strb->Base.Delete = st_renderbuffer_delete;
253 strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
254 strb->Base.GetPointer = null_get_pointer;
255 return &strb->Base;
256 }
257 return NULL;
258 }
259
260 /**
261 * Called via ctx->Driver.BindFramebufferEXT().
262 */
263 static void
264 st_bind_framebuffer(GLcontext *ctx, GLenum target,
265 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
266 {
267
268 }
269
270 /**
271 * Called by ctx->Driver.FramebufferRenderbuffer
272 */
273 static void
274 st_framebuffer_renderbuffer(GLcontext *ctx,
275 struct gl_framebuffer *fb,
276 GLenum attachment,
277 struct gl_renderbuffer *rb)
278 {
279 /* XXX no need for derivation? */
280 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
281 }
282
283
284 /**
285 * Called by ctx->Driver.RenderTexture
286 */
287 static void
288 st_render_texture(GLcontext *ctx,
289 struct gl_framebuffer *fb,
290 struct gl_renderbuffer_attachment *att)
291 {
292 struct st_context *st = ctx->st;
293 struct pipe_framebuffer_state framebuffer;
294 struct pipe_surface *texsurface;
295
296 texsurface = NULL; /* find the mipmap level, cube face, etc */
297
298 /*
299 * XXX basically like this... set the current color (or depth)
300 * drawing surface to be the given texture renderbuffer.
301 */
302 memset(&framebuffer, 0, sizeof(framebuffer));
303 framebuffer.num_cbufs = 1;
304 framebuffer.cbufs[0] = texsurface;
305
306 if (memcmp(&framebuffer, &st->state.framebuffer, sizeof(framebuffer)) != 0) {
307 st->state.framebuffer = framebuffer;
308 st->pipe->set_framebuffer_state( st->pipe, &framebuffer );
309 }
310 }
311
312
313 /**
314 * Called via ctx->Driver.FinishRenderTexture.
315 */
316 static void
317 st_finish_render_texture(GLcontext *ctx,
318 struct gl_renderbuffer_attachment *att)
319 {
320 /* restore drawing to normal framebuffer. may be a no-op */
321 }
322
323
324
325 void st_init_fbo_functions(struct dd_function_table *functions)
326 {
327 functions->NewFramebuffer = st_new_framebuffer;
328 functions->NewRenderbuffer = st_new_renderbuffer;
329 functions->BindFramebuffer = st_bind_framebuffer;
330 functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
331 functions->RenderTexture = st_render_texture;
332 functions->FinishRenderTexture = st_finish_render_texture;
333 /* no longer needed by core Mesa, drivers handle resizes...
334 functions->ResizeBuffers = st_resize_buffers;
335 */
336 }