st_cb_fbo.c revision 5e1bfe426f3e2bc7a13b3814f1fa732141f15a9a
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_texture.h" 47#include "st_format.h" 48#include "st_public.h" 49 50 51 52/** 53 * gl_renderbuffer::AllocStorage() 54 */ 55static GLboolean 56st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, 57 GLenum internalFormat, 58 GLuint width, GLuint height) 59{ 60 struct pipe_context *pipe = ctx->st->pipe; 61 struct st_renderbuffer *strb = st_renderbuffer(rb); 62 const GLuint pipeFormat 63 = st_choose_pipe_format(pipe, internalFormat, GL_NONE, GL_NONE); 64 const struct pipe_format_info *info = st_get_format_info(pipeFormat); 65 GLuint cpp; 66 GLbitfield flags = PIPE_SURFACE_FLAG_RENDER; /* want to render to surface */ 67 68 assert(info); 69 if (!info) 70 return GL_FALSE; 71 72 switch (pipeFormat) { 73 case PIPE_FORMAT_S8_Z24: 74 strb->Base.DataType = GL_UNSIGNED_INT; 75 break; 76 default: 77 strb->Base.DataType = GL_UNSIGNED_BYTE; /* XXX fix */ 78 } 79 80 strb->Base._ActualFormat = info->base_format; 81 strb->Base.RedBits = info->red_bits; 82 strb->Base.GreenBits = info->green_bits; 83 strb->Base.BlueBits = info->blue_bits; 84 strb->Base.AlphaBits = info->alpha_bits; 85 strb->Base.DepthBits = info->depth_bits; 86 strb->Base.StencilBits = info->stencil_bits; 87 88 cpp = info->size; 89 90 if (!strb->surface) { 91 strb->surface = pipe->surface_alloc(pipe, pipeFormat); 92 assert(strb->surface); 93 if (!strb->surface) 94 return GL_FALSE; 95 } 96 97 /* free old region */ 98 if (strb->surface->region) { 99 pipe->region_release(pipe, &strb->surface->region); 100 } 101 102 strb->surface->region = pipe->region_alloc(pipe, cpp, width, height, flags); 103 if (!strb->surface->region) 104 return GL_FALSE; /* out of memory, try s/w buffer? */ 105 106 ASSERT(strb->surface->region->buffer); 107 108 strb->Base.Width = strb->surface->width = width; 109 strb->Base.Height = strb->surface->height = height; 110 111 return GL_TRUE; 112} 113 114 115/** 116 * gl_renderbuffer::Delete() 117 */ 118static void 119st_renderbuffer_delete(struct gl_renderbuffer *rb) 120{ 121 struct st_renderbuffer *strb = st_renderbuffer(rb); 122 GET_CURRENT_CONTEXT(ctx); 123 if (ctx) { 124 struct pipe_context *pipe = ctx->st->pipe; 125 ASSERT(strb); 126 if (strb && strb->surface) { 127 if (strb->surface->region) { 128 pipe->region_release(pipe, &strb->surface->region); 129 } 130 free(strb->surface); 131 } 132 } 133 else { 134 _mesa_warning(NULL, "st_renderbuffer_delete() called, but no current context"); 135 } 136 free(strb); 137} 138 139 140/** 141 * gl_renderbuffer::GetPointer() 142 */ 143static void * 144null_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb, 145 GLint x, GLint y) 146{ 147 /* By returning NULL we force all software rendering to go through 148 * the span routines. 149 */ 150#if 0 151 assert(0); /* Should never get called with softpipe */ 152#endif 153 return NULL; 154} 155 156 157/** 158 * Called via ctx->Driver.NewFramebuffer() 159 */ 160static struct gl_framebuffer * 161st_new_framebuffer(GLcontext *ctx, GLuint name) 162{ 163 /* XXX not sure we need to subclass gl_framebuffer for pipe */ 164 return _mesa_new_framebuffer(ctx, name); 165} 166 167 168/** 169 * Called via ctx->Driver.NewRenderbuffer() 170 */ 171static struct gl_renderbuffer * 172st_new_renderbuffer(GLcontext *ctx, GLuint name) 173{ 174 struct st_renderbuffer *strb = CALLOC_STRUCT(st_renderbuffer); 175 if (strb) { 176 _mesa_init_renderbuffer(&strb->Base, name); 177 strb->Base.Delete = st_renderbuffer_delete; 178 strb->Base.AllocStorage = st_renderbuffer_alloc_storage; 179 strb->Base.GetPointer = null_get_pointer; 180 return &strb->Base; 181 } 182 return NULL; 183} 184 185 186#if 000 187struct gl_renderbuffer * 188st_new_renderbuffer_fb(struct pipe_region *region, GLuint width, GLuint height) 189{ 190 struct st_renderbuffer *strb = CALLOC_STRUCT(st_renderbuffer); 191 if (!strb) 192 return; 193 194 _mesa_init_renderbuffer(&strb->Base, name); 195 strb->Base.Delete = st_renderbuffer_delete; 196 strb->Base.AllocStorage = st_renderbuffer_alloc_storage; 197 strb->Base.GetPointer = null_get_pointer; 198 strb->Base.Width = width; 199 strb->Base.Heigth = height; 200 201 strb->region = region; 202 203 return &strb->Base; 204} 205 206#else 207 208struct gl_renderbuffer * 209st_new_renderbuffer_fb(GLenum intFormat) 210{ 211 struct st_renderbuffer *strb; 212 213 strb = CALLOC_STRUCT(st_renderbuffer); 214 if (!strb) { 215 _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer"); 216 return NULL; 217 } 218 219 _mesa_init_renderbuffer(&strb->Base, 0); 220 strb->Base.ClassID = 0x42; /* XXX temp */ 221 strb->Base.InternalFormat = intFormat; 222 223 switch (intFormat) { 224 case GL_RGB5: 225 case GL_RGBA8: 226 strb->Base._BaseFormat = GL_RGBA; 227 break; 228 case GL_DEPTH_COMPONENT16: 229 case GL_DEPTH_COMPONENT32: 230 strb->Base._BaseFormat = GL_DEPTH_COMPONENT; 231 break; 232 case GL_DEPTH24_STENCIL8_EXT: 233 strb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT; 234 break; 235 default: 236 _mesa_problem(NULL, 237 "Unexpected intFormat in st_new_renderbuffer"); 238 return NULL; 239 } 240 241 /* st-specific methods */ 242 strb->Base.Delete = st_renderbuffer_delete; 243 strb->Base.AllocStorage = st_renderbuffer_alloc_storage; 244 strb->Base.GetPointer = null_get_pointer; 245 246 /* surface is allocate in alloc_renderbuffer_storage() */ 247 strb->surface = NULL; 248 249 return &strb->Base; 250} 251#endif 252 253 254 255/** 256 * Called via ctx->Driver.BindFramebufferEXT(). 257 */ 258static void 259st_bind_framebuffer(GLcontext *ctx, GLenum target, 260 struct gl_framebuffer *fb, struct gl_framebuffer *fbread) 261{ 262 263} 264 265/** 266 * Called by ctx->Driver.FramebufferRenderbuffer 267 */ 268static void 269st_framebuffer_renderbuffer(GLcontext *ctx, 270 struct gl_framebuffer *fb, 271 GLenum attachment, 272 struct gl_renderbuffer *rb) 273{ 274 /* XXX no need for derivation? */ 275 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); 276} 277 278 279/** 280 * Called by ctx->Driver.RenderTexture 281 */ 282static void 283st_render_texture(GLcontext *ctx, 284 struct gl_framebuffer *fb, 285 struct gl_renderbuffer_attachment *att) 286{ 287 struct st_context *st = ctx->st; 288 struct st_renderbuffer *strb; 289 struct gl_renderbuffer *rb; 290 struct pipe_context *pipe = st->pipe; 291 struct pipe_framebuffer_state framebuffer; 292 struct pipe_mipmap_tree *mt; 293 294 assert(!att->Renderbuffer); 295 296 /* create new renderbuffer which wraps the texture image */ 297 rb = st_new_renderbuffer(ctx, 0); 298 if (!rb) { 299 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()"); 300 return; 301 } 302 303 _mesa_reference_renderbuffer(&att->Renderbuffer, rb); 304 assert(rb->RefCount == 1); 305 rb->AllocStorage = NULL; /* should not get called */ 306 strb = st_renderbuffer(rb); 307 308 /* get the mipmap tree for the texture */ 309 mt = st_get_texobj_mipmap_tree(att->Texture); 310 assert(mt); 311 assert(mt->level[0].width); 312 313 /* the renderbuffer's surface is inside the mipmap_tree: */ 314 strb->surface = pipe->get_tex_surface(pipe, mt, 315 att->CubeMapFace, 316 att->TextureLevel, 317 att->Zoffset); 318 assert(strb->surface); 319 320 /* 321 printf("RENDER TO TEXTURE mt=%p surf=%p\n", mt, strb->surface); 322 */ 323 324 /* Invalidate buffer state so that the pipe's framebuffer state 325 * gets updated. 326 * That's where the new renderbuffer (which we just created) gets 327 * passed to the pipe as a (color/depth) render target. 328 */ 329 st_invalidate_state(ctx, _NEW_BUFFERS); 330} 331 332 333/** 334 * Called via ctx->Driver.FinishRenderTexture. 335 */ 336static void 337st_finish_render_texture(GLcontext *ctx, 338 struct gl_renderbuffer_attachment *att) 339{ 340 struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer); 341 342 assert(strb); 343 344 /* 345 printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface); 346 */ 347 348 pipe_surface_unreference(&strb->surface); 349 350 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 351 352 /* restore previous framebuffer state */ 353 st_invalidate_state(ctx, _NEW_BUFFERS); 354} 355 356 357 358void st_init_fbo_functions(struct dd_function_table *functions) 359{ 360 functions->NewFramebuffer = st_new_framebuffer; 361 functions->NewRenderbuffer = st_new_renderbuffer; 362 functions->BindFramebuffer = st_bind_framebuffer; 363 functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer; 364 functions->RenderTexture = st_render_texture; 365 functions->FinishRenderTexture = st_finish_render_texture; 366 /* no longer needed by core Mesa, drivers handle resizes... 367 functions->ResizeBuffers = st_resize_buffers; 368 */ 369} 370