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