init strb->Base.DataType appropriately, clean-ups
[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 struct pipe_format_info
50 {
51 GLuint format;
52 GLenum base_format;
53 GLubyte red_bits;
54 GLubyte green_bits;
55 GLubyte blue_bits;
56 GLubyte alpha_bits;
57 GLubyte luminance_bits;
58 GLubyte intensity_bits;
59 GLubyte depth_bits;
60 GLubyte stencil_bits;
61 GLubyte size; /**< in bytes */
62 };
63
64
65 /*
66 * XXX temporary here
67 */
68 static const struct pipe_format_info *
69 pipe_get_format_info(GLuint format)
70 {
71 static const struct pipe_format_info info[] = {
72 {
73 PIPE_FORMAT_U_R8_G8_B8_A8, /* format */
74 GL_RGBA, /* base_format */
75 8, 8, 8, 8, 0, 0, /* color bits */
76 0, 0, /* depth, stencil */
77 4 /* size in bytes */
78 },
79 {
80 PIPE_FORMAT_U_A8_R8_G8_B8,
81 GL_RGBA, /* base_format */
82 8, 8, 8, 8, 0, 0, /* color bits */
83 0, 0, /* depth, stencil */
84 4 /* size in bytes */
85 },
86 {
87 PIPE_FORMAT_U_A1_R5_G5_B5,
88 GL_RGBA, /* base_format */
89 5, 5, 5, 1, 0, 0, /* color bits */
90 0, 0, /* depth, stencil */
91 2 /* size in bytes */
92 },
93 {
94 PIPE_FORMAT_U_R5_G6_B5,
95 GL_RGBA, /* base_format */
96 5, 6, 5, 0, 0, 0, /* color bits */
97 0, 0, /* depth, stencil */
98 2 /* size in bytes */
99 },
100 /* XXX lots more */
101 {
102 PIPE_FORMAT_S8_Z24,
103 GL_DEPTH_STENCIL_EXT, /* base_format */
104 0, 0, 0, 0, 0, 0, /* color bits */
105 24, 8, /* depth, stencil */
106 4 /* size in bytes */
107 }
108 };
109 GLuint i;
110
111 for (i = 0; i < sizeof(info) / sizeof(info[0]); i++) {
112 if (info[i].format == format)
113 return info + i;
114 }
115 return NULL;
116 }
117
118
119 /**
120 * gl_renderbuffer::AllocStorage()
121 */
122 static GLboolean
123 st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
124 GLenum internalFormat,
125 GLuint width, GLuint height)
126 {
127 struct pipe_context *pipe = ctx->st->pipe;
128 struct st_renderbuffer *strb = st_renderbuffer(rb);
129 const GLuint pipeFormat
130 = st_choose_pipe_format(pipe, internalFormat, GL_NONE, GL_NONE);
131 const struct pipe_format_info *info = pipe_get_format_info(pipeFormat);
132 GLuint cpp, pitch;
133
134 assert(info);
135 if (!info)
136 return GL_FALSE;
137
138 switch (pipeFormat) {
139 case PIPE_FORMAT_S8_Z24:
140 strb->Base.DataType = GL_UNSIGNED_INT;
141 break;
142 default:
143 strb->Base.DataType = GL_UNSIGNED_BYTE; /* XXX fix */
144 }
145
146 strb->Base._ActualFormat = info->base_format;
147 strb->Base.RedBits = info->red_bits;
148 strb->Base.GreenBits = info->green_bits;
149 strb->Base.BlueBits = info->blue_bits;
150 strb->Base.AlphaBits = info->alpha_bits;
151 strb->Base.DepthBits = info->depth_bits;
152 strb->Base.StencilBits = info->stencil_bits;
153
154 cpp = info->size;
155
156 if (!strb->surface) {
157 strb->surface = pipe->surface_alloc(pipe, pipeFormat);
158 assert(strb->surface);
159 if (!strb->surface)
160 return GL_FALSE;
161 }
162
163 /* free old region */
164 if (strb->surface->region) {
165 pipe->region_release(pipe, &strb->surface->region);
166 }
167
168 /* Choose a pitch to match hardware requirements:
169 */
170 pitch = ((cpp * width + 63) & ~63) / cpp; /* XXX fix: device-specific */
171
172 strb->surface->region = pipe->region_alloc(pipe, cpp, pitch, height);
173 if (!strb->surface->region)
174 return GL_FALSE; /* out of memory, try s/w buffer? */
175
176 ASSERT(strb->surface->region->buffer);
177
178 strb->Base.Width = strb->surface->width = width;
179 strb->Base.Height = strb->surface->height = height;
180
181 return GL_TRUE;
182 }
183
184
185 /**
186 * gl_renderbuffer::Delete()
187 */
188 static void
189 st_renderbuffer_delete(struct gl_renderbuffer *rb)
190 {
191 GET_CURRENT_CONTEXT(ctx);
192 struct pipe_context *pipe = ctx->st->pipe;
193 struct st_renderbuffer *strb = st_renderbuffer(rb);
194 ASSERT(strb);
195 if (strb && strb->surface) {
196 if (strb->surface->region) {
197 pipe->region_release(pipe, &strb->surface->region);
198 }
199 free(strb->surface);
200 }
201 free(strb);
202 }
203
204
205 /**
206 * gl_renderbuffer::GetPointer()
207 */
208 static void *
209 null_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
210 GLint x, GLint y)
211 {
212 /* By returning NULL we force all software rendering to go through
213 * the span routines.
214 */
215 #if 0
216 assert(0); /* Should never get called with softpipe */
217 #endif
218 return NULL;
219 }
220
221
222 /**
223 * Called via ctx->Driver.NewFramebuffer()
224 */
225 static struct gl_framebuffer *
226 st_new_framebuffer(GLcontext *ctx, GLuint name)
227 {
228 /* XXX not sure we need to subclass gl_framebuffer for pipe */
229 return _mesa_new_framebuffer(ctx, name);
230 }
231
232
233 /**
234 * Called via ctx->Driver.NewRenderbuffer()
235 */
236 static struct gl_renderbuffer *
237 st_new_renderbuffer(GLcontext *ctx, GLuint name)
238 {
239 struct st_renderbuffer *strb = CALLOC_STRUCT(st_renderbuffer);
240 if (strb) {
241 _mesa_init_renderbuffer(&strb->Base, name);
242 strb->Base.Delete = st_renderbuffer_delete;
243 strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
244 strb->Base.GetPointer = null_get_pointer;
245 return &strb->Base;
246 }
247 return NULL;
248 }
249
250
251 #if 000
252 struct gl_renderbuffer *
253 st_new_renderbuffer_fb(struct pipe_region *region, GLuint width, GLuint height)
254 {
255 struct st_renderbuffer *strb = CALLOC_STRUCT(st_renderbuffer);
256 if (!strb)
257 return;
258
259 _mesa_init_renderbuffer(&strb->Base, name);
260 strb->Base.Delete = st_renderbuffer_delete;
261 strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
262 strb->Base.GetPointer = null_get_pointer;
263 strb->Base.Width = width;
264 strb->Base.Heigth = height;
265
266 strb->region = region;
267
268 return &strb->Base;
269 }
270
271 #else
272
273 struct gl_renderbuffer *
274 st_new_renderbuffer_fb(GLenum intFormat)
275 {
276 struct st_renderbuffer *strb;
277
278 strb = CALLOC_STRUCT(st_renderbuffer);
279 if (!strb) {
280 _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
281 return NULL;
282 }
283
284 _mesa_init_renderbuffer(&strb->Base, 0);
285 strb->Base.ClassID = 0x42; /* XXX temp */
286 strb->Base.InternalFormat = intFormat;
287
288 switch (intFormat) {
289 case GL_RGB5:
290 case GL_RGBA8:
291 strb->Base._BaseFormat = GL_RGBA;
292 break;
293 case GL_DEPTH_COMPONENT16:
294 case GL_DEPTH_COMPONENT32:
295 strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
296 break;
297 case GL_DEPTH24_STENCIL8_EXT:
298 strb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
299 break;
300 default:
301 _mesa_problem(NULL,
302 "Unexpected intFormat in st_new_renderbuffer");
303 return NULL;
304 }
305
306 /* st-specific methods */
307 strb->Base.Delete = st_renderbuffer_delete;
308 strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
309 strb->Base.GetPointer = null_get_pointer;
310
311 /* surface is allocate in alloc_renderbuffer_storage() */
312 strb->surface = NULL;
313
314 return &strb->Base;
315 }
316 #endif
317
318
319
320 /**
321 * Called via ctx->Driver.BindFramebufferEXT().
322 */
323 static void
324 st_bind_framebuffer(GLcontext *ctx, GLenum target,
325 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
326 {
327
328 }
329
330 /**
331 * Called by ctx->Driver.FramebufferRenderbuffer
332 */
333 static void
334 st_framebuffer_renderbuffer(GLcontext *ctx,
335 struct gl_framebuffer *fb,
336 GLenum attachment,
337 struct gl_renderbuffer *rb)
338 {
339 /* XXX no need for derivation? */
340 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
341 }
342
343
344 /**
345 * Called by ctx->Driver.RenderTexture
346 */
347 static void
348 st_render_texture(GLcontext *ctx,
349 struct gl_framebuffer *fb,
350 struct gl_renderbuffer_attachment *att)
351 {
352 struct st_context *st = ctx->st;
353 struct pipe_framebuffer_state framebuffer;
354 struct pipe_surface *texsurface;
355
356 texsurface = NULL; /* find the mipmap level, cube face, etc */
357
358 /*
359 * XXX basically like this... set the current color (or depth)
360 * drawing surface to be the given texture renderbuffer.
361 */
362 memset(&framebuffer, 0, sizeof(framebuffer));
363 framebuffer.num_cbufs = 1;
364 framebuffer.cbufs[0] = texsurface;
365
366 if (memcmp(&framebuffer, &st->state.framebuffer, sizeof(framebuffer)) != 0) {
367 st->state.framebuffer = framebuffer;
368 st->pipe->set_framebuffer_state( st->pipe, &framebuffer );
369 }
370 }
371
372
373 /**
374 * Called via ctx->Driver.FinishRenderTexture.
375 */
376 static void
377 st_finish_render_texture(GLcontext *ctx,
378 struct gl_renderbuffer_attachment *att)
379 {
380 /* restore drawing to normal framebuffer. may be a no-op */
381 }
382
383
384
385 void st_init_fbo_functions(struct dd_function_table *functions)
386 {
387 functions->NewFramebuffer = st_new_framebuffer;
388 functions->NewRenderbuffer = st_new_renderbuffer;
389 functions->BindFramebuffer = st_bind_framebuffer;
390 functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
391 functions->RenderTexture = st_render_texture;
392 functions->FinishRenderTexture = st_finish_render_texture;
393 /* no longer needed by core Mesa, drivers handle resizes...
394 functions->ResizeBuffers = st_resize_buffers;
395 */
396 }